tmp41wklro_/0000755000175000001440000000000014706262455014156 5ustar nabijaczleweliuserstmp41wklro_/Asm/0000700000175000001440000000000014706260545014662 5ustar nabijaczleweliuserstmp41wklro_/Asm/arm/0000700000175000001440000000000014706260545015441 5ustar nabijaczleweliuserstmp41wklro_/Asm/arm/7zCrcOpt.asm0000444000175000001440000000267211263326340017624 0ustar nabijaczleweliusers CODE32 EXPORT |CrcUpdateT4@16| AREA |.text|, CODE, ARM MACRO CRC32_STEP_1 ldrb r4, [r1], #1 subs r2, r2, #1 eor r4, r4, r0 and r4, r4, #0xFF ldr r4, [r3, +r4, lsl #2] eor r0, r4, r0, lsr #8 MEND MACRO CRC32_STEP_4 $STREAM_WORD eor r7, r7, r8 eor r7, r7, r9 eor r0, r0, r7 eor r0, r0, $STREAM_WORD ldr $STREAM_WORD, [r1], #4 and r7, r0, #0xFF and r8, r0, #0xFF00 and r9, r0, #0xFF0000 and r0, r0, #0xFF000000 ldr r7, [r6, +r7, lsl #2] ldr r8, [r5, +r8, lsr #6] ldr r9, [r4, +r9, lsr #14] ldr r0, [r3, +r0, lsr #22] MEND |CrcUpdateT4@16| PROC stmdb sp!, {r4-r11, lr} cmp r2, #0 beq |$fin| |$v1| tst r1, #7 beq |$v2| CRC32_STEP_1 bne |$v1| |$v2| cmp r2, #16 blo |$v3| ldr r10, [r1], #4 ldr r11, [r1], #4 add r4, r3, #0x400 add r5, r3, #0x800 add r6, r3, #0xC00 mov r7, #0 mov r8, #0 mov r9, #0 sub r2, r2, #16 |$loop| ; pld [r1, #0x40] CRC32_STEP_4 r10 CRC32_STEP_4 r11 subs r2, r2, #8 bhs |$loop| sub r1, r1, #8 add r2, r2, #16 eor r7, r7, r8 eor r7, r7, r9 eor r0, r0, r7 |$v3| cmp r2, #0 beq |$fin| |$v4| CRC32_STEP_1 bne |$v4| |$fin| ldmia sp!, {r4-r11, pc} |CrcUpdateT4@16| ENDP END tmp41wklro_/Asm/arm64/0000700000175000001440000000000014706260545015613 5ustar nabijaczleweliuserstmp41wklro_/Asm/arm64/7zAsm.S0000444000175000001440000000611214041327040016732 0ustar nabijaczleweliusers// 7zAsm.S -- ASM macros for arm64 // 2021-04-25 : Igor Pavlov : Public domain #define r0 x0 #define r1 x1 #define r2 x2 #define r3 x3 #define r4 x4 #define r5 x5 #define r6 x6 #define r7 x7 #define r8 x8 #define r9 x9 #define r10 x10 #define r11 x11 #define r12 x12 #define r13 x13 #define r14 x14 #define r15 x15 #define r16 x16 #define r17 x17 #define r18 x18 #define r19 x19 #define r20 x20 #define r21 x21 #define r22 x22 #define r23 x23 #define r24 x24 #define r25 x25 #define r26 x26 #define r27 x27 #define r28 x28 #define r29 x29 #define r30 x30 #define REG_ABI_PARAM_0 r0 #define REG_ABI_PARAM_1 r1 #define REG_ABI_PARAM_2 r2 .macro p2_add reg:req, param:req add \reg, \reg, \param .endm .macro p2_sub reg:req, param:req sub \reg, \reg, \param .endm .macro p2_sub_s reg:req, param:req subs \reg, \reg, \param .endm .macro p2_and reg:req, param:req and \reg, \reg, \param .endm .macro xor reg:req, param:req eor \reg, \reg, \param .endm .macro or reg:req, param:req orr \reg, \reg, \param .endm .macro shl reg:req, param:req lsl \reg, \reg, \param .endm .macro shr reg:req, param:req lsr \reg, \reg, \param .endm .macro sar reg:req, param:req asr \reg, \reg, \param .endm .macro p1_neg reg:req neg \reg, \reg .endm .macro dec reg:req sub \reg, \reg, 1 .endm .macro dec_s reg:req subs \reg, \reg, 1 .endm .macro inc reg:req add \reg, \reg, 1 .endm .macro inc_s reg:req adds \reg, \reg, 1 .endm .macro imul reg:req, param:req mul \reg, \reg, \param .endm /* arm64 and arm use reverted c flag after subs/cmp instructions: arm64-arm : x86 b.lo / b.cc : jb / jc b.hs / b.cs : jae / jnc */ .macro jmp lab:req b \lab .endm .macro je lab:req b.eq \lab .endm .macro jz lab:req b.eq \lab .endm .macro jnz lab:req b.ne \lab .endm .macro jne lab:req b.ne \lab .endm .macro jb lab:req b.lo \lab .endm .macro jbe lab:req b.ls \lab .endm .macro ja lab:req b.hi \lab .endm .macro jae lab:req b.hs \lab .endm .macro cmove dest:req, srcTrue:req csel \dest, \srcTrue, \dest, eq .endm .macro cmovne dest:req, srcTrue:req csel \dest, \srcTrue, \dest, ne .endm .macro cmovs dest:req, srcTrue:req csel \dest, \srcTrue, \dest, mi .endm .macro cmovns dest:req, srcTrue:req csel \dest, \srcTrue, \dest, pl .endm .macro cmovb dest:req, srcTrue:req csel \dest, \srcTrue, \dest, lo .endm .macro cmovae dest:req, srcTrue:req csel \dest, \srcTrue, \dest, hs .endm .macro MY_ALIGN_16 macro .p2align 4,, (1 << 4) - 1 .endm .macro MY_ALIGN_32 macro .p2align 5,, (1 << 5) - 1 .endm .macro MY_ALIGN_64 macro .p2align 6,, (1 << 6) - 1 .endm tmp41wklro_/Asm/arm64/LzmaDecOpt.S0000444000175000001440000011157514041327040017745 0ustar nabijaczleweliusers// LzmaDecOpt.S -- ARM64-ASM version of LzmaDec_DecodeReal_3() function // 2021-04-25 : Igor Pavlov : Public domain /* ; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() ; function for check at link time. ; That code is tightly coupled with LzmaDec_TryDummy() ; and with another functions in LzmaDec.c file. ; CLzmaDec structure, (probs) array layout, input and output of ; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). */ #include "7zAsm.S" // .arch armv8-a // .file "LzmaDecOpt.c" .text .align 2 .p2align 4,,15 #ifdef __APPLE__ .globl _LzmaDec_DecodeReal_3 #else .global LzmaDec_DecodeReal_3 #endif // .type LzmaDec_DecodeReal_3, %function // #define _LZMA_SIZE_OPT 1 #define LZMA_USE_4BYTES_FILL 1 // #define LZMA_USE_2BYTES_COPY 1 // #define LZMA_USE_CMOV_LZ_WRAP 1 // #define _LZMA_PROB32 1 #define MY_ALIGN_FOR_ENTRY MY_ALIGN_32 #define MY_ALIGN_FOR_LOOP MY_ALIGN_32 #define MY_ALIGN_FOR_LOOP_16 MY_ALIGN_16 #ifdef _LZMA_PROB32 .equ PSHIFT , 2 .macro PLOAD dest:req, mem:req ldr \dest, [\mem] .endm .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req ldr \dest, [\mem, \offset]! .endm .macro PLOAD_2 dest:req, mem1:req, mem2:req ldr \dest, [\mem1, \mem2] .endm .macro PLOAD_LSL dest:req, mem1:req, mem2:req ldr \dest, [\mem1, \mem2, lsl #PSHIFT] .endm .macro PSTORE src:req, mem:req str \src, [\mem] .endm .macro PSTORE_2 src:req, mem1:req, mem2:req str \src, [\mem1, \mem2] .endm .macro PSTORE_LSL src:req, mem1:req, mem2:req str \src, [\mem1, \mem2, lsl #PSHIFT] .endm .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req // you must check that temp_reg is free register when macro is used add \temp_reg, \mem1, \mem2 str \src, [\temp_reg, \mem2] .endm #else // .equ PSHIFT , 1 #define PSHIFT 1 .macro PLOAD dest:req, mem:req ldrh \dest, [\mem] .endm .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req ldrh \dest, [\mem, \offset]! .endm .macro PLOAD_2 dest:req, mem1:req, mem2:req ldrh \dest, [\mem1, \mem2] .endm .macro PLOAD_LSL dest:req, mem1:req, mem2:req ldrh \dest, [\mem1, \mem2, lsl #PSHIFT] .endm .macro PSTORE src:req, mem:req strh \src, [\mem] .endm .macro PSTORE_2 src:req, mem1:req, mem2:req strh \src, [\mem1, \mem2] .endm .macro PSTORE_LSL src:req, mem1:req, mem2:req strh \src, [\mem1, \mem2, lsl #PSHIFT] .endm .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req strh \src, [\mem1, \mem2] .endm #endif .equ PMULT , (1 << PSHIFT) .equ PMULT_2 , (2 << PSHIFT) .equ kMatchSpecLen_Error_Data , (1 << 9) # x7 t0 : NORM_CALC : prob2 (IF_BIT_1) # x6 t1 : NORM_CALC : probs_state # x8 t2 : (LITM) temp : (TREE) temp # x4 t3 : (LITM) bit : (TREE) temp : UPDATE_0/UPDATE_0 temp # x10 t4 : (LITM) offs : (TREE) probs_PMULT : numBits # x9 t5 : (LITM) match : sym2 (ShortDist) # x1 t6 : (LITM) litm_prob : (TREE) prob_reg : pbPos # x2 t7 : (LITM) prm : probBranch : cnt # x3 sym : dist # x12 len # x0 range # x5 cod #define range w0 // t6 #define pbPos w1 #define pbPos_R r1 #define prob_reg w1 #define litm_prob prob_reg // t7 #define probBranch w2 #define cnt w2 #define cnt_R r2 #define prm r2 #define sym w3 #define sym_R r3 #define dist sym #define t3 w4 #define bit w4 #define bit_R r4 #define update_temp_reg r4 #define cod w5 #define t1 w6 #define t1_R r6 #define probs_state t1_R #define t0 w7 #define t0_R r7 #define prob2 t0 #define t2 w8 #define t2_R r8 // t5 #define match w9 #define sym2 w9 #define sym2_R r9 #define t4 w10 #define t4_R r10 #define offs w10 #define offs_R r10 #define probs r11 #define len w12 #define len_R x12 #define state w13 #define state_R r13 #define dicPos r14 #define buf r15 #define bufLimit r16 #define dicBufSize r17 #define limit r19 #define rep0 w20 #define rep0_R r20 #define rep1 w21 #define rep2 w22 #define rep3 w23 #define dic r24 #define probs_IsMatch r25 #define probs_Spec r26 #define checkDicSize w27 #define processedPos w28 #define pbMask w29 #define lc2_lpMask w30 .equ kNumBitModelTotalBits , 11 .equ kBitModelTotal , (1 << kNumBitModelTotalBits) .equ kNumMoveBits , 5 .equ kBitModelOffset , (kBitModelTotal - (1 << kNumMoveBits) + 1) .macro NORM_2 macro ldrb t0, [buf], 1 shl range, 8 orr cod, t0, cod, lsl 8 /* mov t0, cod ldrb cod, [buf], 1 shl range, 8 bfi cod, t0, #8, #24 */ .endm .macro TEST_HIGH_BYTE_range macro tst range, 0xFF000000 .endm .macro NORM macro TEST_HIGH_BYTE_range jnz 1f NORM_2 1: .endm # ---------- Branch MACROS ---------- .macro UPDATE_0__0 sub prob2, probBranch, kBitModelOffset .endm .macro UPDATE_0__1 sub probBranch, probBranch, prob2, asr #(kNumMoveBits) .endm .macro UPDATE_0__2 probsArray:req, probOffset:req, probDisp:req .if \probDisp == 0 PSTORE_2 probBranch, \probsArray, \probOffset .elseif \probOffset == 0 PSTORE_2 probBranch, \probsArray, \probDisp * PMULT .else .error "unsupported" // add update_temp_reg, \probsArray, \probOffset PSTORE_2 probBranch, update_temp_reg, \probDisp * PMULT .endif .endm .macro UPDATE_0 probsArray:req, probOffset:req, probDisp:req UPDATE_0__0 UPDATE_0__1 UPDATE_0__2 \probsArray, \probOffset, \probDisp .endm .macro UPDATE_1 probsArray:req, probOffset:req, probDisp:req // sub cod, cod, prob2 // sub range, range, prob2 p2_sub cod, range sub range, prob2, range sub prob2, probBranch, probBranch, lsr #(kNumMoveBits) .if \probDisp == 0 PSTORE_2 prob2, \probsArray, \probOffset .elseif \probOffset == 0 PSTORE_2 prob2, \probsArray, \probDisp * PMULT .else .error "unsupported" // add update_temp_reg, \probsArray, \probOffset PSTORE_2 prob2, update_temp_reg, \probDisp * PMULT .endif .endm .macro CMP_COD_BASE NORM // lsr prob2, range, kNumBitModelTotalBits // imul prob2, probBranch // cmp cod, prob2 mov prob2, range shr range, kNumBitModelTotalBits imul range, probBranch cmp cod, range .endm .macro CMP_COD_1 probsArray:req PLOAD probBranch, \probsArray CMP_COD_BASE .endm .macro CMP_COD_3 probsArray:req, probOffset:req, probDisp:req .if \probDisp == 0 PLOAD_2 probBranch, \probsArray, \probOffset .elseif \probOffset == 0 PLOAD_2 probBranch, \probsArray, \probDisp * PMULT .else .error "unsupported" add update_temp_reg, \probsArray, \probOffset PLOAD_2 probBranch, update_temp_reg, \probDisp * PMULT .endif CMP_COD_BASE .endm .macro IF_BIT_1_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req CMP_COD_3 \probsArray, \probOffset, \probDisp jae \toLabel .endm .macro IF_BIT_1 probsArray:req, probOffset:req, probDisp:req, toLabel:req IF_BIT_1_NOUP \probsArray, \probOffset, \probDisp, \toLabel UPDATE_0 \probsArray, \probOffset, \probDisp .endm .macro IF_BIT_0_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req CMP_COD_3 \probsArray, \probOffset, \probDisp jb \toLabel .endm .macro IF_BIT_0_NOUP_1 probsArray:req, toLabel:req CMP_COD_1 \probsArray jb \toLabel .endm # ---------- CMOV MACROS ---------- .macro NORM_LSR NORM lsr t0, range, #kNumBitModelTotalBits .endm .macro COD_RANGE_SUB subs t1, cod, t0 p2_sub range, t0 .endm .macro RANGE_IMUL prob:req imul t0, \prob .endm .macro NORM_CALC prob:req NORM_LSR RANGE_IMUL \prob COD_RANGE_SUB .endm .macro CMOV_range cmovb range, t0 .endm .macro CMOV_code cmovae cod, t1 .endm .macro CMOV_code_Model_Pre prob:req sub t0, \prob, kBitModelOffset CMOV_code cmovae t0, \prob .endm .macro PUP_BASE_2 prob:req, dest_reg:req # only sar works for both 16/32 bit prob modes sub \dest_reg, \prob, \dest_reg, asr #(kNumMoveBits) .endm .macro PUP prob:req, probPtr:req, mem2:req PUP_BASE_2 \prob, t0 PSTORE_2 t0, \probPtr, \mem2 .endm #define probs_PMULT t4_R .macro BIT_01 add probs_PMULT, probs, PMULT .endm .macro BIT_0_R prob:req PLOAD_2 \prob, probs, 1 * PMULT NORM_LSR sub t3, \prob, kBitModelOffset RANGE_IMUL \prob PLOAD_2 t2, probs, 1 * PMULT_2 COD_RANGE_SUB CMOV_range cmovae t3, \prob PLOAD_2 t0, probs, 1 * PMULT_2 + PMULT PUP_BASE_2 \prob, t3 csel \prob, t2, t0, lo CMOV_code mov sym, 2 PSTORE_2 t3, probs, 1 * PMULT adc sym, sym, wzr BIT_01 .endm .macro BIT_1_R prob:req NORM_LSR p2_add sym, sym sub t3, \prob, kBitModelOffset RANGE_IMUL \prob PLOAD_LSL t2, probs, sym_R COD_RANGE_SUB CMOV_range cmovae t3, \prob PLOAD_LSL t0, probs_PMULT, sym_R PUP_BASE_2 \prob, t3 csel \prob, t2, t0, lo CMOV_code PSTORE_LSL_M1 t3, probs, sym_R, t2_R adc sym, sym, wzr .endm .macro BIT_2_R prob:req NORM_LSR p2_add sym, sym sub t3, \prob, kBitModelOffset RANGE_IMUL \prob COD_RANGE_SUB CMOV_range cmovae t3, \prob CMOV_code PUP_BASE_2 \prob, t3 PSTORE_LSL_M1 t3, probs, sym_R, t2_R adc sym, sym, wzr .endm # ---------- MATCHED LITERAL ---------- .macro LITM_0 macro shl match, (PSHIFT + 1) and bit, match, 256 * PMULT add prm, probs, 256 * PMULT + 1 * PMULT p2_add match, match p2_add prm, bit_R eor offs, bit, 256 * PMULT PLOAD litm_prob, prm NORM_LSR sub t2, litm_prob, kBitModelOffset RANGE_IMUL litm_prob COD_RANGE_SUB cmovae offs, bit CMOV_range and bit, match, offs cmovae t2, litm_prob CMOV_code mov sym, 2 PUP_BASE_2 litm_prob, t2 PSTORE t2, prm add prm, probs, offs_R adc sym, sym, wzr .endm .macro LITM macro p2_add prm, bit_R xor offs, bit PLOAD_LSL litm_prob, prm, sym_R NORM_LSR p2_add match, match sub t2, litm_prob, kBitModelOffset RANGE_IMUL litm_prob COD_RANGE_SUB cmovae offs, bit CMOV_range and bit, match, offs cmovae t2, litm_prob CMOV_code PUP_BASE_2 litm_prob, t2 PSTORE_LSL t2, prm, sym_R add prm, probs, offs_R adc sym, sym, sym .endm .macro LITM_2 macro p2_add prm, bit_R PLOAD_LSL litm_prob, prm, sym_R NORM_LSR sub t2, litm_prob, kBitModelOffset RANGE_IMUL litm_prob COD_RANGE_SUB CMOV_range cmovae t2, litm_prob CMOV_code PUP_BASE_2 litm_prob, t2 PSTORE_LSL t2, prm, sym_R adc sym, sym, sym .endm # ---------- REVERSE BITS ---------- .macro REV_0 prob:req NORM_CALC \prob CMOV_range PLOAD t2, sym2_R PLOAD_2 t3, probs, 3 * PMULT CMOV_code_Model_Pre \prob add t1_R, probs, 3 * PMULT cmovae sym2_R, t1_R PUP \prob, probs, 1 * PMULT csel \prob, t2, t3, lo .endm .macro REV_1 prob:req, step:req NORM_LSR PLOAD_PREINDEXED t2, sym2_R, (\step * PMULT) RANGE_IMUL \prob COD_RANGE_SUB CMOV_range PLOAD_2 t3, sym2_R, (\step * PMULT) sub t0, \prob, kBitModelOffset CMOV_code add t1_R, sym2_R, \step * PMULT cmovae t0, \prob cmovae sym2_R, t1_R PUP_BASE_2 \prob, t0 csel \prob, t2, t3, lo PSTORE_2 t0, t1_R, 0 - \step * PMULT_2 .endm .macro REV_2 prob:req, step:req sub t1_R, sym2_R, probs NORM_LSR orr sym, sym, t1, lsr #PSHIFT RANGE_IMUL \prob COD_RANGE_SUB sub t2, sym, \step CMOV_range cmovb sym, t2 CMOV_code_Model_Pre \prob PUP \prob, sym2_R, 0 .endm .macro REV_1_VAR prob:req PLOAD \prob, sym_R mov probs, sym_R p2_add sym_R, sym2_R NORM_LSR add t2_R, sym_R, sym2_R RANGE_IMUL \prob COD_RANGE_SUB cmovae sym_R, t2_R CMOV_range CMOV_code_Model_Pre \prob p2_add sym2, sym2 PUP \prob, probs, 0 .endm .macro add_big dest:req, src:req, param:req .if (\param) < (1 << 12) add \dest, \src, \param .else #ifndef _LZMA_PROB32 .error "unexpcted add_big expansion" #endif add \dest, \src, (\param) / 2 add \dest, \dest, (\param) - (\param) / 2 .endif .endm .macro sub_big dest:req, src:req, param:req .if (\param) < (1 << 12) sub \dest, \src, \param .else #ifndef _LZMA_PROB32 .error "unexpcted sub_big expansion" #endif sub \dest, \src, (\param) / 2 sub \dest, \dest, (\param) - (\param) / 2 .endif .endm .macro SET_probs offset:req // add_big probs, probs_Spec, (\offset) * PMULT add probs, probs_IsMatch, ((\offset) - IsMatch) * PMULT .endm .macro LIT_PROBS add sym, sym, processedPos, lsl 8 inc processedPos UPDATE_0__0 shl sym, lc2_lpMask SET_probs Literal p2_and sym, lc2_lpMask // p2_add probs_state, pbPos_R p2_add probs, sym_R UPDATE_0__1 add probs, probs, sym_R, lsl 1 UPDATE_0__2 probs_state, pbPos_R, 0 .endm .equ kNumPosBitsMax , 4 .equ kNumPosStatesMax , (1 << kNumPosBitsMax) .equ kLenNumLowBits , 3 .equ kLenNumLowSymbols , (1 << kLenNumLowBits) .equ kLenNumHighBits , 8 .equ kLenNumHighSymbols , (1 << kLenNumHighBits) .equ kNumLenProbs , (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) .equ LenLow , 0 .equ LenChoice , LenLow .equ LenChoice2 , (LenLow + kLenNumLowSymbols) .equ LenHigh , (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) .equ kNumStates , 12 .equ kNumStates2 , 16 .equ kNumLitStates , 7 .equ kStartPosModelIndex , 4 .equ kEndPosModelIndex , 14 .equ kNumFullDistances , (1 << (kEndPosModelIndex >> 1)) .equ kNumPosSlotBits , 6 .equ kNumLenToPosStates , 4 .equ kNumAlignBits , 4 .equ kAlignTableSize , (1 << kNumAlignBits) .equ kMatchMinLen , 2 .equ kMatchSpecLenStart , (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) // .equ kStartOffset , 1408 .equ kStartOffset , 0 .equ SpecPos , (-kStartOffset) .equ IsRep0Long , (SpecPos + kNumFullDistances) .equ RepLenCoder , (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) .equ LenCoder , (RepLenCoder + kNumLenProbs) .equ IsMatch , (LenCoder + kNumLenProbs) .equ kAlign , (IsMatch + (kNumStates2 << kNumPosBitsMax)) .equ IsRep , (kAlign + kAlignTableSize) .equ IsRepG0 , (IsRep + kNumStates) .equ IsRepG1 , (IsRepG0 + kNumStates) .equ IsRepG2 , (IsRepG1 + kNumStates) .equ PosSlot , (IsRepG2 + kNumStates) .equ Literal , (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) .equ NUM_BASE_PROBS , (Literal + kStartOffset) .if kStartOffset != 0 // && IsMatch != 0 .error "Stop_Compiling_Bad_StartOffset" .endif .if NUM_BASE_PROBS != 1984 .error "Stop_Compiling_Bad_LZMA_PROBS" .endif .equ offset_lc , 0 .equ offset_lp , 1 .equ offset_pb , 2 .equ offset_dicSize , 4 .equ offset_probs , 4 + offset_dicSize .equ offset_probs_1664 , 8 + offset_probs .equ offset_dic , 8 + offset_probs_1664 .equ offset_dicBufSize , 8 + offset_dic .equ offset_dicPos , 8 + offset_dicBufSize .equ offset_buf , 8 + offset_dicPos .equ offset_range , 8 + offset_buf .equ offset_code , 4 + offset_range .equ offset_processedPos , 4 + offset_code .equ offset_checkDicSize , 4 + offset_processedPos .equ offset_rep0 , 4 + offset_checkDicSize .equ offset_rep1 , 4 + offset_rep0 .equ offset_rep2 , 4 + offset_rep1 .equ offset_rep3 , 4 + offset_rep2 .equ offset_state , 4 + offset_rep3 .equ offset_remainLen , 4 + offset_state .equ offset_TOTAL_SIZE , 4 + offset_remainLen .if offset_TOTAL_SIZE != 96 .error "Incorrect offset_TOTAL_SIZE" .endif .macro IsMatchBranch_Pre # prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; and pbPos, pbMask, processedPos, lsl #(kLenNumLowBits + 1 + PSHIFT) add probs_state, probs_IsMatch, state_R .endm /* .macro IsMatchBranch IsMatchBranch_Pre IF_BIT_1 probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label .endm */ .macro CheckLimits cmp buf, bufLimit jae fin_OK cmp dicPos, limit jae fin_OK .endm #define CheckLimits_lit CheckLimits /* .macro CheckLimits_lit cmp buf, bufLimit jae fin_OK_lit cmp dicPos, limit jae fin_OK_lit .endm */ #define PARAM_lzma REG_ABI_PARAM_0 #define PARAM_limit REG_ABI_PARAM_1 #define PARAM_bufLimit REG_ABI_PARAM_2 .macro LOAD_LZMA_VAR reg:req, struct_offs:req ldr \reg, [PARAM_lzma, \struct_offs] .endm .macro LOAD_LZMA_BYTE reg:req, struct_offs:req ldrb \reg, [PARAM_lzma, \struct_offs] .endm .macro LOAD_LZMA_PAIR reg0:req, reg1:req, struct_offs:req ldp \reg0, \reg1, [PARAM_lzma, \struct_offs] .endm LzmaDec_DecodeReal_3: _LzmaDec_DecodeReal_3: /* .LFB0: .cfi_startproc */ stp x19, x20, [sp, -128]! stp x21, x22, [sp, 16] stp x23, x24, [sp, 32] stp x25, x26, [sp, 48] stp x27, x28, [sp, 64] stp x29, x30, [sp, 80] str PARAM_lzma, [sp, 120] mov bufLimit, PARAM_bufLimit mov limit, PARAM_limit LOAD_LZMA_PAIR dic, dicBufSize, offset_dic LOAD_LZMA_PAIR dicPos, buf, offset_dicPos LOAD_LZMA_PAIR rep0, rep1, offset_rep0 LOAD_LZMA_PAIR rep2, rep3, offset_rep2 mov t0, 1 << (kLenNumLowBits + 1 + PSHIFT) LOAD_LZMA_BYTE pbMask, offset_pb p2_add limit, dic mov len, wzr // we can set it in all requiread branches instead lsl pbMask, t0, pbMask p2_add dicPos, dic p2_sub pbMask, t0 LOAD_LZMA_BYTE lc2_lpMask, offset_lc mov t0, 256 << PSHIFT LOAD_LZMA_BYTE t1, offset_lp p2_add t1, lc2_lpMask p2_sub lc2_lpMask, (256 << PSHIFT) - PSHIFT shl t0, t1 p2_add lc2_lpMask, t0 LOAD_LZMA_VAR probs_Spec, offset_probs LOAD_LZMA_VAR checkDicSize, offset_checkDicSize LOAD_LZMA_VAR processedPos, offset_processedPos LOAD_LZMA_VAR state, offset_state // range is r0 : this load must be last don't move LOAD_LZMA_PAIR range, cod, offset_range mov sym, wzr shl state, PSHIFT add_big probs_IsMatch, probs_Spec, ((IsMatch - SpecPos) << PSHIFT) // if (processedPos != 0 || checkDicSize != 0) orr t0, checkDicSize, processedPos cbz t0, 1f add t0_R, dicBufSize, dic cmp dicPos, dic cmovne t0_R, dicPos ldrb sym, [t0_R, -1] 1: IsMatchBranch_Pre cmp state, 4 * PMULT jb lit_end cmp state, kNumLitStates * PMULT jb lit_matched_end jmp lz_end #define BIT_0 BIT_0_R prob_reg #define BIT_1 BIT_1_R prob_reg #define BIT_2 BIT_2_R prob_reg # ---------- LITERAL ---------- MY_ALIGN_64 lit_start: mov state, wzr lit_start_2: LIT_PROBS #ifdef _LZMA_SIZE_OPT PLOAD_2 prob_reg, probs, 1 * PMULT mov sym, 1 BIT_01 MY_ALIGN_FOR_LOOP lit_loop: BIT_1 tbz sym, 7, lit_loop #else BIT_0 BIT_1 BIT_1 BIT_1 BIT_1 BIT_1 BIT_1 #endif BIT_2 IsMatchBranch_Pre strb sym, [dicPos], 1 p2_and sym, 255 CheckLimits_lit lit_end: IF_BIT_0_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), lit_start # jmp IsMatch_label #define FLAG_STATE_BITS (4 + PSHIFT) # ---------- MATCHES ---------- # MY_ALIGN_FOR_ENTRY IsMatch_label: UPDATE_1 probs_state, pbPos_R, (IsMatch - IsMatch) IF_BIT_1 probs_state, 0, (IsRep - IsMatch), IsRep_label SET_probs LenCoder or state, (1 << FLAG_STATE_BITS) # ---------- LEN DECODE ---------- len_decode: mov len, 8 - kMatchMinLen IF_BIT_0_NOUP_1 probs, len_mid_0 UPDATE_1 probs, 0, 0 p2_add probs, (1 << (kLenNumLowBits + PSHIFT)) mov len, 0 - kMatchMinLen IF_BIT_0_NOUP_1 probs, len_mid_0 UPDATE_1 probs, 0, 0 p2_add probs, LenHigh * PMULT - (1 << (kLenNumLowBits + PSHIFT)) #if 0 == 1 BIT_0 BIT_1 BIT_1 BIT_1 BIT_1 BIT_1 #else PLOAD_2 prob_reg, probs, 1 * PMULT mov sym, 1 BIT_01 MY_ALIGN_FOR_LOOP len8_loop: BIT_1 tbz sym, 6, len8_loop #endif mov len, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - kMatchMinLen jmp len_mid_2 MY_ALIGN_FOR_ENTRY len_mid_0: UPDATE_0 probs, 0, 0 p2_add probs, pbPos_R BIT_0 len_mid_2: BIT_1 BIT_2 sub len, sym, len tbz state, FLAG_STATE_BITS, copy_match # ---------- DECODE DISTANCE ---------- // probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); mov t0, 3 + kMatchMinLen cmp len, 3 + kMatchMinLen cmovb t0, len SET_probs PosSlot - (kMatchMinLen << (kNumPosSlotBits)) add probs, probs, t0_R, lsl #(kNumPosSlotBits + PSHIFT) #ifdef _LZMA_SIZE_OPT PLOAD_2 prob_reg, probs, 1 * PMULT mov sym, 1 BIT_01 MY_ALIGN_FOR_LOOP slot_loop: BIT_1 tbz sym, 5, slot_loop #else BIT_0 BIT_1 BIT_1 BIT_1 BIT_1 #endif #define numBits t4 mov numBits, sym BIT_2 // we need only low bits p2_and sym, 3 cmp numBits, 32 + kEndPosModelIndex / 2 jb short_dist SET_probs kAlign # unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); p2_sub numBits, (32 + 1 + kNumAlignBits) # distance = (2 | (distance & 1)); or sym, 2 PLOAD_2 prob_reg, probs, 1 * PMULT add sym2_R, probs, 2 * PMULT # ---------- DIRECT DISTANCE ---------- .macro DIRECT_1 shr range, 1 subs t0, cod, range p2_add sym, sym // add t1, sym, 1 csel cod, cod, t0, mi csinc sym, sym, sym, mi // csel sym, t1, sym, pl // adc sym, sym, sym // not 100% compatible for "corruptued-allowed" LZMA streams dec_s numBits je direct_end .endm #ifdef _LZMA_SIZE_OPT jmp direct_norm MY_ALIGN_FOR_ENTRY direct_loop: DIRECT_1 direct_norm: TEST_HIGH_BYTE_range jnz direct_loop NORM_2 jmp direct_loop #else .macro DIRECT_2 TEST_HIGH_BYTE_range jz direct_unroll DIRECT_1 .endm DIRECT_2 DIRECT_2 DIRECT_2 DIRECT_2 DIRECT_2 DIRECT_2 DIRECT_2 DIRECT_2 direct_unroll: NORM_2 DIRECT_1 DIRECT_1 DIRECT_1 DIRECT_1 DIRECT_1 DIRECT_1 DIRECT_1 DIRECT_1 jmp direct_unroll #endif MY_ALIGN_FOR_ENTRY direct_end: shl sym, kNumAlignBits REV_0 prob_reg REV_1 prob_reg, 2 REV_1 prob_reg, 4 REV_2 prob_reg, 8 decode_dist_end: // if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) tst checkDicSize, checkDicSize csel t0, processedPos, checkDicSize, eq cmp sym, t0 jae end_of_payload // jmp end_of_payload # for debug mov rep3, rep2 mov rep2, rep1 mov rep1, rep0 add rep0, sym, 1 .macro STATE_UPDATE_FOR_MATCH // state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; // cmp state, (kNumStates + kNumLitStates) * PMULT cmp state, kNumLitStates * PMULT + (1 << FLAG_STATE_BITS) mov state, kNumLitStates * PMULT mov t0, (kNumLitStates + 3) * PMULT cmovae state, t0 .endm STATE_UPDATE_FOR_MATCH # ---------- COPY MATCH ---------- copy_match: // if ((rem = limit - dicPos) == 0) break // return SZ_ERROR_DATA; subs cnt_R, limit, dicPos // jz fin_dicPos_LIMIT jz fin_OK // curLen = ((rem < len) ? (unsigned)rem : len); cmp cnt_R, len_R cmovae cnt, len sub t0_R, dicPos, dic p2_add dicPos, cnt_R p2_add processedPos, cnt p2_sub len, cnt // pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); p2_sub_s t0_R, rep0_R jae 1f cmn t0_R, cnt_R p2_add t0_R, dicBufSize ja copy_match_cross 1: # ---------- COPY MATCH FAST ---------- # t0_R : src_pos p2_add t0_R, dic ldrb sym, [t0_R] p2_add t0_R, cnt_R p1_neg cnt_R copy_common: dec dicPos # dicPos : (ptr_to_last_dest_BYTE) # t0_R : (src_lim) # cnt_R : (-curLen) IsMatchBranch_Pre inc_s cnt_R jz copy_end cmp rep0, 1 je copy_match_0 #ifdef LZMA_USE_2BYTES_COPY strb sym, [dicPos, cnt_R] dec dicPos # dicPos : (ptr_to_last_dest_16bitWORD) p2_and cnt_R, -2 ldrh sym, [t0_R, cnt_R] adds cnt_R, cnt_R, 2 jz 2f MY_ALIGN_FOR_LOOP 1: /* strh sym, [dicPos, cnt_R] ldrh sym, [t0_R, cnt_R] adds cnt_R, cnt_R, 2 jz 2f */ strh sym, [dicPos, cnt_R] ldrh sym, [t0_R, cnt_R] adds cnt_R, cnt_R, 2 jnz 1b 2: /* // for universal little/big endian code, but slow strh sym, [dicPos] inc dicPos ldrb sym, [t0_R, -1] */ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ // we must improve big-endian detection for another compilers // for big-endian we need to revert bytes rev16 sym, sym #endif // (sym) must represent as little-endian here: strb sym, [dicPos], 1 shr sym, 8 #else MY_ALIGN_FOR_LOOP 1: strb sym, [dicPos, cnt_R] ldrb sym, [t0_R, cnt_R] inc_s cnt_R jz copy_end strb sym, [dicPos, cnt_R] ldrb sym, [t0_R, cnt_R] inc_s cnt_R jnz 1b #endif copy_end: lz_end_match: strb sym, [dicPos], 1 # IsMatchBranch_Pre CheckLimits lz_end: IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label # ---------- LITERAL MATCHED ---------- LIT_PROBS // matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; sub t0_R, dicPos, dic p2_sub_s t0_R, rep0_R #ifdef LZMA_USE_CMOV_LZ_WRAP add t1_R, t0_R, dicBufSize cmovb t0_R, t1_R #else jae 1f p2_add t0_R, dicBufSize 1: #endif ldrb match, [dic, t0_R] // state -= (state < 10) ? 3 : 6; sub sym, state, 6 * PMULT cmp state, 10 * PMULT p2_sub state, 3 * PMULT cmovae state, sym #ifdef _LZMA_SIZE_OPT mov offs, 256 * PMULT shl match, (PSHIFT + 1) mov sym, 1 and bit, match, offs add prm, probs, offs_R MY_ALIGN_FOR_LOOP litm_loop: LITM tbz sym, 8, litm_loop #else LITM_0 LITM LITM LITM LITM LITM LITM LITM_2 #endif IsMatchBranch_Pre strb sym, [dicPos], 1 p2_and sym, 255 // mov len, wzr // LITM uses same regisetr (len / offs). So we clear it CheckLimits_lit lit_matched_end: IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label # IsMatchBranch p2_sub state, 3 * PMULT jmp lit_start_2 # ---------- REP 0 LITERAL ---------- MY_ALIGN_FOR_ENTRY IsRep0Short_label: UPDATE_0 probs_state, pbPos_R, 0 // dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; sub t0_R, dicPos, dic // state = state < kNumLitStates ? 9 : 11; or state, 1 * PMULT # the caller doesn't allow (dicPos >= limit) case for REP_SHORT # so we don't need the following (dicPos == limit) check here: # cmp dicPos, limit # jae fin_dicPos_LIMIT_REP_SHORT # // jmp fin_dicPos_LIMIT_REP_SHORT // for testing/debug puposes inc processedPos IsMatchBranch_Pre p2_sub_s t0_R, rep0_R #ifdef LZMA_USE_CMOV_LZ_WRAP add sym_R, t0_R, dicBufSize cmovb t0_R, sym_R #else jae 1f p2_add t0_R, dicBufSize 1: #endif ldrb sym, [dic, t0_R] // mov len, wzr jmp lz_end_match MY_ALIGN_FOR_ENTRY IsRep_label: UPDATE_1 probs_state, 0, (IsRep - IsMatch) # The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. # So we don't check it here. # mov t0, processedPos # or t0, checkDicSize # jz fin_ERROR_2 // state = state < kNumLitStates ? 8 : 11; cmp state, kNumLitStates * PMULT mov state, 8 * PMULT mov probBranch, 11 * PMULT cmovae state, probBranch SET_probs RepLenCoder IF_BIT_1 probs_state, 0, (IsRepG0 - IsMatch), IsRepG0_label sub_big probs_state, probs_state, (IsMatch - IsRep0Long) << PSHIFT IF_BIT_0_NOUP probs_state, pbPos_R, 0, IsRep0Short_label UPDATE_1 probs_state, pbPos_R, 0 jmp len_decode MY_ALIGN_FOR_ENTRY IsRepG0_label: UPDATE_1 probs_state, 0, (IsRepG0 - IsMatch) IF_BIT_1 probs_state, 0, (IsRepG1 - IsMatch), IsRepG1_label mov dist, rep1 mov rep1, rep0 mov rep0, dist jmp len_decode # MY_ALIGN_FOR_ENTRY IsRepG1_label: UPDATE_1 probs_state, 0, (IsRepG1 - IsMatch) IF_BIT_1 probs_state, 0, (IsRepG2 - IsMatch), IsRepG2_label mov dist, rep2 mov rep2, rep1 mov rep1, rep0 mov rep0, dist jmp len_decode # MY_ALIGN_FOR_ENTRY IsRepG2_label: UPDATE_1 probs_state, 0, (IsRepG2 - IsMatch) mov dist, rep3 mov rep3, rep2 mov rep2, rep1 mov rep1, rep0 mov rep0, dist jmp len_decode # ---------- SPEC SHORT DISTANCE ---------- MY_ALIGN_FOR_ENTRY short_dist: p2_sub_s numBits, 32 + 1 jbe decode_dist_end or sym, 2 shl sym, numBits add sym_R, probs_Spec, sym_R, lsl #PSHIFT p2_add sym_R, SpecPos * PMULT + 1 * PMULT mov sym2, PMULT // # step MY_ALIGN_FOR_LOOP spec_loop: REV_1_VAR prob_reg dec_s numBits jnz spec_loop p2_add sym2_R, probs_Spec .if SpecPos != 0 p2_add sym2_R, SpecPos * PMULT .endif p2_sub sym_R, sym2_R shr sym, PSHIFT jmp decode_dist_end # ---------- COPY MATCH 0 ---------- MY_ALIGN_FOR_ENTRY copy_match_0: #ifdef LZMA_USE_4BYTES_FILL strb sym, [dicPos, cnt_R] inc_s cnt_R jz copy_end strb sym, [dicPos, cnt_R] inc_s cnt_R jz copy_end strb sym, [dicPos, cnt_R] inc_s cnt_R jz copy_end orr t3, sym, sym, lsl 8 p2_and cnt_R, -4 orr t3, t3, t3, lsl 16 MY_ALIGN_FOR_LOOP_16 1: /* str t3, [dicPos, cnt_R] adds cnt_R, cnt_R, 4 jz 2f */ str t3, [dicPos, cnt_R] adds cnt_R, cnt_R, 4 jnz 1b 2: // p2_and sym, 255 #else MY_ALIGN_FOR_LOOP 1: strb sym, [dicPos, cnt_R] inc_s cnt_R jz copy_end strb sym, [dicPos, cnt_R] inc_s cnt_R jnz 1b #endif jmp copy_end # ---------- COPY MATCH CROSS ---------- copy_match_cross: # t0_R - src pos # cnt_R - total copy len p1_neg cnt_R 1: ldrb sym, [dic, t0_R] inc t0_R strb sym, [dicPos, cnt_R] inc cnt_R cmp t0_R, dicBufSize jne 1b ldrb sym, [dic] sub t0_R, dic, cnt_R jmp copy_common /* fin_dicPos_LIMIT_REP_SHORT: mov len, 1 jmp fin_OK */ /* fin_dicPos_LIMIT: jmp fin_OK # For more strict mode we can stop decoding with error # mov sym, 1 # jmp fin */ fin_ERROR_MATCH_DIST: # rep0 = distance + 1; p2_add len, kMatchSpecLen_Error_Data mov rep3, rep2 mov rep2, rep1 mov rep1, rep0 mov rep0, sym STATE_UPDATE_FOR_MATCH # jmp fin_OK mov sym, 1 jmp fin end_of_payload: inc_s sym jnz fin_ERROR_MATCH_DIST mov len, kMatchSpecLenStart xor state, (1 << FLAG_STATE_BITS) jmp fin_OK /* fin_OK_lit: mov len, wzr */ fin_OK: mov sym, wzr fin: NORM #define fin_lzma_reg t0_R .macro STORE_LZMA_VAR reg:req, struct_offs:req str \reg, [fin_lzma_reg, \struct_offs] .endm .macro STORE_LZMA_PAIR reg0:req, reg1:req, struct_offs:req stp \reg0, \reg1, [fin_lzma_reg, \struct_offs] .endm ldr fin_lzma_reg, [sp, 120] p2_sub dicPos, dic shr state, PSHIFT STORE_LZMA_PAIR dicPos, buf, offset_dicPos STORE_LZMA_PAIR range, cod, offset_range STORE_LZMA_VAR processedPos, offset_processedPos STORE_LZMA_PAIR rep0, rep1, offset_rep0 STORE_LZMA_PAIR rep2, rep3, offset_rep2 STORE_LZMA_PAIR state, len, offset_state mov w0, sym ldp x29, x30, [sp, 80] ldp x27, x28, [sp, 64] ldp x25, x26, [sp, 48] ldp x23, x24, [sp, 32] ldp x21, x22, [sp, 16] ldp x19, x20, [sp], 128 ret /* .cfi_endproc .LFE0: .size LzmaDec_DecodeReal_3, .-LzmaDec_DecodeReal_3 .ident "TAG_LZMA" .section .note.GNU-stack,"",@progbits */ tmp41wklro_/Asm/x86/0000700000175000001440000000000014706260545015307 5ustar nabijaczleweliuserstmp41wklro_/Asm/x86/7zAsm.asm0000444000175000001440000001323114534573460017024 0ustar nabijaczleweliusers; 7zAsm.asm -- ASM macros ; 2023-12-08 : Igor Pavlov : Public domain ; UASM can require these changes ; OPTION FRAMEPRESERVEFLAGS:ON ; OPTION PROLOGUE:NONE ; OPTION EPILOGUE:NONE ifdef @wordsize ; @wordsize is defined only in JWASM and ASMC and is not defined in MASM ; @wordsize eq 8 for 64-bit x64 ; @wordsize eq 2 for 32-bit x86 if @wordsize eq 8 x64 equ 1 endif else ifdef RAX x64 equ 1 endif endif ifdef x64 IS_X64 equ 1 else IS_X64 equ 0 endif ifdef ABI_LINUX IS_LINUX equ 1 else IS_LINUX equ 0 endif ifndef x64 ; Use ABI_CDECL for x86 (32-bit) only ; if ABI_CDECL is not defined, we use fastcall abi ifdef ABI_CDECL IS_CDECL equ 1 else IS_CDECL equ 0 endif endif OPTION PROLOGUE:NONE OPTION EPILOGUE:NONE MY_ASM_START macro ifdef x64 .code else .386 .model flat _TEXT$00 SEGMENT PARA PUBLIC 'CODE' endif endm MY_PROC macro name:req, numParams:req align 16 proc_numParams = numParams if (IS_X64 gt 0) proc_name equ name elseif (IS_LINUX gt 0) proc_name equ name elseif (IS_CDECL gt 0) proc_name equ @CatStr(_,name) else proc_name equ @CatStr(@,name,@, %numParams * 4) endif proc_name PROC endm MY_ENDP macro if (IS_X64 gt 0) ret elseif (IS_CDECL gt 0) ret elseif (proc_numParams LT 3) ret else ret (proc_numParams - 2) * 4 endif proc_name ENDP endm ifdef x64 REG_SIZE equ 8 REG_LOGAR_SIZE equ 3 else REG_SIZE equ 4 REG_LOGAR_SIZE equ 2 endif x0 equ EAX x1 equ ECX x2 equ EDX x3 equ EBX x4 equ ESP x5 equ EBP x6 equ ESI x7 equ EDI x0_W equ AX x1_W equ CX x2_W equ DX x3_W equ BX x5_W equ BP x6_W equ SI x7_W equ DI x0_L equ AL x1_L equ CL x2_L equ DL x3_L equ BL x0_H equ AH x1_H equ CH x2_H equ DH x3_H equ BH ; r0_L equ AL ; r1_L equ CL ; r2_L equ DL ; r3_L equ BL ; r0_H equ AH ; r1_H equ CH ; r2_H equ DH ; r3_H equ BH ifdef x64 x5_L equ BPL x6_L equ SIL x7_L equ DIL x8_L equ r8b x9_L equ r9b x10_L equ r10b x11_L equ r11b x12_L equ r12b x13_L equ r13b x14_L equ r14b x15_L equ r15b r0 equ RAX r1 equ RCX r2 equ RDX r3 equ RBX r4 equ RSP r5 equ RBP r6 equ RSI r7 equ RDI x8 equ r8d x9 equ r9d x10 equ r10d x11 equ r11d x12 equ r12d x13 equ r13d x14 equ r14d x15 equ r15d else r0 equ x0 r1 equ x1 r2 equ x2 r3 equ x3 r4 equ x4 r5 equ x5 r6 equ x6 r7 equ x7 endif x0_R equ r0 x1_R equ r1 x2_R equ r2 x3_R equ r3 x4_R equ r4 x5_R equ r5 x6_R equ r6 x7_R equ r7 x8_R equ r8 x9_R equ r9 x10_R equ r10 x11_R equ r11 x12_R equ r12 x13_R equ r13 x14_R equ r14 x15_R equ r15 ifdef x64 ifdef ABI_LINUX MY_PUSH_2_REGS macro push r3 push r5 endm MY_POP_2_REGS macro pop r5 pop r3 endm endif endif MY_PUSH_4_REGS macro push r3 push r5 push r6 push r7 endm MY_POP_4_REGS macro pop r7 pop r6 pop r5 pop r3 endm ; for fastcall and for WIN-x64 REG_PARAM_0_x equ x1 REG_PARAM_0 equ r1 REG_PARAM_1_x equ x2 REG_PARAM_1 equ r2 ifndef x64 ; for x86-fastcall REG_ABI_PARAM_0_x equ REG_PARAM_0_x REG_ABI_PARAM_0 equ REG_PARAM_0 REG_ABI_PARAM_1_x equ REG_PARAM_1_x REG_ABI_PARAM_1 equ REG_PARAM_1 MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro MY_PUSH_4_REGS endm MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro MY_POP_4_REGS endm else ; x64 if (IS_LINUX eq 0) ; for WIN-x64: REG_PARAM_2_x equ x8 REG_PARAM_2 equ r8 REG_PARAM_3 equ r9 REG_ABI_PARAM_0_x equ REG_PARAM_0_x REG_ABI_PARAM_0 equ REG_PARAM_0 REG_ABI_PARAM_1_x equ REG_PARAM_1_x REG_ABI_PARAM_1 equ REG_PARAM_1 REG_ABI_PARAM_2_x equ REG_PARAM_2_x REG_ABI_PARAM_2 equ REG_PARAM_2 REG_ABI_PARAM_3 equ REG_PARAM_3 else ; for LINUX-x64: REG_LINUX_PARAM_0_x equ x7 REG_LINUX_PARAM_0 equ r7 REG_LINUX_PARAM_1_x equ x6 REG_LINUX_PARAM_1 equ r6 REG_LINUX_PARAM_2 equ r2 REG_LINUX_PARAM_3 equ r1 REG_LINUX_PARAM_4_x equ x8 REG_LINUX_PARAM_4 equ r8 REG_LINUX_PARAM_5 equ r9 REG_ABI_PARAM_0_x equ REG_LINUX_PARAM_0_x REG_ABI_PARAM_0 equ REG_LINUX_PARAM_0 REG_ABI_PARAM_1_x equ REG_LINUX_PARAM_1_x REG_ABI_PARAM_1 equ REG_LINUX_PARAM_1 REG_ABI_PARAM_2 equ REG_LINUX_PARAM_2 REG_ABI_PARAM_3 equ REG_LINUX_PARAM_3 REG_ABI_PARAM_4_x equ REG_LINUX_PARAM_4_x REG_ABI_PARAM_4 equ REG_LINUX_PARAM_4 REG_ABI_PARAM_5 equ REG_LINUX_PARAM_5 MY_ABI_LINUX_TO_WIN_2 macro mov r2, r6 mov r1, r7 endm MY_ABI_LINUX_TO_WIN_3 macro mov r8, r2 mov r2, r6 mov r1, r7 endm MY_ABI_LINUX_TO_WIN_4 macro mov r9, r1 mov r8, r2 mov r2, r6 mov r1, r7 endm endif ; IS_LINUX MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro if (IS_LINUX gt 0) MY_PUSH_2_REGS else MY_PUSH_4_REGS endif endm MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro if (IS_LINUX gt 0) MY_POP_2_REGS else MY_POP_4_REGS endif endm MY_PUSH_PRESERVED_ABI_REGS macro MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 push r12 push r13 push r14 push r15 endm MY_POP_PRESERVED_ABI_REGS macro pop r15 pop r14 pop r13 pop r12 MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 endm endif ; x64 tmp41wklro_/Asm/x86/7zCrcOpt.asm0000444000175000001440000001506714534645620017505 0ustar nabijaczleweliusers; 7zCrcOpt.asm -- CRC32 calculation : optimized version ; 2023-12-08 : Igor Pavlov : Public domain include 7zAsm.asm MY_ASM_START NUM_WORDS equ 3 UNROLL_CNT equ 2 if (NUM_WORDS lt 1) or (NUM_WORDS gt 64) .err endif if (UNROLL_CNT lt 1) .err endif rD equ r2 rD_x equ x2 rN equ r7 rT equ r5 ifndef x64 if (IS_CDECL gt 0) crc_OFFS equ (REG_SIZE * 5) data_OFFS equ (REG_SIZE + crc_OFFS) size_OFFS equ (REG_SIZE + data_OFFS) else size_OFFS equ (REG_SIZE * 5) endif table_OFFS equ (REG_SIZE + size_OFFS) endif ; rN + rD is same speed as rD, but we reduce one instruction in loop SRCDAT_1 equ rN + rD * 1 + 1 * SRCDAT_4 equ rN + rD * 1 + 4 * CRC macro op:req, dest:req, src:req, t:req op dest, dword ptr [rT + @CatStr(src, _R) * 4 + 0400h * (t)] endm CRC_XOR macro dest:req, src:req, t:req CRC xor, dest, src, t endm CRC_MOV macro dest:req, src:req, t:req CRC mov, dest, src, t endm MOVZXLO macro dest:req, src:req movzx dest, @CatStr(src, _L) endm MOVZXHI macro dest:req, src:req movzx dest, @CatStr(src, _H) endm ; movzx x0, x0_L - is slow in some cpus (ivb), if same register for src and dest ; movzx x3, x0_L sometimes is 0 cycles latency (not always) ; movzx x3, x0_L sometimes is 0.5 cycles latency ; movzx x3, x0_H is 2 cycles latency in some cpus CRC1b macro movzx x6, byte ptr [rD] MOVZXLO x3, x0 inc rD shr x0, 8 xor x6, x3 CRC_XOR x0, x6, 0 dec rN endm LOAD_1 macro dest:req, t:req, iter:req, index:req movzx dest, byte ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + index)] endm LOAD_2 macro dest:req, t:req, iter:req, index:req movzx dest, word ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + index)] endm CRC_QUAD macro nn, t:req, iter:req ifdef x64 ; paired memory loads give 1-3% speed gain, but it uses more registers LOAD_2 x3, t, iter, 0 LOAD_2 x9, t, iter, 2 MOVZXLO x6, x3 shr x3, 8 CRC_XOR nn, x6, t * 4 + 3 MOVZXLO x6, x9 shr x9, 8 CRC_XOR nn, x3, t * 4 + 2 CRC_XOR nn, x6, t * 4 + 1 CRC_XOR nn, x9, t * 4 + 0 elseif 0 LOAD_2 x3, t, iter, 0 MOVZXLO x6, x3 shr x3, 8 CRC_XOR nn, x6, t * 4 + 3 CRC_XOR nn, x3, t * 4 + 2 LOAD_2 x3, t, iter, 2 MOVZXLO x6, x3 shr x3, 8 CRC_XOR nn, x6, t * 4 + 1 CRC_XOR nn, x3, t * 4 + 0 elseif 0 LOAD_1 x3, t, iter, 0 LOAD_1 x6, t, iter, 1 CRC_XOR nn, x3, t * 4 + 3 CRC_XOR nn, x6, t * 4 + 2 LOAD_1 x3, t, iter, 2 LOAD_1 x6, t, iter, 3 CRC_XOR nn, x3, t * 4 + 1 CRC_XOR nn, x6, t * 4 + 0 else ; 32-bit load is better if there is only one read port (core2) ; but that code can be slower if there are 2 read ports (snb) mov x3, dword ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + 0)] MOVZXLO x6, x3 CRC_XOR nn, x6, t * 4 + 3 MOVZXHI x6, x3 shr x3, 16 CRC_XOR nn, x6, t * 4 + 2 MOVZXLO x6, x3 shr x3, 8 CRC_XOR nn, x6, t * 4 + 1 CRC_XOR nn, x3, t * 4 + 0 endif endm LAST equ (4 * (NUM_WORDS - 1)) CRC_ITER macro qq, nn, iter mov nn, [SRCDAT_4 (NUM_WORDS * (1 + iter))] i = 0 rept NUM_WORDS - 1 CRC_QUAD nn, i, iter i = i + 1 endm MOVZXLO x6, qq mov x3, qq shr x3, 24 CRC_XOR nn, x6, LAST + 3 CRC_XOR nn, x3, LAST + 0 ror qq, 16 MOVZXLO x6, qq shr qq, 24 CRC_XOR nn, x6, LAST + 1 if ((UNROLL_CNT and 1) eq 1) and (iter eq (UNROLL_CNT - 1)) CRC_MOV qq, qq, LAST + 2 xor qq, nn else CRC_XOR nn, qq, LAST + 2 endif endm ; + 4 for prefetching next 4-bytes after current iteration NUM_BYTES_LIMIT equ (NUM_WORDS * 4 * UNROLL_CNT + 4) ALIGN_MASK equ 3 ; MY_PROC @CatStr(CrcUpdateT, 12), 4 MY_PROC @CatStr(CrcUpdateT, %(NUM_WORDS * 4)), 4 MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 ifdef x64 mov x0, REG_ABI_PARAM_0_x ; x0 = x1(win) / x7(linux) mov rT, REG_ABI_PARAM_3 ; r5 = r9(win) / x1(linux) mov rN, REG_ABI_PARAM_2 ; r7 = r8(win) / r2(linux) ; mov rD, REG_ABI_PARAM_1 ; r2 = r2(win) if (IS_LINUX gt 0) mov rD, REG_ABI_PARAM_1 ; r2 = r6 endif else if (IS_CDECL gt 0) mov x0, [r4 + crc_OFFS] mov rD, [r4 + data_OFFS] else mov x0, REG_ABI_PARAM_0_x endif mov rN, [r4 + size_OFFS] mov rT, [r4 + table_OFFS] endif cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK jb crc_end @@: test rD_x, ALIGN_MASK ; test rD, ALIGN_MASK jz @F CRC1b jmp @B @@: xor x0, dword ptr [rD] lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)] sub rD, rN align 16 @@: unr_index = 0 while unr_index lt UNROLL_CNT if (unr_index and 1) eq 0 CRC_ITER x0, x1, unr_index else CRC_ITER x1, x0, unr_index endif unr_index = unr_index + 1 endm add rD, NUM_WORDS * 4 * UNROLL_CNT jnc @B if 0 ; byte verson add rD, rN xor x0, dword ptr [rD] add rN, NUM_BYTES_LIMIT - 1 else ; 4-byte version add rN, 4 * NUM_WORDS * UNROLL_CNT sub rD, 4 * NUM_WORDS * UNROLL_CNT @@: MOVZXLO x3, x0 MOVZXHI x1, x0 shr x0, 16 MOVZXLO x6, x0 shr x0, 8 CRC_MOV x0, x0, 0 CRC_XOR x0, x3, 3 CRC_XOR x0, x1, 2 CRC_XOR x0, x6, 1 add rD, 4 if (NUM_WORDS * UNROLL_CNT) ne 1 jc @F xor x0, [SRCDAT_4 0] jmp @B @@: endif add rD, rN add rN, 4 - 1 endif sub rN, rD crc_end: test rN, rN jz func_end @@: CRC1b jnz @B func_end: MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 MY_ENDP end tmp41wklro_/Asm/x86/AesOpt.asm0000444000175000001440000004131514161630760017213 0ustar nabijaczleweliusers; AesOpt.asm -- AES optimized code for x86 AES hardware instructions ; 2021-12-25 : Igor Pavlov : Public domain include 7zAsm.asm ifdef __ASMC__ use_vaes_256 equ 1 else ifdef ymm0 use_vaes_256 equ 1 endif endif ifdef use_vaes_256 ECHO "++ VAES 256" else ECHO "-- NO VAES 256" endif ifdef x64 ECHO "x86-64" else ECHO "x86" if (IS_CDECL gt 0) ECHO "ABI : CDECL" else ECHO "ABI : no CDECL : FASTCALL" endif endif if (IS_LINUX gt 0) ECHO "ABI : LINUX" else ECHO "ABI : WINDOWS" endif MY_ASM_START ifndef x64 .686 .xmm endif ; MY_ALIGN EQU ALIGN(64) MY_ALIGN EQU SEG_ALIGN EQU MY_ALIGN MY_SEG_PROC macro name:req, numParams:req ; seg_name equ @CatStr(_TEXT$, name) ; seg_name SEGMENT SEG_ALIGN 'CODE' MY_PROC name, numParams endm MY_SEG_ENDP macro ; seg_name ENDS endm NUM_AES_KEYS_MAX equ 15 ; the number of push operators in function PROLOG if (IS_LINUX eq 0) or (IS_X64 eq 0) num_regs_push equ 2 stack_param_offset equ (REG_SIZE * (1 + num_regs_push)) endif ifdef x64 num_param equ REG_ABI_PARAM_2 else if (IS_CDECL gt 0) ; size_t size ; void * data ; UInt32 * aes ; ret-ip <- (r4) aes_OFFS equ (stack_param_offset) data_OFFS equ (REG_SIZE + aes_OFFS) size_OFFS equ (REG_SIZE + data_OFFS) num_param equ [r4 + size_OFFS] else num_param equ [r4 + stack_param_offset] endif endif keys equ REG_PARAM_0 ; r1 rD equ REG_PARAM_1 ; r2 rN equ r0 koffs_x equ x7 koffs_r equ r7 ksize_x equ x6 ksize_r equ r6 keys2 equ r3 state equ xmm0 key equ xmm0 key_ymm equ ymm0 key_ymm_n equ 0 ifdef x64 ways = 11 else ways = 4 endif ways_start_reg equ 1 iv equ @CatStr(xmm, %(ways_start_reg + ways)) iv_ymm equ @CatStr(ymm, %(ways_start_reg + ways)) WOP macro op, op2 i = 0 rept ways op @CatStr(xmm, %(ways_start_reg + i)), op2 i = i + 1 endm endm ifndef ABI_LINUX ifdef x64 ; we use 32 bytes of home space in stack in WIN64-x64 NUM_HOME_MM_REGS equ (32 / 16) ; we preserve xmm registers starting from xmm6 in WIN64-x64 MM_START_SAVE_REG equ 6 SAVE_XMM macro num_used_mm_regs:req num_save_mm_regs = num_used_mm_regs - MM_START_SAVE_REG if num_save_mm_regs GT 0 num_save_mm_regs2 = num_save_mm_regs - NUM_HOME_MM_REGS ; RSP is (16*x + 8) after entering the function in WIN64-x64 stack_offset = 16 * num_save_mm_regs2 + (stack_param_offset mod 16) i = 0 rept num_save_mm_regs if i eq NUM_HOME_MM_REGS sub r4, stack_offset endif if i lt NUM_HOME_MM_REGS movdqa [r4 + stack_param_offset + i * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i)) else movdqa [r4 + (i - NUM_HOME_MM_REGS) * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i)) endif i = i + 1 endm endif endm RESTORE_XMM macro num_used_mm_regs:req if num_save_mm_regs GT 0 i = 0 if num_save_mm_regs2 GT 0 rept num_save_mm_regs2 movdqa @CatStr(xmm, %(MM_START_SAVE_REG + NUM_HOME_MM_REGS + i)), [r4 + i * 16] i = i + 1 endm add r4, stack_offset endif num_low_regs = num_save_mm_regs - i i = 0 rept num_low_regs movdqa @CatStr(xmm, %(MM_START_SAVE_REG + i)), [r4 + stack_param_offset + i * 16] i = i + 1 endm endif endm endif ; x64 endif ; ABI_LINUX MY_PROLOG macro num_used_mm_regs:req ; num_regs_push: must be equal to the number of push operators ; push r3 ; push r5 if (IS_LINUX eq 0) or (IS_X64 eq 0) push r6 push r7 endif mov rN, num_param ; don't move it; num_param can use stack pointer (r4) if (IS_X64 eq 0) if (IS_CDECL gt 0) mov rD, [r4 + data_OFFS] mov keys, [r4 + aes_OFFS] endif elseif (IS_LINUX gt 0) MY_ABI_LINUX_TO_WIN_2 endif ifndef ABI_LINUX ifdef x64 SAVE_XMM num_used_mm_regs endif endif mov ksize_x, [keys + 16] shl ksize_x, 5 endm MY_EPILOG macro ifndef ABI_LINUX ifdef x64 RESTORE_XMM num_save_mm_regs endif endif if (IS_LINUX eq 0) or (IS_X64 eq 0) pop r7 pop r6 endif ; pop r5 ; pop r3 MY_ENDP endm OP_KEY macro op:req, offs:req op state, [keys + offs] endm WOP_KEY macro op:req, offs:req movdqa key, [keys + offs] WOP op, key endm ; ---------- AES-CBC Decode ---------- XOR_WITH_DATA macro reg, _ppp_ pxor reg, [rD + i * 16] endm WRITE_TO_DATA macro reg, _ppp_ movdqa [rD + i * 16], reg endm ; state0 equ @CatStr(xmm, %(ways_start_reg)) key0 equ @CatStr(xmm, %(ways_start_reg + ways + 1)) key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1)) key_last equ @CatStr(xmm, %(ways_start_reg + ways + 2)) key_last_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2)) key_last_ymm_n equ (ways_start_reg + ways + 2) NUM_CBC_REGS equ (ways_start_reg + ways + 3) MY_SEG_PROC AesCbc_Decode_HW, 3 AesCbc_Decode_HW_start:: MY_PROLOG NUM_CBC_REGS AesCbc_Decode_HW_start_2:: movdqa iv, [keys] add keys, 32 movdqa key0, [keys + 1 * ksize_r] movdqa key_last, [keys] sub ksize_x, 16 jmp check2 align 16 nextBlocks2: WOP movdqa, [rD + i * 16] mov koffs_x, ksize_x ; WOP_KEY pxor, ksize_r + 16 WOP pxor, key0 ; align 16 @@: WOP_KEY aesdec, 1 * koffs_r sub koffs_r, 16 jnz @B ; WOP_KEY aesdeclast, 0 WOP aesdeclast, key_last pxor @CatStr(xmm, %(ways_start_reg)), iv i = 1 rept ways - 1 pxor @CatStr(xmm, %(ways_start_reg + i)), [rD + i * 16 - 16] i = i + 1 endm movdqa iv, [rD + ways * 16 - 16] WOP WRITE_TO_DATA add rD, ways * 16 AesCbc_Decode_HW_start_3:: check2: sub rN, ways jnc nextBlocks2 add rN, ways sub ksize_x, 16 jmp check nextBlock: movdqa state, [rD] mov koffs_x, ksize_x ; OP_KEY pxor, 1 * ksize_r + 32 pxor state, key0 ; movdqa state0, [rD] ; movdqa state, key0 ; pxor state, state0 @@: OP_KEY aesdec, 1 * koffs_r + 16 OP_KEY aesdec, 1 * koffs_r sub koffs_r, 32 jnz @B OP_KEY aesdec, 16 ; OP_KEY aesdeclast, 0 aesdeclast state, key_last pxor state, iv movdqa iv, [rD] ; movdqa iv, state0 movdqa [rD], state add rD, 16 check: sub rN, 1 jnc nextBlock movdqa [keys - 32], iv MY_EPILOG ; ---------- AVX ---------- AVX__WOP_n macro op i = 0 rept ways op (ways_start_reg + i) i = i + 1 endm endm AVX__WOP macro op i = 0 rept ways op @CatStr(ymm, %(ways_start_reg + i)) i = i + 1 endm endm AVX__WOP_KEY macro op:req, offs:req vmovdqa key_ymm, ymmword ptr [keys2 + offs] AVX__WOP_n op endm AVX__CBC_START macro reg ; vpxor reg, key_ymm, ymmword ptr [rD + 32 * i] vpxor reg, key0_ymm, ymmword ptr [rD + 32 * i] endm AVX__CBC_END macro reg if i eq 0 vpxor reg, reg, iv_ymm else vpxor reg, reg, ymmword ptr [rD + i * 32 - 16] endif endm AVX__WRITE_TO_DATA macro reg vmovdqu ymmword ptr [rD + 32 * i], reg endm AVX__XOR_WITH_DATA macro reg vpxor reg, reg, ymmword ptr [rD + 32 * i] endm AVX__CTR_START macro reg vpaddq iv_ymm, iv_ymm, one_ymm ; vpxor reg, iv_ymm, key_ymm vpxor reg, iv_ymm, key0_ymm endm MY_VAES_INSTR_2 macro cmd, dest, a1, a2 db 0c4H db 2 + 040H + 020h * (1 - (a2) / 8) + 080h * (1 - (dest) / 8) db 5 + 8 * ((not (a1)) and 15) db cmd db 0c0H + 8 * ((dest) and 7) + ((a2) and 7) endm MY_VAES_INSTR macro cmd, dest, a MY_VAES_INSTR_2 cmd, dest, dest, a endm MY_vaesenc macro dest, a MY_VAES_INSTR 0dcH, dest, a endm MY_vaesenclast macro dest, a MY_VAES_INSTR 0ddH, dest, a endm MY_vaesdec macro dest, a MY_VAES_INSTR 0deH, dest, a endm MY_vaesdeclast macro dest, a MY_VAES_INSTR 0dfH, dest, a endm AVX__VAES_DEC macro reg MY_vaesdec reg, key_ymm_n endm AVX__VAES_DEC_LAST_key_last macro reg ; MY_vaesdeclast reg, key_ymm_n MY_vaesdeclast reg, key_last_ymm_n endm AVX__VAES_ENC macro reg MY_vaesenc reg, key_ymm_n endm AVX__VAES_ENC_LAST macro reg MY_vaesenclast reg, key_ymm_n endm AVX__vinserti128_TO_HIGH macro dest, src vinserti128 dest, dest, src, 1 endm MY_PROC AesCbc_Decode_HW_256, 3 ifdef use_vaes_256 MY_PROLOG NUM_CBC_REGS cmp rN, ways * 2 jb AesCbc_Decode_HW_start_2 vmovdqa iv, xmmword ptr [keys] add keys, 32 vbroadcasti128 key0_ymm, xmmword ptr [keys + 1 * ksize_r] vbroadcasti128 key_last_ymm, xmmword ptr [keys] sub ksize_x, 16 mov koffs_x, ksize_x add ksize_x, ksize_x AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 2) * 32) push keys2 sub r4, AVX_STACK_SUB ; sub r4, 32 ; sub r4, ksize_r ; lea keys2, [r4 + 32] mov keys2, r4 and keys2, -32 broad: vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r] vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm sub koffs_r, 16 ; jnc broad jnz broad sub rN, ways * 2 align 16 avx_cbcdec_nextBlock2: mov koffs_x, ksize_x ; AVX__WOP_KEY AVX__CBC_START, 1 * koffs_r + 32 AVX__WOP AVX__CBC_START @@: AVX__WOP_KEY AVX__VAES_DEC, 1 * koffs_r sub koffs_r, 32 jnz @B ; AVX__WOP_KEY AVX__VAES_DEC_LAST, 0 AVX__WOP_n AVX__VAES_DEC_LAST_key_last AVX__vinserti128_TO_HIGH iv_ymm, xmmword ptr [rD] AVX__WOP AVX__CBC_END vmovdqa iv, xmmword ptr [rD + ways * 32 - 16] AVX__WOP AVX__WRITE_TO_DATA add rD, ways * 32 sub rN, ways * 2 jnc avx_cbcdec_nextBlock2 add rN, ways * 2 shr ksize_x, 1 ; lea r4, [r4 + 1 * ksize_r + 32] add r4, AVX_STACK_SUB pop keys2 vzeroupper jmp AesCbc_Decode_HW_start_3 else jmp AesCbc_Decode_HW_start endif MY_ENDP MY_SEG_ENDP ; ---------- AES-CBC Encode ---------- e0 equ xmm1 CENC_START_KEY equ 2 CENC_NUM_REG_KEYS equ (3 * 2) ; last_key equ @CatStr(xmm, %(CENC_START_KEY + CENC_NUM_REG_KEYS)) MY_SEG_PROC AesCbc_Encode_HW, 3 MY_PROLOG (CENC_START_KEY + CENC_NUM_REG_KEYS + 0) movdqa state, [keys] add keys, 32 i = 0 rept CENC_NUM_REG_KEYS movdqa @CatStr(xmm, %(CENC_START_KEY + i)), [keys + i * 16] i = i + 1 endm add keys, ksize_r neg ksize_r add ksize_r, (16 * CENC_NUM_REG_KEYS) ; movdqa last_key, [keys] jmp check_e align 16 nextBlock_e: movdqa e0, [rD] mov koffs_r, ksize_r pxor e0, @CatStr(xmm, %(CENC_START_KEY)) pxor state, e0 i = 1 rept (CENC_NUM_REG_KEYS - 1) aesenc state, @CatStr(xmm, %(CENC_START_KEY + i)) i = i + 1 endm @@: OP_KEY aesenc, 1 * koffs_r OP_KEY aesenc, 1 * koffs_r + 16 add koffs_r, 32 jnz @B OP_KEY aesenclast, 0 ; aesenclast state, last_key movdqa [rD], state add rD, 16 check_e: sub rN, 1 jnc nextBlock_e ; movdqa [keys - 32], state movdqa [keys + 1 * ksize_r - (16 * CENC_NUM_REG_KEYS) - 32], state MY_EPILOG MY_SEG_ENDP ; ---------- AES-CTR ---------- ifdef x64 ; ways = 11 endif one equ @CatStr(xmm, %(ways_start_reg + ways + 1)) one_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1)) key0 equ @CatStr(xmm, %(ways_start_reg + ways + 2)) key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2)) NUM_CTR_REGS equ (ways_start_reg + ways + 3) INIT_CTR macro reg, _ppp_ paddq iv, one movdqa reg, iv endm MY_SEG_PROC AesCtr_Code_HW, 3 Ctr_start:: MY_PROLOG NUM_CTR_REGS Ctr_start_2:: movdqa iv, [keys] add keys, 32 movdqa key0, [keys] add keys, ksize_r neg ksize_r add ksize_r, 16 Ctr_start_3:: mov koffs_x, 1 movd one, koffs_x jmp check2_c align 16 nextBlocks2_c: WOP INIT_CTR, 0 mov koffs_r, ksize_r ; WOP_KEY pxor, 1 * koffs_r -16 WOP pxor, key0 @@: WOP_KEY aesenc, 1 * koffs_r add koffs_r, 16 jnz @B WOP_KEY aesenclast, 0 WOP XOR_WITH_DATA WOP WRITE_TO_DATA add rD, ways * 16 check2_c: sub rN, ways jnc nextBlocks2_c add rN, ways sub keys, 16 add ksize_r, 16 jmp check_c ; align 16 nextBlock_c: paddq iv, one ; movdqa state, [keys + 1 * koffs_r - 16] movdqa state, key0 mov koffs_r, ksize_r pxor state, iv @@: OP_KEY aesenc, 1 * koffs_r OP_KEY aesenc, 1 * koffs_r + 16 add koffs_r, 32 jnz @B OP_KEY aesenc, 0 OP_KEY aesenclast, 16 pxor state, [rD] movdqa [rD], state add rD, 16 check_c: sub rN, 1 jnc nextBlock_c ; movdqa [keys - 32], iv movdqa [keys + 1 * ksize_r - 16 - 32], iv MY_EPILOG MY_PROC AesCtr_Code_HW_256, 3 ifdef use_vaes_256 MY_PROLOG NUM_CTR_REGS cmp rN, ways * 2 jb Ctr_start_2 vbroadcasti128 iv_ymm, xmmword ptr [keys] add keys, 32 vbroadcasti128 key0_ymm, xmmword ptr [keys] mov koffs_x, 1 vmovd one, koffs_x vpsubq iv_ymm, iv_ymm, one_ymm vpaddq one, one, one AVX__vinserti128_TO_HIGH one_ymm, one add keys, ksize_r sub ksize_x, 16 neg ksize_r mov koffs_r, ksize_r add ksize_r, ksize_r AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 1) * 32) push keys2 lea keys2, [r4 - 32] sub r4, AVX_STACK_SUB and keys2, -32 vbroadcasti128 key_ymm, xmmword ptr [keys] vmovdqa ymmword ptr [keys2], key_ymm @@: vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r] vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm add koffs_r, 16 jnz @B sub rN, ways * 2 align 16 avx_ctr_nextBlock2: mov koffs_r, ksize_r AVX__WOP AVX__CTR_START ; AVX__WOP_KEY AVX__CTR_START, 1 * koffs_r - 32 @@: AVX__WOP_KEY AVX__VAES_ENC, 1 * koffs_r add koffs_r, 32 jnz @B AVX__WOP_KEY AVX__VAES_ENC_LAST, 0 AVX__WOP AVX__XOR_WITH_DATA AVX__WOP AVX__WRITE_TO_DATA add rD, ways * 32 sub rN, ways * 2 jnc avx_ctr_nextBlock2 add rN, ways * 2 vextracti128 iv, iv_ymm, 1 sar ksize_r, 1 add r4, AVX_STACK_SUB pop keys2 vzeroupper jmp Ctr_start_3 else jmp Ctr_start endif MY_ENDP MY_SEG_ENDP end tmp41wklro_/Asm/x86/LzFindOpt.asm0000444000175000001440000003301514634302320017660 0ustar nabijaczleweliusers; LzFindOpt.asm -- ASM version of GetMatchesSpecN_2() function ; 2024-06-18: Igor Pavlov : Public domain ; ifndef x64 ; x64=1 ; .err endif include 7zAsm.asm MY_ASM_START ifndef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT if (IS_LINUX gt 0) Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1 else Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1 endif endif ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT _TEXT$LZFINDOPT SEGMENT ALIGN(64) 'CODE' MY_ALIGN macro num:req align num ; align 16 endm else MY_ALIGN macro num:req ; We expect that ".text" is aligned for 16-bytes. ; So we don't need large alignment inside our function. align 16 endm endif MY_ALIGN_16 macro MY_ALIGN 16 endm MY_ALIGN_32 macro MY_ALIGN 32 endm MY_ALIGN_64 macro MY_ALIGN 64 endm t0_L equ x0_L t0_x equ x0 t0 equ r0 t1_x equ x3 t1 equ r3 cp_x equ t1_x cp_r equ t1 m equ x5 m_r equ r5 len_x equ x6 len equ r6 diff_x equ x7 diff equ r7 len0 equ r10 len1_x equ x11 len1 equ r11 maxLen_x equ x12 maxLen equ r12 d equ r13 ptr0 equ r14 ptr1 equ r15 d_lim equ m_r cycSize equ len_x hash_lim equ len0 delta1_x equ len1_x delta1_r equ len1 delta_x equ maxLen_x delta_r equ maxLen hash equ ptr0 src equ ptr1 if (IS_LINUX gt 0) ; r1 r2 r8 r9 : win32 ; r7 r6 r2 r1 r8 r9 : linux lenLimit equ r8 lenLimit_x equ x8 ; pos_r equ r2 pos equ x2 cur equ r1 son equ r9 else lenLimit equ REG_ABI_PARAM_2 lenLimit_x equ REG_ABI_PARAM_2_x pos equ REG_ABI_PARAM_1_x cur equ REG_ABI_PARAM_0 son equ REG_ABI_PARAM_3 endif if (IS_LINUX gt 0) maxLen_OFFS equ (REG_SIZE * (6 + 1)) else cutValue_OFFS equ (REG_SIZE * (8 + 1 + 4)) d_OFFS equ (REG_SIZE + cutValue_OFFS) maxLen_OFFS equ (REG_SIZE + d_OFFS) endif hash_OFFS equ (REG_SIZE + maxLen_OFFS) limit_OFFS equ (REG_SIZE + hash_OFFS) size_OFFS equ (REG_SIZE + limit_OFFS) cycPos_OFFS equ (REG_SIZE + size_OFFS) cycSize_OFFS equ (REG_SIZE + cycPos_OFFS) posRes_OFFS equ (REG_SIZE + cycSize_OFFS) if (IS_LINUX gt 0) else cutValue_PAR equ [r0 + cutValue_OFFS] d_PAR equ [r0 + d_OFFS] endif maxLen_PAR equ [r0 + maxLen_OFFS] hash_PAR equ [r0 + hash_OFFS] limit_PAR equ [r0 + limit_OFFS] size_PAR equ [r0 + size_OFFS] cycPos_PAR equ [r0 + cycPos_OFFS] cycSize_PAR equ [r0 + cycSize_OFFS] posRes_PAR equ [r0 + posRes_OFFS] cutValue_VAR equ DWORD PTR [r4 + 8 * 0] cutValueCur_VAR equ DWORD PTR [r4 + 8 * 0 + 4] cycPos_VAR equ DWORD PTR [r4 + 8 * 1 + 0] cycSize_VAR equ DWORD PTR [r4 + 8 * 1 + 4] hash_VAR equ QWORD PTR [r4 + 8 * 2] limit_VAR equ QWORD PTR [r4 + 8 * 3] size_VAR equ QWORD PTR [r4 + 8 * 4] distances equ QWORD PTR [r4 + 8 * 5] maxLen_VAR equ QWORD PTR [r4 + 8 * 6] Old_RSP equ QWORD PTR [r4 + 8 * 7] LOCAL_SIZE equ 8 * 8 COPY_VAR_32 macro dest_var, src_var mov x3, src_var mov dest_var, x3 endm COPY_VAR_64 macro dest_var, src_var mov r3, src_var mov dest_var, r3 endm ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT ; MY_ALIGN_64 else MY_ALIGN_16 endif MY_PROC GetMatchesSpecN_2, 13 MY_PUSH_PRESERVED_ABI_REGS mov r0, RSP lea r3, [r0 - LOCAL_SIZE] and r3, -64 mov RSP, r3 mov Old_RSP, r0 if (IS_LINUX gt 0) mov d, REG_ABI_PARAM_5 ; r13 = r9 mov cutValue_VAR, REG_ABI_PARAM_4_x ; = r8 mov son, REG_ABI_PARAM_3 ; r9 = r1 mov r8, REG_ABI_PARAM_2 ; r8 = r2 mov pos, REG_ABI_PARAM_1_x ; r2 = x6 mov r1, REG_ABI_PARAM_0 ; r1 = r7 else COPY_VAR_32 cutValue_VAR, cutValue_PAR mov d, d_PAR endif COPY_VAR_64 limit_VAR, limit_PAR mov hash_lim, size_PAR mov size_VAR, hash_lim mov cp_x, cycPos_PAR mov hash, hash_PAR mov cycSize, cycSize_PAR mov cycSize_VAR, cycSize ; we want cur in (rcx). So we change the cur and lenLimit variables sub lenLimit, cur neg lenLimit_x inc lenLimit_x mov t0_x, maxLen_PAR sub t0, lenLimit mov maxLen_VAR, t0 jmp main_loop MY_ALIGN_64 fill_empty: ; ptr0 = *ptr1 = kEmptyHashValue; mov QWORD PTR [ptr1], 0 inc pos inc cp_x mov DWORD PTR [d - 4], 0 cmp d, limit_VAR jae fin cmp hash, hash_lim je fin ; MY_ALIGN_64 main_loop: ; UInt32 delta = *hash++; mov diff_x, [hash] ; delta add hash, 4 ; mov cycPos_VAR, cp_x inc cur add d, 4 mov m, pos sub m, diff_x; ; matchPos ; CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; lea ptr1, [son + 8 * cp_r] ; mov cycSize, cycSize_VAR cmp pos, cycSize jb directMode ; if (pos < cycSize_VAR) ; CYC MODE cmp diff_x, cycSize jae fill_empty ; if (delta >= cycSize_VAR) xor t0_x, t0_x mov cycPos_VAR, cp_x sub cp_x, diff_x ; jae prepare_for_tree_loop ; add cp_x, cycSize cmovb t0_x, cycSize add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0) jmp prepare_for_tree_loop directMode: cmp diff_x, pos je fill_empty ; if (delta == pos) jae fin_error ; if (delta >= pos) mov cycPos_VAR, cp_x mov cp_x, m prepare_for_tree_loop: mov len0, lenLimit mov hash_VAR, hash ; CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1; lea ptr0, [ptr1 + 4] ; UInt32 *_distances = ++d; mov distances, d neg len0 mov len1, len0 mov t0_x, cutValue_VAR mov maxLen, maxLen_VAR mov cutValueCur_VAR, t0_x MY_ALIGN_32 tree_loop: neg diff mov len, len0 cmp len1, len0 cmovb len, len1 ; len = (len1 < len0 ? len1 : len0); add diff, cur mov t0_x, [son + cp_r * 8] ; prefetch movzx t0_x, BYTE PTR [diff + 1 * len] lea cp_r, [son + cp_r * 8] cmp [cur + 1 * len], t0_L je matched_1 jb left_0 mov [ptr1], m mov m, [cp_r + 4] lea ptr1, [cp_r + 4] sub diff, cur ; FIX32 jmp next_node MY_ALIGN_32 left_0: mov [ptr0], m mov m, [cp_r] mov ptr0, cp_r sub diff, cur ; FIX32 ; jmp next_node ; ------------ NEXT NODE ------------ ; MY_ALIGN_32 next_node: mov cycSize, cycSize_VAR dec cutValueCur_VAR je finish_tree add diff_x, pos ; prev_match = pos + diff cmp m, diff_x jae fin_error ; if (new_match >= prev_match) mov diff_x, pos sub diff_x, m ; delta = pos - new_match cmp pos, cycSize jae cyc_mode_2 ; if (pos >= cycSize) mov cp_x, m test m, m jne tree_loop ; if (m != 0) finish_tree: ; ptr0 = *ptr1 = kEmptyHashValue; mov DWORD PTR [ptr0], 0 mov DWORD PTR [ptr1], 0 inc pos ; _distances[-1] = (UInt32)(d - _distances); mov t0, distances mov t1, d sub t1, t0 shr t1_x, 2 mov [t0 - 4], t1_x cmp d, limit_VAR jae fin ; if (d >= limit) mov cp_x, cycPos_VAR mov hash, hash_VAR mov hash_lim, size_VAR inc cp_x cmp hash, hash_lim jne main_loop ; if (hash != size) jmp fin MY_ALIGN_32 cyc_mode_2: cmp diff_x, cycSize jae finish_tree ; if (delta >= cycSize) mov cp_x, cycPos_VAR xor t0_x, t0_x sub cp_x, diff_x ; cp_x = cycPos - delta cmovb t0_x, cycSize add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0) jmp tree_loop MY_ALIGN_32 matched_1: inc len ; cmp len_x, lenLimit_x je short lenLimit_reach movzx t0_x, BYTE PTR [diff + 1 * len] cmp [cur + 1 * len], t0_L jne mismatch MY_ALIGN_32 match_loop: ; while (++len != lenLimit) (len[diff] != len[0]) ; inc len ; cmp len_x, lenLimit_x je short lenLimit_reach movzx t0_x, BYTE PTR [diff + 1 * len] cmp BYTE PTR [cur + 1 * len], t0_L je match_loop mismatch: jb left_2 mov [ptr1], m mov m, [cp_r + 4] lea ptr1, [cp_r + 4] mov len1, len jmp max_update MY_ALIGN_32 left_2: mov [ptr0], m mov m, [cp_r] mov ptr0, cp_r mov len0, len max_update: sub diff, cur ; restore diff cmp maxLen, len jae next_node mov maxLen, len add len, lenLimit mov [d], len_x mov t0_x, diff_x not t0_x mov [d + 4], t0_x add d, 8 jmp next_node MY_ALIGN_32 lenLimit_reach: mov delta_r, cur sub delta_r, diff lea delta1_r, [delta_r - 1] mov t0_x, [cp_r] mov [ptr1], t0_x mov t0_x, [cp_r + 4] mov [ptr0], t0_x mov [d], lenLimit_x mov [d + 4], delta1_x add d, 8 ; _distances[-1] = (UInt32)(d - _distances); mov t0, distances mov t1, d sub t1, t0 shr t1_x, 2 mov [t0 - 4], t1_x mov hash, hash_VAR mov hash_lim, size_VAR inc pos mov cp_x, cycPos_VAR inc cp_x mov d_lim, limit_VAR mov cycSize, cycSize_VAR ; if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) ; break; cmp hash, hash_lim je fin cmp d, d_lim jae fin cmp delta_x, [hash] jne main_loop movzx t0_x, BYTE PTR [diff] cmp [cur], t0_L jne main_loop ; jmp main_loop ; bypass for debug mov cycPos_VAR, cp_x shl len, 3 ; cycSize * 8 sub diff, cur ; restore diff xor t0_x, t0_x cmp cp_x, delta_x ; cmp (cycPos_VAR, delta) lea cp_r, [son + 8 * cp_r] ; dest lea src, [cp_r + 8 * diff] cmovb t0, len ; t0 = (cycPos_VAR < delta ? cycSize * 8 : 0) add src, t0 add len, son ; len = son + cycSize * 8 MY_ALIGN_32 long_loop: add hash, 4 ; *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff]; mov t0, [src] add src, 8 mov [cp_r], t0 add cp_r, 8 cmp src, len cmove src, son ; if end of (son) buffer is reached, we wrap to begin mov DWORD PTR [d], 2 mov [d + 4], lenLimit_x mov [d + 8], delta1_x add d, 12 inc cur cmp hash, hash_lim je long_footer cmp delta_x, [hash] jne long_footer movzx t0_x, BYTE PTR [diff + 1 * cur] cmp [cur], t0_L jne long_footer cmp d, d_lim jb long_loop long_footer: sub cp_r, son shr cp_r, 3 add pos, cp_x sub pos, cycPos_VAR mov cycSize, cycSize_VAR cmp d, d_lim jae fin cmp hash, hash_lim jne main_loop jmp fin fin_error: xor d, d fin: mov RSP, Old_RSP mov t0, [r4 + posRes_OFFS] mov [t0], pos mov r0, d MY_POP_PRESERVED_ABI_REGS MY_ENDP ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT _TEXT$LZFINDOPT ENDS endif end tmp41wklro_/Asm/x86/LzmaDecOpt.asm0000444000175000001440000010402614634302320020012 0ustar nabijaczleweliusers; LzmaDecOpt.asm -- ASM version of LzmaDec_DecodeReal_3() function ; 2024-06-18: Igor Pavlov : Public domain ; ; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() ; function for check at link time. ; That code is tightly coupled with LzmaDec_TryDummy() ; and with another functions in LzmaDec.c file. ; CLzmaDec structure, (probs) array layout, input and output of ; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). ifndef x64 ; x64=1 ; .err endif include 7zAsm.asm MY_ASM_START ; if Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT is defined, we use additional SEGMENT with 64-byte alignment. ; if Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT is not defined, we use default SEGMENT (where default 16-byte alignment of segment is expected). ; The performance is almost identical in our tests. ; But the performance can depend from position of lzmadec code inside instruction cache ; or micro-op cache line (depending from low address bits in 32-byte/64-byte cache lines). ; And 64-byte alignment provides a more consistent speed regardless ; of the code's position in the executable. ; But also it's possible that code without Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT can be ; slightly faster than 64-bytes aligned code in some cases, if offset of lzmadec ; code in 64-byte block after compilation provides better speed by some reason. ; Note that Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT adds an extra section to the ELF file. ; If you don't want to get that extra section, do not define Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT. ifndef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT if (IS_LINUX gt 0) Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT equ 1 else Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT equ 1 endif endif ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT _TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE' MY_ALIGN macro num:req align num ; align 16 endm else MY_ALIGN macro num:req ; We expect that ".text" is aligned for 16-bytes. ; So we don't need large alignment inside out function. align 16 endm endif MY_ALIGN_16 macro MY_ALIGN 16 endm MY_ALIGN_32 macro MY_ALIGN 32 endm MY_ALIGN_64 macro MY_ALIGN 64 endm ; _LZMA_SIZE_OPT equ 1 ; _LZMA_PROB32 equ 1 ifdef _LZMA_PROB32 PSHIFT equ 2 PLOAD macro dest, mem mov dest, dword ptr [mem] endm PSTORE macro src, mem mov dword ptr [mem], src endm else PSHIFT equ 1 PLOAD macro dest, mem movzx dest, word ptr [mem] endm PSTORE macro src, mem mov word ptr [mem], @CatStr(src, _W) endm endif PMULT equ (1 SHL PSHIFT) PMULT_HALF equ (1 SHL (PSHIFT - 1)) PMULT_2 equ (1 SHL (PSHIFT + 1)) kMatchSpecLen_Error_Data equ (1 SHL 9) ; x0 range ; x1 pbPos / (prob) TREE ; x2 probBranch / prm (MATCHED) / pbPos / cnt ; x3 sym ;====== r4 === RSP ; x5 cod ; x6 t1 NORM_CALC / probs_state / dist ; x7 t0 NORM_CALC / prob2 IF_BIT_1 ; x8 state ; x9 match (MATCHED) / sym2 / dist2 / lpMask_reg ; x10 kBitModelTotal_reg ; r11 probs ; x12 offs (MATCHED) / dic / len_temp ; x13 processedPos ; x14 bit (MATCHED) / dicPos ; r15 buf cod equ x5 cod_L equ x5_L range equ x0 state equ x8 state_R equ r8 buf equ r15 processedPos equ x13 kBitModelTotal_reg equ x10 probBranch equ x2 probBranch_R equ r2 probBranch_W equ x2_W pbPos equ x1 pbPos_R equ r1 cnt equ x2 cnt_R equ r2 lpMask_reg equ x9 dicPos equ r14 sym equ x3 sym_R equ r3 sym_L equ x3_L probs equ r11 dic equ r12 t0 equ x7 t0_W equ x7_W t0_R equ r7 prob2 equ t0 prob2_W equ t0_W t1 equ x6 t1_R equ r6 probs_state equ t1 probs_state_R equ t1_R prm equ r2 match equ x9 match_R equ r9 offs equ x12 offs_R equ r12 bit equ x14 bit_R equ r14 sym2 equ x9 sym2_R equ r9 len_temp equ x12 dist equ sym dist2 equ x9 kNumBitModelTotalBits equ 11 kBitModelTotal equ (1 SHL kNumBitModelTotalBits) kNumMoveBits equ 5 kBitModelOffset equ ((1 SHL kNumMoveBits) - 1) kTopValue equ (1 SHL 24) NORM_2 macro ; movzx t0, BYTE PTR [buf] shl cod, 8 mov cod_L, BYTE PTR [buf] shl range, 8 ; or cod, t0 inc buf endm NORM macro cmp range, kTopValue jae SHORT @F NORM_2 @@: endm ; ---------- Branch MACROS ---------- UPDATE_0 macro probsArray:req, probOffset:req, probDisp:req mov prob2, kBitModelTotal_reg sub prob2, probBranch shr prob2, kNumMoveBits add probBranch, prob2 PSTORE probBranch, probOffset * 1 + probsArray + probDisp * PMULT endm UPDATE_1 macro probsArray:req, probOffset:req, probDisp:req sub prob2, range sub cod, range mov range, prob2 mov prob2, probBranch shr probBranch, kNumMoveBits sub prob2, probBranch PSTORE prob2, probOffset * 1 + probsArray + probDisp * PMULT endm CMP_COD macro probsArray:req, probOffset:req, probDisp:req PLOAD probBranch, probOffset * 1 + probsArray + probDisp * PMULT NORM mov prob2, range shr range, kNumBitModelTotalBits imul range, probBranch cmp cod, range endm IF_BIT_1_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req CMP_COD probsArray, probOffset, probDisp jae toLabel endm IF_BIT_1 macro probsArray:req, probOffset:req, probDisp:req, toLabel:req IF_BIT_1_NOUP probsArray, probOffset, probDisp, toLabel UPDATE_0 probsArray, probOffset, probDisp endm IF_BIT_0_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req CMP_COD probsArray, probOffset, probDisp jb toLabel endm ; ---------- CMOV MACROS ---------- NORM_CALC macro prob:req NORM mov t0, range shr range, kNumBitModelTotalBits imul range, prob sub t0, range mov t1, cod sub cod, range endm PUP macro prob:req, probPtr:req sub t0, prob ; only sar works for both 16/32 bit prob modes sar t0, kNumMoveBits add t0, prob PSTORE t0, probPtr endm PUP_SUB macro prob:req, probPtr:req, symSub:req sbb sym, symSub PUP prob, probPtr endm PUP_COD macro prob:req, probPtr:req, symSub:req mov t0, kBitModelOffset cmovb cod, t1 mov t1, sym cmovb t0, kBitModelTotal_reg PUP_SUB prob, probPtr, symSub endm BIT_0 macro prob:req, probNext:req PLOAD prob, probs + 1 * PMULT PLOAD probNext, probs + 1 * PMULT_2 NORM_CALC prob cmovae range, t0 PLOAD t0, probs + 1 * PMULT_2 + PMULT cmovae probNext, t0 mov t0, kBitModelOffset cmovb cod, t1 cmovb t0, kBitModelTotal_reg mov sym, 2 PUP_SUB prob, probs + 1 * PMULT, 0 - 1 endm BIT_1 macro prob:req, probNext:req PLOAD probNext, probs + sym_R * PMULT_2 add sym, sym NORM_CALC prob cmovae range, t0 PLOAD t0, probs + sym_R * PMULT + PMULT cmovae probNext, t0 PUP_COD prob, probs + t1_R * PMULT_HALF, 0 - 1 endm BIT_2 macro prob:req, symSub:req add sym, sym NORM_CALC prob cmovae range, t0 PUP_COD prob, probs + t1_R * PMULT_HALF, symSub endm ; ---------- MATCHED LITERAL ---------- LITM_0 macro mov offs, 256 * PMULT shl match, (PSHIFT + 1) mov bit, offs and bit, match PLOAD x1, probs + 256 * PMULT + bit_R * 1 + 1 * PMULT lea prm, [probs + 256 * PMULT + bit_R * 1 + 1 * PMULT] ; lea prm, [probs + 256 * PMULT + 1 * PMULT] ; add prm, bit_R xor offs, bit add match, match NORM_CALC x1 cmovae offs, bit mov bit, match cmovae range, t0 mov t0, kBitModelOffset cmovb cod, t1 cmovb t0, kBitModelTotal_reg mov sym, 0 PUP_SUB x1, prm, -2-1 endm LITM macro and bit, offs lea prm, [probs + offs_R * 1] add prm, bit_R PLOAD x1, prm + sym_R * PMULT xor offs, bit add sym, sym add match, match NORM_CALC x1 cmovae offs, bit mov bit, match cmovae range, t0 PUP_COD x1, prm + t1_R * PMULT_HALF, - 1 endm LITM_2 macro and bit, offs lea prm, [probs + offs_R * 1] add prm, bit_R PLOAD x1, prm + sym_R * PMULT add sym, sym NORM_CALC x1 cmovae range, t0 PUP_COD x1, prm + t1_R * PMULT_HALF, 256 - 1 endm ; ---------- REVERSE BITS ---------- REV_0 macro prob:req, probNext:req ; PLOAD prob, probs + 1 * PMULT ; lea sym2_R, [probs + 2 * PMULT] ; PLOAD probNext, probs + 2 * PMULT PLOAD probNext, sym2_R NORM_CALC prob cmovae range, t0 PLOAD t0, probs + 3 * PMULT cmovae probNext, t0 cmovb cod, t1 mov t0, kBitModelOffset cmovb t0, kBitModelTotal_reg lea t1_R, [probs + 3 * PMULT] cmovae sym2_R, t1_R PUP prob, probs + 1 * PMULT endm REV_1 macro prob:req, probNext:req, step:req add sym2_R, step * PMULT PLOAD probNext, sym2_R NORM_CALC prob cmovae range, t0 PLOAD t0, sym2_R + step * PMULT cmovae probNext, t0 cmovb cod, t1 mov t0, kBitModelOffset cmovb t0, kBitModelTotal_reg lea t1_R, [sym2_R + step * PMULT] cmovae sym2_R, t1_R PUP prob, t1_R - step * PMULT_2 endm REV_2 macro prob:req, step:req sub sym2_R, probs shr sym2, PSHIFT or sym, sym2 NORM_CALC prob cmovae range, t0 lea t0, [sym - step] cmovb sym, t0 cmovb cod, t1 mov t0, kBitModelOffset cmovb t0, kBitModelTotal_reg PUP prob, probs + sym2_R * PMULT endm REV_1_VAR macro prob:req PLOAD prob, sym_R mov probs, sym_R add sym_R, sym2_R NORM_CALC prob cmovae range, t0 lea t0_R, [sym_R + 1 * sym2_R] cmovae sym_R, t0_R mov t0, kBitModelOffset cmovb cod, t1 ; mov t1, kBitModelTotal ; cmovb t0, t1 cmovb t0, kBitModelTotal_reg add sym2, sym2 PUP prob, probs endm LIT_PROBS macro lpMaskParam:req ; prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); mov t0, processedPos shl t0, 8 add sym, t0 and sym, lpMaskParam add probs_state_R, pbPos_R mov x1, LOC lc2 lea sym, dword ptr[sym_R + 2 * sym_R] add probs, Literal * PMULT shl sym, x1_L add probs, sym_R UPDATE_0 probs_state_R, 0, IsMatch inc processedPos endm kNumPosBitsMax equ 4 kNumPosStatesMax equ (1 SHL kNumPosBitsMax) kLenNumLowBits equ 3 kLenNumLowSymbols equ (1 SHL kLenNumLowBits) kLenNumHighBits equ 8 kLenNumHighSymbols equ (1 SHL kLenNumHighBits) kNumLenProbs equ (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) LenLow equ 0 LenChoice equ LenLow LenChoice2 equ (LenLow + kLenNumLowSymbols) LenHigh equ (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) kNumStates equ 12 kNumStates2 equ 16 kNumLitStates equ 7 kStartPosModelIndex equ 4 kEndPosModelIndex equ 14 kNumFullDistances equ (1 SHL (kEndPosModelIndex SHR 1)) kNumPosSlotBits equ 6 kNumLenToPosStates equ 4 kNumAlignBits equ 4 kAlignTableSize equ (1 SHL kNumAlignBits) kMatchMinLen equ 2 kMatchSpecLenStart equ (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) kStartOffset equ 1664 SpecPos equ (-kStartOffset) IsRep0Long equ (SpecPos + kNumFullDistances) RepLenCoder equ (IsRep0Long + (kNumStates2 SHL kNumPosBitsMax)) LenCoder equ (RepLenCoder + kNumLenProbs) IsMatch equ (LenCoder + kNumLenProbs) kAlign equ (IsMatch + (kNumStates2 SHL kNumPosBitsMax)) IsRep equ (kAlign + kAlignTableSize) IsRepG0 equ (IsRep + kNumStates) IsRepG1 equ (IsRepG0 + kNumStates) IsRepG2 equ (IsRepG1 + kNumStates) PosSlot equ (IsRepG2 + kNumStates) Literal equ (PosSlot + (kNumLenToPosStates SHL kNumPosSlotBits)) NUM_BASE_PROBS equ (Literal + kStartOffset) if kAlign ne 0 .err endif if NUM_BASE_PROBS ne 1984 .err endif PTR_FIELD equ dq ? CLzmaDec_Asm struct lc db ? lp db ? pb db ? _pad_ db ? dicSize dd ? probs_Spec PTR_FIELD probs_1664 PTR_FIELD dic_Spec PTR_FIELD dicBufSize PTR_FIELD dicPos_Spec PTR_FIELD buf_Spec PTR_FIELD range_Spec dd ? code_Spec dd ? processedPos_Spec dd ? checkDicSize dd ? rep0 dd ? rep1 dd ? rep2 dd ? rep3 dd ? state_Spec dd ? remainLen dd ? CLzmaDec_Asm ends CLzmaDec_Asm_Loc struct OLD_RSP PTR_FIELD lzmaPtr PTR_FIELD _pad0_ PTR_FIELD _pad1_ PTR_FIELD _pad2_ PTR_FIELD dicBufSize PTR_FIELD probs_Spec PTR_FIELD dic_Spec PTR_FIELD limit PTR_FIELD bufLimit PTR_FIELD lc2 dd ? lpMask dd ? pbMask dd ? checkDicSize dd ? _pad_ dd ? remainLen dd ? dicPos_Spec PTR_FIELD rep0 dd ? rep1 dd ? rep2 dd ? rep3 dd ? CLzmaDec_Asm_Loc ends GLOB_2 equ [sym_R].CLzmaDec_Asm. GLOB equ [r1].CLzmaDec_Asm. LOC_0 equ [r0].CLzmaDec_Asm_Loc. LOC equ [RSP].CLzmaDec_Asm_Loc. COPY_VAR macro name mov t0, GLOB_2 name mov LOC_0 name, t0 endm RESTORE_VAR macro name mov t0, LOC name mov GLOB name, t0 endm IsMatchBranch_Pre macro reg ; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; mov pbPos, LOC pbMask and pbPos, processedPos shl pbPos, (kLenNumLowBits + 1 + PSHIFT) lea probs_state_R, [probs + 1 * state_R] endm IsMatchBranch macro reg IsMatchBranch_Pre IF_BIT_1 probs_state_R, pbPos_R, IsMatch, IsMatch_label endm CheckLimits macro reg cmp buf, LOC bufLimit jae fin_OK cmp dicPos, LOC limit jae fin_OK endm ; RSP is (16x + 8) bytes aligned in WIN64-x64 ; LocalSize equ ((((SIZEOF CLzmaDec_Asm_Loc) + 7) / 16 * 16) + 8) PARAM_lzma equ REG_ABI_PARAM_0 PARAM_limit equ REG_ABI_PARAM_1 PARAM_bufLimit equ REG_ABI_PARAM_2 ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT ; MY_ALIGN_64 else MY_ALIGN_16 endif MY_PROC LzmaDec_DecodeReal_3, 3 MY_PUSH_PRESERVED_ABI_REGS lea r0, [RSP - (SIZEOF CLzmaDec_Asm_Loc)] and r0, -128 mov r5, RSP mov RSP, r0 mov LOC_0 Old_RSP, r5 mov LOC_0 lzmaPtr, PARAM_lzma mov LOC_0 remainLen, 0 ; remainLen must be ZERO mov LOC_0 bufLimit, PARAM_bufLimit mov sym_R, PARAM_lzma ; CLzmaDec_Asm_Loc pointer for GLOB_2 mov dic, GLOB_2 dic_Spec add PARAM_limit, dic mov LOC_0 limit, PARAM_limit COPY_VAR(rep0) COPY_VAR(rep1) COPY_VAR(rep2) COPY_VAR(rep3) mov dicPos, GLOB_2 dicPos_Spec add dicPos, dic mov LOC_0 dicPos_Spec, dicPos mov LOC_0 dic_Spec, dic mov x1_L, GLOB_2 pb mov t0, 1 shl t0, x1_L dec t0 mov LOC_0 pbMask, t0 ; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; ; unsigned lc = p->prop.lc; ; unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); mov x1_L, GLOB_2 lc mov x2, 100h mov t0, x2 shr x2, x1_L ; inc x1 add x1_L, PSHIFT mov LOC_0 lc2, x1 mov x1_L, GLOB_2 lp shl t0, x1_L sub t0, x2 mov LOC_0 lpMask, t0 mov lpMask_reg, t0 ; mov probs, GLOB_2 probs_Spec ; add probs, kStartOffset SHL PSHIFT mov probs, GLOB_2 probs_1664 mov LOC_0 probs_Spec, probs mov t0_R, GLOB_2 dicBufSize mov LOC_0 dicBufSize, t0_R mov x1, GLOB_2 checkDicSize mov LOC_0 checkDicSize, x1 mov processedPos, GLOB_2 processedPos_Spec mov state, GLOB_2 state_Spec shl state, PSHIFT mov buf, GLOB_2 buf_Spec mov range, GLOB_2 range_Spec mov cod, GLOB_2 code_Spec mov kBitModelTotal_reg, kBitModelTotal xor sym, sym ; if (processedPos != 0 || checkDicSize != 0) or x1, processedPos jz @f add t0_R, dic cmp dicPos, dic cmovnz t0_R, dicPos movzx sym, byte ptr[t0_R - 1] @@: IsMatchBranch_Pre cmp state, 4 * PMULT jb lit_end cmp state, kNumLitStates * PMULT jb lit_matched_end jmp lz_end ; ---------- LITERAL ---------- MY_ALIGN_64 lit_start: xor state, state lit_start_2: LIT_PROBS lpMask_reg ifdef _LZMA_SIZE_OPT PLOAD x1, probs + 1 * PMULT mov sym, 1 MY_ALIGN_16 lit_loop: BIT_1 x1, x2 mov x1, x2 cmp sym, 127 jbe lit_loop else BIT_0 x1, x2 BIT_1 x2, x1 BIT_1 x1, x2 BIT_1 x2, x1 BIT_1 x1, x2 BIT_1 x2, x1 BIT_1 x1, x2 endif BIT_2 x2, 256 - 1 ; mov dic, LOC dic_Spec mov probs, LOC probs_Spec IsMatchBranch_Pre mov byte ptr[dicPos], sym_L inc dicPos CheckLimits lit_end: IF_BIT_0_NOUP probs_state_R, pbPos_R, IsMatch, lit_start ; jmp IsMatch_label ; ---------- MATCHES ---------- ; MY_ALIGN_32 IsMatch_label: UPDATE_1 probs_state_R, pbPos_R, IsMatch IF_BIT_1 probs_state_R, 0, IsRep, IsRep_label add probs, LenCoder * PMULT add state, kNumStates * PMULT ; ---------- LEN DECODE ---------- len_decode: mov len_temp, 8 - 1 - kMatchMinLen IF_BIT_0_NOUP probs, 0, 0, len_mid_0 UPDATE_1 probs, 0, 0 add probs, (1 SHL (kLenNumLowBits + PSHIFT)) mov len_temp, -1 - kMatchMinLen IF_BIT_0_NOUP probs, 0, 0, len_mid_0 UPDATE_1 probs, 0, 0 add probs, LenHigh * PMULT - (1 SHL (kLenNumLowBits + PSHIFT)) mov sym, 1 PLOAD x1, probs + 1 * PMULT MY_ALIGN_32 len8_loop: BIT_1 x1, x2 mov x1, x2 cmp sym, 64 jb len8_loop mov len_temp, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - 1 - kMatchMinLen jmp short len_mid_2 ; we use short here for MASM that doesn't optimize that code as another assembler programs MY_ALIGN_32 len_mid_0: UPDATE_0 probs, 0, 0 add probs, pbPos_R BIT_0 x2, x1 len_mid_2: BIT_1 x1, x2 BIT_2 x2, len_temp mov probs, LOC probs_Spec cmp state, kNumStates * PMULT jb copy_match ; ---------- DECODE DISTANCE ---------- ; probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); mov t0, 3 + kMatchMinLen cmp sym, 3 + kMatchMinLen cmovb t0, sym add probs, PosSlot * PMULT - (kMatchMinLen SHL (kNumPosSlotBits + PSHIFT)) shl t0, (kNumPosSlotBits + PSHIFT) add probs, t0_R ; sym = Len ; mov LOC remainLen, sym mov len_temp, sym ifdef _LZMA_SIZE_OPT PLOAD x1, probs + 1 * PMULT mov sym, 1 MY_ALIGN_16 slot_loop: BIT_1 x1, x2 mov x1, x2 cmp sym, 32 jb slot_loop else BIT_0 x1, x2 BIT_1 x2, x1 BIT_1 x1, x2 BIT_1 x2, x1 BIT_1 x1, x2 endif mov x1, sym BIT_2 x2, 64-1 and sym, 3 mov probs, LOC probs_Spec cmp x1, 32 + kEndPosModelIndex / 2 jb short_dist ; unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); sub x1, (32 + 1 + kNumAlignBits) ; distance = (2 | (distance & 1)); or sym, 2 PLOAD x2, probs + 1 * PMULT shl sym, kNumAlignBits + 1 lea sym2_R, [probs + 2 * PMULT] jmp direct_norm ; lea t1, [sym_R + (1 SHL kNumAlignBits)] ; cmp range, kTopValue ; jb direct_norm ; ---------- DIRECT DISTANCE ---------- MY_ALIGN_32 direct_loop: shr range, 1 mov t0, cod sub cod, range cmovs cod, t0 cmovns sym, t1 comment ~ sub cod, range mov x2, cod sar x2, 31 lea sym, dword ptr [r2 + sym_R * 2 + 1] and x2, range add cod, x2 ~ dec x1 je direct_end add sym, sym direct_norm: lea t1, [sym_R + (1 SHL kNumAlignBits)] cmp range, kTopValue jae near ptr direct_loop ; we align for 32 here with "near ptr" command above NORM_2 jmp direct_loop MY_ALIGN_32 direct_end: ; prob = + kAlign; ; distance <<= kNumAlignBits; REV_0 x2, x1 REV_1 x1, x2, 2 REV_1 x2, x1, 4 REV_2 x1, 8 decode_dist_end: ; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) mov t1, LOC rep0 mov x1, LOC rep1 mov x2, LOC rep2 mov t0, LOC checkDicSize test t0, t0 cmove t0, processedPos cmp sym, t0 jae end_of_payload ; jmp end_of_payload ; for debug ; rep3 = rep2; ; rep2 = rep1; ; rep1 = rep0; ; rep0 = distance + 1; inc sym mov LOC rep0, sym ; mov sym, LOC remainLen mov sym, len_temp mov LOC rep1, t1 mov LOC rep2, x1 mov LOC rep3, x2 ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; cmp state, (kNumStates + kNumLitStates) * PMULT mov state, kNumLitStates * PMULT mov t0, (kNumLitStates + 3) * PMULT cmovae state, t0 ; ---------- COPY MATCH ---------- copy_match: ; len += kMatchMinLen; ; add sym, kMatchMinLen ; if ((rem = limit - dicPos) == 0) ; { ; p->dicPos = dicPos; ; return SZ_ERROR_DATA; ; } mov cnt_R, LOC limit sub cnt_R, dicPos jz fin_dicPos_LIMIT ; curLen = ((rem < len) ? (unsigned)rem : len); cmp cnt_R, sym_R ; cmovae cnt_R, sym_R ; 64-bit cmovae cnt, sym ; 32-bit mov dic, LOC dic_Spec mov x1, LOC rep0 mov t0_R, dicPos add dicPos, cnt_R ; processedPos += curLen; add processedPos, cnt ; len -= curLen; sub sym, cnt mov LOC remainLen, sym sub t0_R, dic ; pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); sub t0_R, r1 jae @f mov r1, LOC dicBufSize add t0_R, r1 sub r1, t0_R cmp cnt_R, r1 ja copy_match_cross @@: ; if (curLen <= dicBufSize - pos) ; ---------- COPY MATCH FAST ---------- ; Byte *dest = dic + dicPos; ; mov r1, dic ; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; ; sub t0_R, dicPos ; dicPos += curLen; ; const Byte *lim = dest + curLen; add t0_R, dic movzx sym, byte ptr[t0_R] add t0_R, cnt_R neg cnt_R ; lea r1, [dicPos - 1] copy_common: dec dicPos ; cmp LOC rep0, 1 ; je rep0Label ; t0_R - src_lim ; r1 - dest_lim - 1 ; cnt_R - (-cnt) IsMatchBranch_Pre inc cnt_R jz copy_end MY_ALIGN_16 @@: mov byte ptr[cnt_R * 1 + dicPos], sym_L movzx sym, byte ptr[cnt_R * 1 + t0_R] inc cnt_R jnz @b copy_end: lz_end_match: mov byte ptr[dicPos], sym_L inc dicPos ; IsMatchBranch_Pre CheckLimits lz_end: IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label ; ---------- LITERAL MATCHED ---------- LIT_PROBS LOC lpMask ; matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; mov x1, LOC rep0 ; mov dic, LOC dic_Spec mov LOC dicPos_Spec, dicPos ; state -= (state < 10) ? 3 : 6; lea t0, [state_R - 6 * PMULT] sub state, 3 * PMULT cmp state, 7 * PMULT cmovae state, t0 sub dicPos, dic sub dicPos, r1 jae @f add dicPos, LOC dicBufSize @@: comment ~ xor t0, t0 sub dicPos, r1 cmovb t0_R, LOC dicBufSize ~ movzx match, byte ptr[dic + dicPos * 1] ifdef _LZMA_SIZE_OPT mov offs, 256 * PMULT shl match, (PSHIFT + 1) mov bit, match mov sym, 1 MY_ALIGN_16 litm_loop: LITM cmp sym, 256 jb litm_loop sub sym, 256 else LITM_0 LITM LITM LITM LITM LITM LITM LITM_2 endif mov probs, LOC probs_Spec IsMatchBranch_Pre ; mov dic, LOC dic_Spec mov dicPos, LOC dicPos_Spec mov byte ptr[dicPos], sym_L inc dicPos CheckLimits lit_matched_end: IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label ; IsMatchBranch mov lpMask_reg, LOC lpMask sub state, 3 * PMULT jmp lit_start_2 ; ---------- REP 0 LITERAL ---------- MY_ALIGN_32 IsRep0Short_label: UPDATE_0 probs_state_R, pbPos_R, IsRep0Long ; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; mov dic, LOC dic_Spec mov t0_R, dicPos mov probBranch, LOC rep0 sub t0_R, dic sub probs, RepLenCoder * PMULT ; state = state < kNumLitStates ? 9 : 11; or state, 1 * PMULT ; the caller doesn't allow (dicPos >= limit) case for REP_SHORT ; so we don't need the following (dicPos == limit) check here: ; cmp dicPos, LOC limit ; jae fin_dicPos_LIMIT_REP_SHORT inc processedPos IsMatchBranch_Pre ; xor sym, sym ; sub t0_R, probBranch_R ; cmovb sym_R, LOC dicBufSize ; add t0_R, sym_R sub t0_R, probBranch_R jae @f add t0_R, LOC dicBufSize @@: movzx sym, byte ptr[dic + t0_R * 1] jmp lz_end_match MY_ALIGN_32 IsRep_label: UPDATE_1 probs_state_R, 0, IsRep ; The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. ; So we don't check it here. ; mov t0, processedPos ; or t0, LOC checkDicSize ; jz fin_ERROR_2 ; state = state < kNumLitStates ? 8 : 11; cmp state, kNumLitStates * PMULT mov state, 8 * PMULT mov probBranch, 11 * PMULT cmovae state, probBranch ; prob = probs + RepLenCoder; add probs, RepLenCoder * PMULT IF_BIT_1 probs_state_R, 0, IsRepG0, IsRepG0_label IF_BIT_0_NOUP probs_state_R, pbPos_R, IsRep0Long, IsRep0Short_label UPDATE_1 probs_state_R, pbPos_R, IsRep0Long jmp len_decode MY_ALIGN_32 IsRepG0_label: UPDATE_1 probs_state_R, 0, IsRepG0 mov dist2, LOC rep0 mov dist, LOC rep1 mov LOC rep1, dist2 IF_BIT_1 probs_state_R, 0, IsRepG1, IsRepG1_label mov LOC rep0, dist jmp len_decode ; MY_ALIGN_32 IsRepG1_label: UPDATE_1 probs_state_R, 0, IsRepG1 mov dist2, LOC rep2 mov LOC rep2, dist IF_BIT_1 probs_state_R, 0, IsRepG2, IsRepG2_label mov LOC rep0, dist2 jmp len_decode ; MY_ALIGN_32 IsRepG2_label: UPDATE_1 probs_state_R, 0, IsRepG2 mov dist, LOC rep3 mov LOC rep3, dist2 mov LOC rep0, dist jmp len_decode ; ---------- SPEC SHORT DISTANCE ---------- MY_ALIGN_32 short_dist: sub x1, 32 + 1 jbe decode_dist_end or sym, 2 shl sym, x1_L lea sym_R, [probs + sym_R * PMULT + SpecPos * PMULT + 1 * PMULT] mov sym2, PMULT ; step MY_ALIGN_32 spec_loop: REV_1_VAR x2 dec x1 jnz spec_loop mov probs, LOC probs_Spec sub sym, sym2 sub sym, SpecPos * PMULT sub sym_R, probs shr sym, PSHIFT jmp decode_dist_end ; ---------- COPY MATCH CROSS ---------- copy_match_cross: ; t0_R - src pos ; r1 - len to dicBufSize ; cnt_R - total copy len mov t1_R, t0_R ; srcPos mov t0_R, dic mov r1, LOC dicBufSize ; neg cnt_R @@: movzx sym, byte ptr[t1_R * 1 + t0_R] inc t1_R mov byte ptr[cnt_R * 1 + dicPos], sym_L inc cnt_R cmp t1_R, r1 jne @b movzx sym, byte ptr[t0_R] sub t0_R, cnt_R jmp copy_common ; fin_dicPos_LIMIT_REP_SHORT: ; mov sym, 1 fin_dicPos_LIMIT: mov LOC remainLen, sym jmp fin_OK ; For more strict mode we can stop decoding with error ; mov sym, 1 ; jmp fin fin_ERROR_MATCH_DIST: ; rep3 = rep2; ; rep2 = rep1; ; rep1 = rep0; ; rep0 = distance + 1; add len_temp, kMatchSpecLen_Error_Data mov LOC remainLen, len_temp mov LOC rep0, sym mov LOC rep1, t1 mov LOC rep2, x1 mov LOC rep3, x2 ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; cmp state, (kNumStates + kNumLitStates) * PMULT mov state, kNumLitStates * PMULT mov t0, (kNumLitStates + 3) * PMULT cmovae state, t0 ; jmp fin_OK mov sym, 1 jmp fin end_of_payload: inc sym jnz fin_ERROR_MATCH_DIST mov LOC remainLen, kMatchSpecLenStart sub state, kNumStates * PMULT fin_OK: xor sym, sym fin: NORM mov r1, LOC lzmaPtr sub dicPos, LOC dic_Spec mov GLOB dicPos_Spec, dicPos mov GLOB buf_Spec, buf mov GLOB range_Spec, range mov GLOB code_Spec, cod shr state, PSHIFT mov GLOB state_Spec, state mov GLOB processedPos_Spec, processedPos RESTORE_VAR(remainLen) RESTORE_VAR(rep0) RESTORE_VAR(rep1) RESTORE_VAR(rep2) RESTORE_VAR(rep3) mov x0, sym mov RSP, LOC Old_RSP MY_POP_PRESERVED_ABI_REGS MY_ENDP ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT _TEXT$LZMADECOPT ENDS endif end tmp41wklro_/Asm/x86/Sha256Opt.asm0000444000175000001440000001455714633515600017462 0ustar nabijaczleweliusers; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions ; 2024-06-16 : Igor Pavlov : Public domain include 7zAsm.asm MY_ASM_START ; .data ; public K ; we can use external SHA256_K_ARRAY defined in Sha256.c ; but we must guarantee that SHA256_K_ARRAY is aligned for 16-bytes COMMENT @ ifdef x64 K_CONST equ SHA256_K_ARRAY else K_CONST equ _SHA256_K_ARRAY endif EXTRN K_CONST:xmmword @ CONST SEGMENT READONLY align 16 Reverse_Endian_Mask db 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 ; COMMENT @ align 16 K_CONST \ DD 0428a2f98H, 071374491H, 0b5c0fbcfH, 0e9b5dba5H DD 03956c25bH, 059f111f1H, 0923f82a4H, 0ab1c5ed5H DD 0d807aa98H, 012835b01H, 0243185beH, 0550c7dc3H DD 072be5d74H, 080deb1feH, 09bdc06a7H, 0c19bf174H DD 0e49b69c1H, 0efbe4786H, 00fc19dc6H, 0240ca1ccH DD 02de92c6fH, 04a7484aaH, 05cb0a9dcH, 076f988daH DD 0983e5152H, 0a831c66dH, 0b00327c8H, 0bf597fc7H DD 0c6e00bf3H, 0d5a79147H, 006ca6351H, 014292967H DD 027b70a85H, 02e1b2138H, 04d2c6dfcH, 053380d13H DD 0650a7354H, 0766a0abbH, 081c2c92eH, 092722c85H DD 0a2bfe8a1H, 0a81a664bH, 0c24b8b70H, 0c76c51a3H DD 0d192e819H, 0d6990624H, 0f40e3585H, 0106aa070H DD 019a4c116H, 01e376c08H, 02748774cH, 034b0bcb5H DD 0391c0cb3H, 04ed8aa4aH, 05b9cca4fH, 0682e6ff3H DD 0748f82eeH, 078a5636fH, 084c87814H, 08cc70208H DD 090befffaH, 0a4506cebH, 0bef9a3f7H, 0c67178f2H ; @ CONST ENDS ; _TEXT$SHA256OPT SEGMENT 'CODE' ifndef x64 .686 .xmm endif ; jwasm-based assemblers for linux and linker from new versions of binutils ; can generate incorrect code for load [ARRAY + offset] instructions. ; 22.00: we load K_CONST offset to (rTable) register to avoid jwasm+binutils problem rTable equ r0 ; rTable equ K_CONST ifdef x64 rNum equ REG_ABI_PARAM_2 if (IS_LINUX eq 0) LOCAL_SIZE equ (16 * 2) endif else rNum equ r3 LOCAL_SIZE equ (16 * 1) endif rState equ REG_ABI_PARAM_0 rData equ REG_ABI_PARAM_1 MY_SHA_INSTR macro cmd, a1, a2 db 0fH, 038H, cmd, (0c0H + a1 * 8 + a2) endm cmd_sha256rnds2 equ 0cbH cmd_sha256msg1 equ 0ccH cmd_sha256msg2 equ 0cdH MY_sha256rnds2 macro a1, a2 MY_SHA_INSTR cmd_sha256rnds2, a1, a2 endm MY_sha256msg1 macro a1, a2 MY_SHA_INSTR cmd_sha256msg1, a1, a2 endm MY_sha256msg2 macro a1, a2 MY_SHA_INSTR cmd_sha256msg2, a1, a2 endm MY_PROLOG macro ifdef x64 if (IS_LINUX eq 0) movdqa [r4 + 8], xmm6 movdqa [r4 + 8 + 16], xmm7 sub r4, LOCAL_SIZE + 8 movdqa [r4 ], xmm8 movdqa [r4 + 16], xmm9 endif else ; x86 push r3 push r5 mov r5, r4 NUM_PUSH_REGS equ 2 PARAM_OFFSET equ (REG_SIZE * (1 + NUM_PUSH_REGS)) if (IS_CDECL gt 0) mov rState, [r4 + PARAM_OFFSET] mov rData, [r4 + PARAM_OFFSET + REG_SIZE * 1] mov rNum, [r4 + PARAM_OFFSET + REG_SIZE * 2] else ; fastcall mov rNum, [r4 + PARAM_OFFSET] endif and r4, -16 sub r4, LOCAL_SIZE endif endm MY_EPILOG macro ifdef x64 if (IS_LINUX eq 0) movdqa xmm8, [r4] movdqa xmm9, [r4 + 16] add r4, LOCAL_SIZE + 8 movdqa xmm6, [r4 + 8] movdqa xmm7, [r4 + 8 + 16] endif else ; x86 mov r4, r5 pop r5 pop r3 endif MY_ENDP endm msg equ xmm0 tmp equ xmm0 state0_N equ 2 state1_N equ 3 w_regs equ 4 state1_save equ xmm1 state0 equ @CatStr(xmm, %state0_N) state1 equ @CatStr(xmm, %state1_N) ifdef x64 state0_save equ xmm8 mask2 equ xmm9 else state0_save equ [r4] mask2 equ xmm0 endif LOAD_MASK macro movdqa mask2, XMMWORD PTR Reverse_Endian_Mask endm LOAD_W macro k:req movdqu @CatStr(xmm, %(w_regs + k)), [rData + (16 * (k))] pshufb @CatStr(xmm, %(w_regs + k)), mask2 endm ; pre1 <= 4 && pre2 >= 1 && pre1 > pre2 && (pre1 - pre2) <= 1 pre1 equ 3 pre2 equ 2 RND4 macro k movdqa msg, xmmword ptr [rTable + (k) * 16] paddd msg, @CatStr(xmm, %(w_regs + ((k + 0) mod 4))) MY_sha256rnds2 state0_N, state1_N pshufd msg, msg, 0eH if (k GE (4 - pre1)) AND (k LT (16 - pre1)) ; w4[0] = msg1(w4[-4], w4[-3]) MY_sha256msg1 (w_regs + ((k + pre1) mod 4)), (w_regs + ((k + pre1 - 3) mod 4)) endif MY_sha256rnds2 state1_N, state0_N if (k GE (4 - pre2)) AND (k LT (16 - pre2)) movdqa tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 1) mod 4))) palignr tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 2) mod 4))), 4 paddd @CatStr(xmm, %(w_regs + ((k + pre2) mod 4))), tmp ; w4[0] = msg2(w4[0], w4[-1]) MY_sha256msg2 %(w_regs + ((k + pre2) mod 4)), %(w_regs + ((k + pre2 - 1) mod 4)) endif endm REVERSE_STATE macro ; state0 ; dcba ; state1 ; hgfe pshufd tmp, state0, 01bH ; abcd pshufd state0, state1, 01bH ; efgh movdqa state1, state0 ; efgh punpcklqdq state0, tmp ; cdgh punpckhqdq state1, tmp ; abef endm MY_PROC Sha256_UpdateBlocks_HW, 3 MY_PROLOG lea rTable, [K_CONST] cmp rNum, 0 je end_c movdqu state0, [rState] ; dcba movdqu state1, [rState + 16] ; hgfe REVERSE_STATE ifdef x64 LOAD_MASK endif align 16 nextBlock: movdqa state0_save, state0 movdqa state1_save, state1 ifndef x64 LOAD_MASK endif LOAD_W 0 LOAD_W 1 LOAD_W 2 LOAD_W 3 k = 0 rept 16 RND4 k k = k + 1 endm paddd state0, state0_save paddd state1, state1_save add rData, 64 sub rNum, 1 jnz nextBlock REVERSE_STATE movdqu [rState], state0 movdqu [rState + 16], state1 end_c: MY_EPILOG ; _TEXT$SHA256OPT ENDS end tmp41wklro_/Asm/x86/XzCrc64Opt.asm0000444000175000001440000003037014534645620017712 0ustar nabijaczleweliusers; XzCrc64Opt.asm -- CRC64 calculation : optimized version ; 2023-12-08 : Igor Pavlov : Public domain include 7zAsm.asm MY_ASM_START NUM_WORDS equ 3 if (NUM_WORDS lt 1) or (NUM_WORDS gt 64) .err endif NUM_SKIP_BYTES equ ((NUM_WORDS - 2) * 4) MOVZXLO macro dest:req, src:req movzx dest, @CatStr(src, _L) endm MOVZXHI macro dest:req, src:req movzx dest, @CatStr(src, _H) endm ifdef x64 rD equ r11 rN equ r10 rT equ r9 CRC_OP macro op:req, dest:req, src:req, t:req op dest, QWORD PTR [rT + @CatStr(src, _R) * 8 + 0800h * (t)] endm CRC_XOR macro dest:req, src:req, t:req CRC_OP xor, dest, src, t endm CRC_MOV macro dest:req, src:req, t:req CRC_OP mov, dest, src, t endm CRC1b macro movzx x6, BYTE PTR [rD] inc rD MOVZXLO x3, x0 xor x6, x3 shr r0, 8 CRC_XOR r0, x6, 0 dec rN endm ; ALIGN_MASK is 3 or 7 bytes alignment: ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4) if NUM_WORDS eq 1 src_rN_offset equ 4 ; + 4 for prefetching next 4-bytes after current iteration NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 4) SRCDAT4 equ DWORD PTR [rN + rD * 1] XOR_NEXT macro mov x1, [rD] xor r0, r1 endm else ; NUM_WORDS > 1 src_rN_offset equ 8 ; + 8 for prefetching next 8-bytes after current iteration NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 8) XOR_NEXT macro xor r0, QWORD PTR [rD] ; 64-bit read, can be unaligned endm ; 32-bit or 64-bit LOAD_SRC_MULT4 macro dest:req, word_index:req mov dest, [rN + rD * 1 + 4 * (word_index) - src_rN_offset]; endm endif MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 4 MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 mov r0, REG_ABI_PARAM_0 ; r0 <- r1 / r7 mov rD, REG_ABI_PARAM_1 ; r11 <- r2 / r6 mov rN, REG_ABI_PARAM_2 ; r10 <- r8 / r2 if (IS_LINUX gt 0) mov rT, REG_ABI_PARAM_3 ; r9 <- r9 / r1 endif cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK jb crc_end @@: test rD, ALIGN_MASK jz @F CRC1b jmp @B @@: XOR_NEXT lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)] sub rD, rN add rN, src_rN_offset align 16 @@: if NUM_WORDS eq 1 mov x1, x0 shr x1, 8 MOVZXLO x3, x1 MOVZXLO x2, x0 shr x1, 8 shr r0, 32 xor x0, SRCDAT4 CRC_XOR r0, x2, 3 CRC_XOR r0, x3, 2 MOVZXLO x2, x1 shr x1, 8 CRC_XOR r0, x2, 1 CRC_XOR r0, x1, 0 else ; NUM_WORDS > 1 if NUM_WORDS ne 2 k = 2 while k lt NUM_WORDS LOAD_SRC_MULT4 x1, k crc_op1 textequ if k eq 2 if (NUM_WORDS and 1) LOAD_SRC_MULT4 x7, NUM_WORDS ; aligned 32-bit LOAD_SRC_MULT4 x6, NUM_WORDS + 1 ; aligned 32-bit shl r6, 32 else LOAD_SRC_MULT4 r6, NUM_WORDS ; aligned 64-bit crc_op1 textequ endif endif table = 4 * (NUM_WORDS - 1 - k) MOVZXLO x3, x1 CRC_OP crc_op1, r7, x3, 3 + table MOVZXHI x3, x1 shr x1, 16 CRC_XOR r6, x3, 2 + table MOVZXLO x3, x1 shr x1, 8 CRC_XOR r7, x3, 1 + table CRC_XOR r6, x1, 0 + table k = k + 1 endm crc_op2 textequ else ; NUM_WORDS == 2 LOAD_SRC_MULT4 r6, NUM_WORDS ; aligned 64-bit crc_op2 textequ endif ; NUM_WORDS == 2 MOVZXHI x3, x0 MOVZXLO x2, x0 mov r1, r0 shr r1, 32 shr x0, 16 CRC_XOR r6, x2, NUM_SKIP_BYTES + 7 CRC_OP crc_op2, r7, x3, NUM_SKIP_BYTES + 6 MOVZXLO x2, x0 MOVZXHI x5, x1 MOVZXLO x3, x1 shr x0, 8 shr x1, 16 CRC_XOR r7, x2, NUM_SKIP_BYTES + 5 CRC_XOR r6, x3, NUM_SKIP_BYTES + 3 CRC_XOR r7, x0, NUM_SKIP_BYTES + 4 CRC_XOR r6, x5, NUM_SKIP_BYTES + 2 MOVZXLO x2, x1 shr x1, 8 CRC_XOR r7, x2, NUM_SKIP_BYTES + 1 CRC_MOV r0, x1, NUM_SKIP_BYTES + 0 xor r0, r6 xor r0, r7 endif ; NUM_WORDS > 1 add rD, NUM_WORDS * 4 jnc @B sub rN, src_rN_offset add rD, rN XOR_NEXT add rN, NUM_BYTES_LIMIT - 1 sub rN, rD crc_end: test rN, rN jz func_end @@: CRC1b jnz @B func_end: MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 MY_ENDP else ; ================================================================== ; x86 (32-bit) rD equ r7 rN equ r1 rT equ r5 xA equ x6 xA_R equ r6 ifdef x64 num_VAR equ r8 else crc_OFFS equ (REG_SIZE * 5) if (IS_CDECL gt 0) or (IS_LINUX gt 0) ; cdecl or (GNU fastcall) stack: ; (UInt32 *) table ; size_t size ; void * data ; (UInt64) crc ; ret-ip <-(r4) data_OFFS equ (8 + crc_OFFS) size_OFFS equ (REG_SIZE + data_OFFS) table_OFFS equ (REG_SIZE + size_OFFS) num_VAR equ [r4 + size_OFFS] table_VAR equ [r4 + table_OFFS] else ; Windows fastcall: ; r1 = data, r2 = size ; stack: ; (UInt32 *) table ; (UInt64) crc ; ret-ip <-(r4) table_OFFS equ (8 + crc_OFFS) table_VAR equ [r4 + table_OFFS] num_VAR equ table_VAR endif endif ; x64 SRCDAT4 equ DWORD PTR [rN + rD * 1] CRC_1 macro op:req, dest:req, src:req, t:req, word_index:req op dest, DWORD PTR [rT + @CatStr(src, _R) * 8 + 0800h * (t) + (word_index) * 4] endm CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req CRC_1 op0, dest0, src, t, 0 CRC_1 op1, dest1, src, t, 1 endm CRC_XOR macro dest0:req, dest1:req, src:req, t:req CRC xor, xor, dest0, dest1, src, t endm CRC1b macro movzx xA, BYTE PTR [rD] inc rD MOVZXLO x3, x0 xor xA, x3 shrd x0, x2, 8 shr x2, 8 CRC_XOR x0, x2, xA, 0 dec rN endm MY_PROLOG_BASE macro MY_PUSH_4_REGS ifdef x64 mov r0, REG_ABI_PARAM_0 ; r0 <- r1 / r7 mov rT, REG_ABI_PARAM_3 ; r5 <- r9 / r1 mov rN, REG_ABI_PARAM_2 ; r1 <- r8 / r2 mov rD, REG_ABI_PARAM_1 ; r7 <- r2 / r6 mov r2, r0 shr r2, 32 mov x0, x0 else if (IS_CDECL gt 0) or (IS_LINUX gt 0) proc_numParams = proc_numParams + 2 ; for ABI_LINUX mov rN, [r4 + size_OFFS] mov rD, [r4 + data_OFFS] else mov rD, REG_ABI_PARAM_0 ; r7 <- r1 : (data) mov rN, REG_ABI_PARAM_1 ; r1 <- r2 : (size) endif mov x0, [r4 + crc_OFFS] mov x2, [r4 + crc_OFFS + 4] mov rT, table_VAR endif endm MY_EPILOG_BASE macro crc_end:req, func_end:req crc_end: test rN, rN jz func_end @@: CRC1b jnz @B func_end: ifdef x64 shl r2, 32 xor r0, r2 endif MY_POP_4_REGS endm ; ALIGN_MASK is 3 or 7 bytes alignment: ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4) if (NUM_WORDS eq 1) NUM_BYTES_LIMIT_T4 equ (NUM_WORDS * 4 + 4) MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 5 MY_PROLOG_BASE cmp rN, NUM_BYTES_LIMIT_T4 + ALIGN_MASK jb crc_end_4 @@: test rD, ALIGN_MASK jz @F CRC1b jmp @B @@: xor x0, [rD] lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT_T4 - 1)] sub rD, rN add rN, 4 MOVZXLO xA, x0 align 16 @@: mov x3, SRCDAT4 xor x3, x2 shr x0, 8 CRC xor, mov, x3, x2, xA, 3 MOVZXLO xA, x0 shr x0, 8 ; MOVZXHI xA, x0 ; shr x0, 16 CRC_XOR x3, x2, xA, 2 MOVZXLO xA, x0 shr x0, 8 CRC_XOR x3, x2, xA, 1 CRC_XOR x3, x2, x0, 0 MOVZXLO xA, x3 mov x0, x3 add rD, 4 jnc @B sub rN, 4 add rD, rN xor x0, [rD] add rN, NUM_BYTES_LIMIT_T4 - 1 sub rN, rD MY_EPILOG_BASE crc_end_4, func_end_4 MY_ENDP else ; NUM_WORDS > 1 SHR_X macro x, imm shr x, imm endm ITER_1 macro v0, v1, a, off MOVZXLO xA, a SHR_X a, 8 CRC_XOR v0, v1, xA, off endm ITER_4 macro v0, v1, a, off if 0 eq 0 ITER_1 v0, v1, a, off + 3 ITER_1 v0, v1, a, off + 2 ITER_1 v0, v1, a, off + 1 CRC_XOR v0, v1, a, off elseif 0 eq 0 MOVZXLO xA, a CRC_XOR v0, v1, xA, off + 3 mov xA, a ror a, 16 ; 32-bit ror shr xA, 24 CRC_XOR v0, v1, xA, off MOVZXLO xA, a SHR_X a, 24 CRC_XOR v0, v1, xA, off + 1 CRC_XOR v0, v1, a, off + 2 else ; MOVZXHI provides smaller code, but MOVZX_HI_BYTE is not fast instruction MOVZXLO xA, a CRC_XOR v0, v1, xA, off + 3 MOVZXHI xA, a SHR_X a, 16 CRC_XOR v0, v1, xA, off + 2 MOVZXLO xA, a SHR_X a, 8 CRC_XOR v0, v1, xA, off + 1 CRC_XOR v0, v1, a, off endif endm ITER_1_PAIR macro v0, v1, a0, a1, off ITER_1 v0, v1, a0, off + 4 ITER_1 v0, v1, a1, off endm src_rD_offset equ 8 STEP_SIZE equ (NUM_WORDS * 4) ITER_12_NEXT macro op, index, v0, v1 op v0, DWORD PTR [rD + (index + 1) * STEP_SIZE - src_rD_offset] op v1, DWORD PTR [rD + (index + 1) * STEP_SIZE + 4 - src_rD_offset] endm ITER_12 macro index, a0, a1, v0, v1 if NUM_SKIP_BYTES eq 0 ITER_12_NEXT mov, index, v0, v1 else k = 0 while k lt NUM_SKIP_BYTES movzx xA, BYTE PTR [rD + (index) * STEP_SIZE + k + 8 - src_rD_offset] if k eq 0 CRC mov, mov, v0, v1, xA, NUM_SKIP_BYTES - 1 - k else CRC_XOR v0, v1, xA, NUM_SKIP_BYTES - 1 - k endif k = k + 1 endm ITER_12_NEXT xor, index, v0, v1 endif if 0 eq 0 ITER_4 v0, v1, a0, NUM_SKIP_BYTES + 4 ITER_4 v0, v1, a1, NUM_SKIP_BYTES else ; interleave version is faster/slower for different processors ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 3 ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 2 ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 1 CRC_XOR v0, v1, a0, NUM_SKIP_BYTES + 4 CRC_XOR v0, v1, a1, NUM_SKIP_BYTES endif endm ; we use (UNROLL_CNT > 1) to reduce read ports pressure (num_VAR reads) UNROLL_CNT equ (2 * 1) NUM_BYTES_LIMIT equ (STEP_SIZE * UNROLL_CNT + 8) MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 5 MY_PROLOG_BASE cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK jb crc_end_12 @@: test rD, ALIGN_MASK jz @F CRC1b jmp @B @@: xor x0, [rD] xor x2, [rD + 4] add rD, src_rD_offset lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)] mov num_VAR, rN align 16 @@: i = 0 rept UNROLL_CNT if (i and 1) eq 0 ITER_12 i, x0, x2, x1, x3 else ITER_12 i, x1, x3, x0, x2 endif i = i + 1 endm if (UNROLL_CNT and 1) mov x0, x1 mov x2, x3 endif add rD, STEP_SIZE * UNROLL_CNT cmp rD, num_VAR jb @B mov rN, num_VAR add rN, NUM_BYTES_LIMIT - 1 sub rN, rD sub rD, src_rD_offset xor x0, [rD] xor x2, [rD + 4] MY_EPILOG_BASE crc_end_12, func_end_12 MY_ENDP endif ; (NUM_WORDS > 1) endif ; ! x64 end tmp41wklro_/C/0000700000175000001440000000000014706260545014324 5ustar nabijaczleweliuserstmp41wklro_/C/7z.h0000444000175000001440000001230714412260060015032 0ustar nabijaczleweliusers/* 7z.h -- 7z interface 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_H #define ZIP7_INC_7Z_H #include "7zTypes.h" EXTERN_C_BEGIN #define k7zStartHeaderSize 0x20 #define k7zSignatureSize 6 extern const Byte k7zSignature[k7zSignatureSize]; typedef struct { const Byte *Data; size_t Size; } CSzData; /* CSzCoderInfo & CSzFolder support only default methods */ typedef struct { size_t PropsOffset; UInt32 MethodID; Byte NumStreams; Byte PropsSize; } CSzCoderInfo; typedef struct { UInt32 InIndex; UInt32 OutIndex; } CSzBond; #define SZ_NUM_CODERS_IN_FOLDER_MAX 4 #define SZ_NUM_BONDS_IN_FOLDER_MAX 3 #define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 typedef struct { UInt32 NumCoders; UInt32 NumBonds; UInt32 NumPackStreams; UInt32 UnpackStream; UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; } CSzFolder; SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { Byte *Defs; /* MSB 0 bit numbering */ UInt32 *Vals; } CSzBitUi32s; typedef struct { Byte *Defs; /* MSB 0 bit numbering */ // UInt64 *Vals; CNtfsFileTime *Vals; } CSzBitUi64s; #define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) #define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) typedef struct { UInt32 NumPackStreams; UInt32 NumFolders; UInt64 *PackPositions; // NumPackStreams + 1 CSzBitUi32s FolderCRCs; // NumFolders size_t *FoCodersOffsets; // NumFolders + 1 UInt32 *FoStartPackStreamIndex; // NumFolders + 1 UInt32 *FoToCoderUnpackSizes; // NumFolders + 1 Byte *FoToMainUnpackSizeIndex; // NumFolders UInt64 *CoderUnpackSizes; // for all coders in all folders Byte *CodersData; UInt64 RangeLimit; } CSzAr; UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, ILookInStreamPtr stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAllocPtr allocMain); typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 NumFiles; UInt64 *UnpackPositions; // NumFiles + 1 // Byte *IsEmptyFiles; Byte *IsDirs; CSzBitUi32s CRCs; CSzBitUi32s Attribs; // CSzBitUi32s Parents; CSzBitUi64s MTime; CSzBitUi64s CTime; UInt32 *FolderToFile; // NumFolders + 1 UInt32 *FileToFolder; // NumFiles size_t *FileNameOffsets; /* in 2-byte steps */ Byte *FileNames; /* UTF-16-LE */ } CSzArEx; #define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) #define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* if dest == NULL, the return value specifies the required size of the buffer, in 16-bit characters, including the null-terminating character. if dest != NULL, the return value specifies the number of 16-bit characters that are written to the dest, including the null-terminating character. */ size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); /* size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); */ /* SzArEx_Extract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzArEx_Extract( const CSzArEx *db, ILookInStreamPtr inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAllocPtr allocMain, ISzAllocPtr allocTemp); /* SzArEx_Open Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp); EXTERN_C_END #endif tmp41wklro_/C/7zAlloc.c0000444000175000001440000000332714400604220015777 0ustar nabijaczleweliusers/* 7zAlloc.c -- Allocation functions for 7z processing 2023-03-04 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "7zAlloc.h" /* #define SZ_ALLOC_DEBUG */ /* use SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef SZ_ALLOC_DEBUG /* #ifdef _WIN32 #include "7zWindows.h" #endif */ #include static int g_allocCount = 0; static int g_allocCountTemp = 0; static void Print_Alloc(const char *s, size_t size, int *counter) { const unsigned size2 = (unsigned)size; fprintf(stderr, "\n%s count = %10d : %10u bytes; ", s, *counter, size2); (*counter)++; } static void Print_Free(const char *s, int *counter) { (*counter)--; fprintf(stderr, "\n%s count = %10d", s, *counter); } #endif void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) if (size == 0) return 0; #ifdef SZ_ALLOC_DEBUG Print_Alloc("Alloc", size, &g_allocCount); #endif return malloc(size); } void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) #ifdef SZ_ALLOC_DEBUG if (address) Print_Free("Free ", &g_allocCount); #endif free(address); } void *SzAllocTemp(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) if (size == 0) return 0; #ifdef SZ_ALLOC_DEBUG Print_Alloc("Alloc_temp", size, &g_allocCountTemp); /* #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif */ #endif return malloc(size); } void SzFreeTemp(ISzAllocPtr p, void *address) { UNUSED_VAR(p) #ifdef SZ_ALLOC_DEBUG if (address) Print_Free("Free_temp ", &g_allocCountTemp); /* #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif */ #endif free(address); } tmp41wklro_/C/7zAlloc.h0000444000175000001440000000061714400604220016003 0ustar nabijaczleweliusers/* 7zAlloc.h -- Allocation functions 2023-03-04 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_ALLOC_H #define ZIP7_INC_7Z_ALLOC_H #include "7zTypes.h" EXTERN_C_BEGIN void *SzAlloc(ISzAllocPtr p, size_t size); void SzFree(ISzAllocPtr p, void *address); void *SzAllocTemp(ISzAllocPtr p, size_t size); void SzFreeTemp(ISzAllocPtr p, void *address); EXTERN_C_END #endif tmp41wklro_/C/7zArcIn.c0000444000175000001440000013137014476326460015765 0ustar nabijaczleweliusers/* 7zArcIn.c -- 7z Input functions 2023-09-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "7z.h" #include "7zBuf.h" #include "7zCrc.h" #include "CpuArch.h" #define MY_ALLOC(T, p, size, alloc) \ { if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } #define MY_ALLOC_ZE(T, p, size, alloc) \ { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } #define MY_ALLOC_AND_CPY(to, size, from, alloc) \ { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } #define k7zMajorVersion 0 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttrib, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy // k7zNtSecure, // k7zParent, // k7zIsReal }; const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) { if (num == 0) { p->Defs = NULL; p->Vals = NULL; } else { MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc) MY_ALLOC(UInt32, p->Vals, num, alloc) } return SZ_OK; } static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; } #define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; } static void SzAr_Init(CSzAr *p) { p->NumPackStreams = 0; p->NumFolders = 0; p->PackPositions = NULL; SzBitUi32s_INIT(&p->FolderCRCs) p->FoCodersOffsets = NULL; p->FoStartPackStreamIndex = NULL; p->FoToCoderUnpackSizes = NULL; p->FoToMainUnpackSizeIndex = NULL; p->CoderUnpackSizes = NULL; p->CodersData = NULL; p->RangeLimit = 0; } static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->PackPositions); SzBitUi32s_Free(&p->FolderCRCs, alloc); ISzAlloc_Free(alloc, p->FoCodersOffsets); ISzAlloc_Free(alloc, p->FoStartPackStreamIndex); ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes); ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); ISzAlloc_Free(alloc, p->CoderUnpackSizes); ISzAlloc_Free(alloc, p->CodersData); SzAr_Init(p); } void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->NumFiles = 0; p->dataPos = 0; p->UnpackPositions = NULL; p->IsDirs = NULL; p->FolderToFile = NULL; p->FileToFolder = NULL; p->FileNameOffsets = NULL; p->FileNames = NULL; SzBitUi32s_INIT(&p->CRCs) SzBitUi32s_INIT(&p->Attribs) // SzBitUi32s_INIT(&p->Parents) SzBitUi64s_INIT(&p->MTime) SzBitUi64s_INIT(&p->CTime) } void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->UnpackPositions); ISzAlloc_Free(alloc, p->IsDirs); ISzAlloc_Free(alloc, p->FolderToFile); ISzAlloc_Free(alloc, p->FileToFolder); ISzAlloc_Free(alloc, p->FileNameOffsets); ISzAlloc_Free(alloc, p->FileNames); SzBitUi32s_Free(&p->CRCs, alloc); SzBitUi32s_Free(&p->Attribs, alloc); // SzBitUi32s_Free(&p->Parents, alloc); SzBitUi64s_Free(&p->MTime, alloc); SzBitUi64s_Free(&p->CTime, alloc); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } static int TestSignatureCandidate(const Byte *testBytes) { unsigned i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } #define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; } #define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \ (_sd_)->Size--; dest = *(_sd_)->Data++; #define SZ_READ_BYTE_SD(_sd_, dest) \ if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; \ SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) #define SZ_READ_BYTE_2(dest) \ if (sd.Size == 0) return SZ_ERROR_ARCHIVE; \ sd.Size--; dest = *sd.Data++; #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } #define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte, mask; unsigned i; UInt32 v; SZ_READ_BYTE(firstByte) if ((firstByte & 0x80) == 0) { *value = firstByte; return SZ_OK; } SZ_READ_BYTE(v) if ((firstByte & 0x40) == 0) { *value = (((UInt32)firstByte & 0x3F) << 8) | v; return SZ_OK; } SZ_READ_BYTE(mask) *value = v | ((UInt32)mask << 8); mask = 0x20; for (i = 2; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); *value |= (highPart << (8 * i)); return SZ_OK; } SZ_READ_BYTE(b) *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) { Byte firstByte; UInt64 value64; if (sd->Size == 0) return SZ_ERROR_ARCHIVE; firstByte = *sd->Data; if ((firstByte & 0x80) == 0) { *value = firstByte; sd->Data++; sd->Size--; return SZ_OK; } RINOK(ReadNumber(sd, &value64)) if (value64 >= (UInt32)0x80000000 - 1) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } #define ReadID(sd, value) ReadNumber(sd, value) static SRes SkipData(CSzData *sd) { UInt64 size; RINOK(ReadNumber(sd, &size)) if (size > sd->Size) return SZ_ERROR_ARCHIVE; SKIP_DATA(sd, size) return SZ_OK; } static SRes WaitId(CSzData *sd, UInt32 id) { for (;;) { UInt64 type; RINOK(ReadID(sd, &type)) if (type == id) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SkipData(sd)) } } static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) { const UInt32 numBytes = (numItems + 7) >> 3; if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; *v = sd->Data; SKIP_DATA(sd, numBytes) return SZ_OK; } static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) { unsigned b = 0; unsigned m = 0; UInt32 sum = 0; for (; numItems != 0; numItems--) { if (m == 0) { b = *bits++; m = 8; } m--; sum += (UInt32)((b >> m) & 1); } return sum; } static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) { Byte allAreDefined; Byte *v2; const UInt32 numBytes = (numItems + 7) >> 3; *v = NULL; SZ_READ_BYTE(allAreDefined) if (numBytes == 0) return SZ_OK; if (allAreDefined == 0) { if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc) SKIP_DATA(sd, numBytes) return SZ_OK; } MY_ALLOC(Byte, *v, numBytes, alloc) v2 = *v; memset(v2, 0xFF, (size_t)numBytes); { const unsigned numBits = (unsigned)numItems & 7; if (numBits != 0) v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); } return SZ_OK; } static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { UInt32 i; CSzData sd; UInt32 *vals; const Byte *defs; MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc) sd = *sd2; defs = crcs->Defs; vals = crcs->Vals; for (i = 0; i < numItems; i++) if (SzBitArray_Check(defs, i)) { SZ_READ_32(vals[i]) } else vals[i] = 0; *sd2 = sd; return SZ_OK; } static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { SzBitUi32s_Free(crcs, alloc); RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)) return ReadUi32s(sd, numItems, crcs, alloc); } static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) { Byte allAreDefined; UInt32 numDefined = numItems; SZ_READ_BYTE(allAreDefined) if (!allAreDefined) { const size_t numBytes = (numItems + 7) >> 3; if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; numDefined = CountDefinedBits(sd->Data, numItems); SKIP_DATA(sd, numBytes) } if (numDefined > (sd->Size >> 2)) return SZ_ERROR_ARCHIVE; SKIP_DATA(sd, (size_t)numDefined * 4) return SZ_OK; } static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) { RINOK(SzReadNumber32(sd, &p->NumPackStreams)) RINOK(WaitId(sd, k7zIdSize)) MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc) { UInt64 sum = 0; UInt32 i; const UInt32 numPackStreams = p->NumPackStreams; for (i = 0; i < numPackStreams; i++) { UInt64 packSize; p->PackPositions[i] = sum; RINOK(ReadNumber(sd, &packSize)) sum += packSize; if (sum < packSize) return SZ_ERROR_ARCHIVE; } p->PackPositions[i] = sum; } for (;;) { UInt64 type; RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { /* CRC of packed streams is unused now */ RINOK(SkipBitUi32s(sd, p->NumPackStreams)) continue; } RINOK(SkipData(sd)) } } /* static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } */ #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) { UInt32 numCoders, i; UInt32 numInStreams = 0; const Byte *dataStart = sd->Data; f->NumCoders = 0; f->NumBonds = 0; f->NumPackStreams = 0; f->UnpackStream = 0; RINOK(SzReadNumber32(sd, &numCoders)) if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED; for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = f->Coders + i; unsigned idSize, j; UInt64 id; SZ_READ_BYTE(mainByte) if ((mainByte & 0xC0) != 0) return SZ_ERROR_UNSUPPORTED; idSize = (unsigned)(mainByte & 0xF); if (idSize > sizeof(id)) return SZ_ERROR_UNSUPPORTED; if (idSize > sd->Size) return SZ_ERROR_ARCHIVE; id = 0; for (j = 0; j < idSize; j++) { id = ((id << 8) | *sd->Data); sd->Data++; sd->Size--; } if (id > (UInt32)0xFFFFFFFF) return SZ_ERROR_UNSUPPORTED; coder->MethodID = (UInt32)id; coder->NumStreams = 1; coder->PropsOffset = 0; coder->PropsSize = 0; if ((mainByte & 0x10) != 0) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; coder->NumStreams = (Byte)numStreams; RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams != 1) return SZ_ERROR_UNSUPPORTED; } numInStreams += coder->NumStreams; if (numInStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; if ((mainByte & 0x20) != 0) { UInt32 propsSize = 0; RINOK(SzReadNumber32(sd, &propsSize)) if (propsSize > sd->Size) return SZ_ERROR_ARCHIVE; if (propsSize >= 0x80) return SZ_ERROR_UNSUPPORTED; coder->PropsOffset = (size_t)(sd->Data - dataStart); coder->PropsSize = (Byte)propsSize; sd->Data += (size_t)propsSize; sd->Size -= (size_t)propsSize; } } /* if (numInStreams == 1 && numCoders == 1) { f->NumPackStreams = 1; f->PackStreams[0] = 0; } else */ { Byte streamUsed[k_NumCodersStreams_in_Folder_MAX]; UInt32 numBonds, numPackStreams; numBonds = numCoders - 1; if (numInStreams < numBonds) return SZ_ERROR_ARCHIVE; if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED; f->NumBonds = numBonds; numPackStreams = numInStreams - numBonds; if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED; f->NumPackStreams = numPackStreams; for (i = 0; i < numInStreams; i++) streamUsed[i] = False; if (numBonds != 0) { Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX]; for (i = 0; i < numCoders; i++) coderUsed[i] = False; for (i = 0; i < numBonds; i++) { CSzBond *bp = f->Bonds + i; RINOK(SzReadNumber32(sd, &bp->InIndex)) if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex]) return SZ_ERROR_ARCHIVE; streamUsed[bp->InIndex] = True; RINOK(SzReadNumber32(sd, &bp->OutIndex)) if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex]) return SZ_ERROR_ARCHIVE; coderUsed[bp->OutIndex] = True; } for (i = 0; i < numCoders; i++) if (!coderUsed[i]) { f->UnpackStream = i; break; } if (i == numCoders) return SZ_ERROR_ARCHIVE; } if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (!streamUsed[i]) break; if (i == numInStreams) return SZ_ERROR_ARCHIVE; f->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { UInt32 index; RINOK(SzReadNumber32(sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; f->PackStreams[i] = index; } } f->NumCoders = numCoders; return SZ_OK; } static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) { CSzData sd; sd = *sd2; for (; num != 0; num--) { Byte firstByte, mask; unsigned i; SZ_READ_BYTE_2(firstByte) if ((firstByte & 0x80) == 0) continue; if ((firstByte & 0x40) == 0) { if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; sd.Data++; continue; } mask = 0x20; for (i = 2; i < 8 && (firstByte & mask) != 0; i++) mask >>= 1; if (i > sd.Size) return SZ_ERROR_ARCHIVE; SKIP_DATA2(sd, i) } *sd2 = sd; return SZ_OK; } #define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64 static SRes ReadUnpackInfo(CSzAr *p, CSzData *sd2, UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { CSzData sd; UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; const Byte *startBufPtr; Byte external; RINOK(WaitId(sd2, k7zIdFolder)) RINOK(SzReadNumber32(sd2, &numFolders)) if (numFolders > numFoldersMax) return SZ_ERROR_UNSUPPORTED; p->NumFolders = numFolders; SZ_READ_BYTE_SD(sd2, external) if (external == 0) sd = *sd2; else { UInt32 index; RINOK(SzReadNumber32(sd2, &index)) if (index >= numTempBufs) return SZ_ERROR_ARCHIVE; sd.Data = tempBufs[index].data; sd.Size = tempBufs[index].size; } MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc) MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc) MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc) MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc) startBufPtr = sd.Data; packStreamIndex = 0; numCodersOutStreams = 0; for (fo = 0; fo < numFolders; fo++) { UInt32 numCoders, ci, numInStreams = 0; p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr); RINOK(SzReadNumber32(&sd, &numCoders)) if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) return SZ_ERROR_UNSUPPORTED; for (ci = 0; ci < numCoders; ci++) { Byte mainByte; unsigned idSize; UInt32 coderInStreams; SZ_READ_BYTE_2(mainByte) if ((mainByte & 0xC0) != 0) return SZ_ERROR_UNSUPPORTED; idSize = (mainByte & 0xF); if (idSize > 8) return SZ_ERROR_UNSUPPORTED; if (idSize > sd.Size) return SZ_ERROR_ARCHIVE; SKIP_DATA2(sd, idSize) coderInStreams = 1; if ((mainByte & 0x10) != 0) { UInt32 coderOutStreams; RINOK(SzReadNumber32(&sd, &coderInStreams)) RINOK(SzReadNumber32(&sd, &coderOutStreams)) if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1) return SZ_ERROR_UNSUPPORTED; } numInStreams += coderInStreams; if ((mainByte & 0x20) != 0) { UInt32 propsSize; RINOK(SzReadNumber32(&sd, &propsSize)) if (propsSize > sd.Size) return SZ_ERROR_ARCHIVE; SKIP_DATA2(sd, propsSize) } } { UInt32 indexOfMainStream = 0; UInt32 numPackStreams = 1; if (numCoders != 1 || numInStreams != 1) { Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX]; Byte coderUsed[k_Scan_NumCoders_MAX]; UInt32 i; const UInt32 numBonds = numCoders - 1; if (numInStreams < numBonds) return SZ_ERROR_ARCHIVE; if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; for (i = 0; i < numInStreams; i++) streamUsed[i] = False; for (i = 0; i < numCoders; i++) coderUsed[i] = False; for (i = 0; i < numBonds; i++) { UInt32 index; RINOK(SzReadNumber32(&sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; RINOK(SzReadNumber32(&sd, &index)) if (index >= numCoders || coderUsed[index]) return SZ_ERROR_ARCHIVE; coderUsed[index] = True; } numPackStreams = numInStreams - numBonds; if (numPackStreams != 1) for (i = 0; i < numPackStreams; i++) { UInt32 index; RINOK(SzReadNumber32(&sd, &index)) if (index >= numInStreams || streamUsed[index]) return SZ_ERROR_ARCHIVE; streamUsed[index] = True; } for (i = 0; i < numCoders; i++) if (!coderUsed[i]) { indexOfMainStream = i; break; } if (i == numCoders) return SZ_ERROR_ARCHIVE; } p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; numCodersOutStreams += numCoders; if (numCodersOutStreams < numCoders) return SZ_ERROR_UNSUPPORTED; if (numPackStreams > p->NumPackStreams - packStreamIndex) return SZ_ERROR_ARCHIVE; packStreamIndex += numPackStreams; } } p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; { const size_t dataSize = (size_t)(sd.Data - startBufPtr); p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoCodersOffsets[fo] = dataSize; MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc) } if (external != 0) { if (sd.Size != 0) return SZ_ERROR_ARCHIVE; sd = *sd2; } RINOK(WaitId(&sd, k7zIdCodersUnpackSize)) MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc) { UInt32 i; for (i = 0; i < numCodersOutStreams; i++) { RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)) } } for (;;) { UInt64 type; RINOK(ReadID(&sd, &type)) if (type == k7zIdEnd) { *sd2 = sd; return SZ_OK; } if (type == k7zIdCRC) { RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)) continue; } RINOK(SkipData(&sd)) } } UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) { return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]]; } typedef struct { UInt32 NumTotalSubStreams; UInt32 NumSubDigests; CSzData sdNumSubStreams; CSzData sdSizes; CSzData sdCRCs; } CSubStreamInfo; static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt64 type = 0; UInt32 numSubDigests = 0; const UInt32 numFolders = p->NumFolders; UInt32 numUnpackStreams = numFolders; UInt32 numUnpackSizesInData = 0; for (;;) { RINOK(ReadID(sd, &type)) if (type == k7zIdNumUnpackStream) { UInt32 i; ssi->sdNumSubStreams.Data = sd->Data; numUnpackStreams = 0; numSubDigests = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)) if (numUnpackStreams > numUnpackStreams + numStreams) return SZ_ERROR_UNSUPPORTED; numUnpackStreams += numStreams; if (numStreams != 0) numUnpackSizesInData += (numStreams - 1); if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) numSubDigests += numStreams; } ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data); continue; } if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) break; RINOK(SkipData(sd)) } if (!ssi->sdNumSubStreams.Data) { numSubDigests = numFolders; if (p->FolderCRCs.Defs) numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); } ssi->NumTotalSubStreams = numUnpackStreams; ssi->NumSubDigests = numSubDigests; if (type == k7zIdSize) { ssi->sdSizes.Data = sd->Data; RINOK(SkipNumbers(sd, numUnpackSizesInData)) ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data); RINOK(ReadID(sd, &type)) } for (;;) { if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { ssi->sdCRCs.Data = sd->Data; RINOK(SkipBitUi32s(sd, numSubDigests)) ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); } else { RINOK(SkipData(sd)) } RINOK(ReadID(sd, &type)) } } static SRes SzReadStreamsInfo(CSzAr *p, CSzData *sd, UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, UInt64 *dataOffset, CSubStreamInfo *ssi, ISzAllocPtr alloc) { UInt64 type; SzData_CLEAR(&ssi->sdSizes) SzData_CLEAR(&ssi->sdCRCs) SzData_CLEAR(&ssi->sdNumSubStreams) *dataOffset = 0; RINOK(ReadID(sd, &type)) if (type == k7zIdPackInfo) { RINOK(ReadNumber(sd, dataOffset)) if (*dataOffset > p->RangeLimit) return SZ_ERROR_ARCHIVE; RINOK(ReadPackInfo(p, sd, alloc)) if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset) return SZ_ERROR_ARCHIVE; RINOK(ReadID(sd, &type)) } if (type == k7zIdUnpackInfo) { RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)) RINOK(ReadID(sd, &type)) } if (type == k7zIdSubStreamsInfo) { RINOK(ReadSubStreamsInfo(p, sd, ssi)) RINOK(ReadID(sd, &type)) } else { ssi->NumTotalSubStreams = p->NumFolders; // ssi->NumSubDigests = 0; } return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); } static SRes SzReadAndDecodePackedStreams( ILookInStreamPtr inStream, CSzData *sd, CBuf *tempBufs, UInt32 numFoldersMax, UInt64 baseOffset, CSzAr *p, ISzAllocPtr allocTemp) { UInt64 dataStartPos; UInt32 fo; CSubStreamInfo ssi; RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)) dataStartPos += baseOffset; if (p->NumFolders == 0) return SZ_ERROR_ARCHIVE; for (fo = 0; fo < p->NumFolders; fo++) Buf_Init(tempBufs + fo); for (fo = 0; fo < p->NumFolders; fo++) { CBuf *tempBuf = tempBufs + fo; const UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo); if ((size_t)unpackSize != unpackSize) return SZ_ERROR_MEM; if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; } for (fo = 0; fo < p->NumFolders; fo++) { const CBuf *tempBuf = tempBufs + fo; RINOK(LookInStream_SeekTo(inStream, dataStartPos)) RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)) } return SZ_OK; } static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) { size_t pos = 0; *offsets++ = 0; if (numFiles == 0) return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; if (size < 2) return SZ_ERROR_ARCHIVE; if (data[size - 2] != 0 || data[size - 1] != 0) return SZ_ERROR_ARCHIVE; do { const Byte *p; if (pos == size) return SZ_ERROR_ARCHIVE; for (p = data + pos; #ifdef _WIN32 *(const UInt16 *)(const void *)p != 0 #else p[0] != 0 || p[1] != 0 #endif ; p += 2); pos = (size_t)(p - data) + 2; *offsets++ = (pos >> 1); } while (--numFiles); return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; } static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, CSzData *sd2, const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { CSzData sd; UInt32 i; CNtfsFileTime *vals; Byte *defs; Byte external; RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)) SZ_READ_BYTE_SD(sd2, external) if (external == 0) sd = *sd2; else { UInt32 index; RINOK(SzReadNumber32(sd2, &index)) if (index >= numTempBufs) return SZ_ERROR_ARCHIVE; sd.Data = tempBufs[index].data; sd.Size = tempBufs[index].size; } MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc) vals = p->Vals; defs = p->Defs; for (i = 0; i < num; i++) if (SzBitArray_Check(defs, i)) { if (sd.Size < 8) return SZ_ERROR_ARCHIVE; vals[i].Low = GetUi32(sd.Data); vals[i].High = GetUi32(sd.Data + 4); SKIP_DATA2(sd, 8) } else vals[i].High = vals[i].Low = 0; if (external == 0) *sd2 = sd; return SZ_OK; } #define NUM_ADDITIONAL_STREAMS_MAX 8 static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, ILookInStreamPtr inStream, CBuf *tempBufs, UInt32 *numTempBufs, ISzAllocPtr allocMain, ISzAllocPtr allocTemp ) { CSubStreamInfo ssi; { UInt64 type; SzData_CLEAR(&ssi.sdSizes) SzData_CLEAR(&ssi.sdCRCs) SzData_CLEAR(&ssi.sdNumSubStreams) ssi.NumSubDigests = 0; ssi.NumTotalSubStreams = 0; RINOK(ReadID(sd, &type)) if (type == k7zIdArchiveProperties) { for (;;) { UInt64 type2; RINOK(ReadID(sd, &type2)) if (type2 == k7zIdEnd) break; RINOK(SkipData(sd)) } RINOK(ReadID(sd, &type)) } if (type == k7zIdAdditionalStreamsInfo) { CSzAr tempAr; SRes res; SzAr_Init(&tempAr); tempAr.RangeLimit = p->db.RangeLimit; res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, p->startPosAfterHeader, &tempAr, allocTemp); *numTempBufs = tempAr.NumFolders; SzAr_Free(&tempAr, allocTemp); if (res != SZ_OK) return res; RINOK(ReadID(sd, &type)) } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, &p->dataPos, &ssi, allocMain)) p->dataPos += p->startPosAfterHeader; RINOK(ReadID(sd, &type)) } if (type == k7zIdEnd) { return SZ_OK; } if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; } { UInt32 numFiles = 0; UInt32 numEmptyStreams = 0; const Byte *emptyStreams = NULL; const Byte *emptyFiles = NULL; RINOK(SzReadNumber32(sd, &numFiles)) p->NumFiles = numFiles; for (;;) { UInt64 type; UInt64 size; RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break; RINOK(ReadNumber(sd, &size)) if (size > sd->Size) return SZ_ERROR_ARCHIVE; if (type >= ((UInt32)1 << 8)) { SKIP_DATA(sd, size) } else switch ((unsigned)type) { case k7zIdName: { size_t namesSize; const Byte *namesData; Byte external; SZ_READ_BYTE(external) if (external == 0) { namesSize = (size_t)size - 1; namesData = sd->Data; } else { UInt32 index; RINOK(SzReadNumber32(sd, &index)) if (index >= *numTempBufs) return SZ_ERROR_ARCHIVE; namesData = (tempBufs)[index].data; namesSize = (tempBufs)[index].size; } if ((namesSize & 1) != 0) return SZ_ERROR_ARCHIVE; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain) MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain) RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) if (external == 0) { SKIP_DATA(sd, namesSize) } break; } case k7zIdEmptyStream: { RINOK(RememberBitVector(sd, numFiles, &emptyStreams)) numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); emptyFiles = NULL; break; } case k7zIdEmptyFile: { RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)) break; } case k7zIdWinAttrib: { Byte external; CSzData sdSwitch; CSzData *sdPtr; SzBitUi32s_Free(&p->Attribs, allocMain); RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)) SZ_READ_BYTE(external) if (external == 0) sdPtr = sd; else { UInt32 index; RINOK(SzReadNumber32(sd, &index)) if (index >= *numTempBufs) return SZ_ERROR_ARCHIVE; sdSwitch.Data = (tempBufs)[index].data; sdSwitch.Size = (tempBufs)[index].size; sdPtr = &sdSwitch; } RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)) break; } /* case k7zParent: { SzBitUi32s_Free(&p->Parents, allocMain); RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); RINOK(SzReadSwitch(sd)); RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); break; } */ case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; default: { SKIP_DATA(sd, size) } } } if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) return SZ_ERROR_ARCHIVE; for (;;) { UInt64 type; RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break; RINOK(SkipData(sd)) } { UInt32 i; UInt32 emptyFileIndex = 0; UInt32 folderIndex = 0; UInt32 remSubStreams = 0; UInt32 numSubStreams = 0; UInt64 unpackPos = 0; const Byte *digestsDefs = NULL; const Byte *digestsVals = NULL; UInt32 digestIndex = 0; Byte isDirMask = 0; Byte crcMask = 0; Byte mask = 0x80; MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain) MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain) MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain) MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain) RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)) if (ssi.sdCRCs.Size != 0) { Byte allDigestsDefined = 0; SZ_READ_BYTE_SD_NOCHECK(&ssi.sdCRCs, allDigestsDefined) if (allDigestsDefined) digestsVals = ssi.sdCRCs.Data; else { const size_t numBytes = (ssi.NumSubDigests + 7) >> 3; digestsDefs = ssi.sdCRCs.Data; digestsVals = digestsDefs + numBytes; } } for (i = 0; i < numFiles; i++, mask >>= 1) { if (mask == 0) { const UInt32 byteIndex = (i - 1) >> 3; p->IsDirs[byteIndex] = isDirMask; p->CRCs.Defs[byteIndex] = crcMask; isDirMask = 0; crcMask = 0; mask = 0x80; } p->UnpackPositions[i] = unpackPos; p->CRCs.Vals[i] = 0; if (emptyStreams && SzBitArray_Check(emptyStreams, i)) { if (emptyFiles) { if (!SzBitArray_Check(emptyFiles, emptyFileIndex)) isDirMask |= mask; emptyFileIndex++; } else isDirMask |= mask; if (remSubStreams == 0) { p->FileToFolder[i] = (UInt32)-1; continue; } } if (remSubStreams == 0) { for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderToFile[folderIndex] = i; numSubStreams = 1; if (ssi.sdNumSubStreams.Data) { RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)) } remSubStreams = numSubStreams; if (numSubStreams != 0) break; { const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); unpackPos += folderUnpackSize; if (unpackPos < folderUnpackSize) return SZ_ERROR_ARCHIVE; } folderIndex++; } } p->FileToFolder[i] = folderIndex; if (emptyStreams && SzBitArray_Check(emptyStreams, i)) continue; if (--remSubStreams == 0) { const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); const UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]]; if (folderUnpackSize < unpackPos - startFolderUnpackPos) return SZ_ERROR_ARCHIVE; unpackPos = startFolderUnpackPos + folderUnpackSize; if (unpackPos < folderUnpackSize) return SZ_ERROR_ARCHIVE; if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex)) { p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; crcMask |= mask; } folderIndex++; } else { UInt64 v; RINOK(ReadNumber(&ssi.sdSizes, &v)) unpackPos += v; if (unpackPos < v) return SZ_ERROR_ARCHIVE; } if ((crcMask & mask) == 0 && digestsVals) { if (!digestsDefs || SzBitArray_Check(digestsDefs, digestIndex)) { p->CRCs.Vals[i] = GetUi32(digestsVals); digestsVals += 4; crcMask |= mask; } digestIndex++; } } if (mask != 0x80) { const UInt32 byteIndex = (i - 1) >> 3; p->IsDirs[byteIndex] = isDirMask; p->CRCs.Defs[byteIndex] = crcMask; } p->UnpackPositions[i] = unpackPos; if (remSubStreams != 0) return SZ_ERROR_ARCHIVE; for (;;) { p->FolderToFile[folderIndex] = i; if (folderIndex >= p->db.NumFolders) break; if (!ssi.sdNumSubStreams.Data) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)) if (numSubStreams != 0) return SZ_ERROR_ARCHIVE; /* { UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); unpackPos += folderUnpackSize; if (unpackPos < folderUnpackSize) return SZ_ERROR_ARCHIVE; } */ folderIndex++; } if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0) return SZ_ERROR_ARCHIVE; } } return SZ_OK; } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { UInt32 i; UInt32 numTempBufs = 0; SRes res; CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Init(tempBufs + i); res = SzReadHeader2(p, sd, inStream, tempBufs, &numTempBufs, allocMain, allocTemp); for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Free(tempBufs + i, allocTemp); RINOK(res) if (sd->Size != 0) return SZ_ERROR_FAIL; return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { Byte header[k7zStartHeaderSize]; Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buf; SRes res; startArcPos = 0; RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)) RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)) if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; p->db.RangeLimit = nextHeaderOffset; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)) if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset || (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)) if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buf.data; sd.Size = buf.size; res = ReadID(&sd, &type); if (res == SZ_OK && type == k7zIdEncodedHeader) { CSzAr tempAr; CBuf tempBuf; Buf_Init(&tempBuf); SzAr_Init(&tempAr); tempAr.RangeLimit = p->db.RangeLimit; res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); SzAr_Free(&tempAr, allocTemp); if (res != SZ_OK) { Buf_Free(&tempBuf, allocTemp); } else { Buf_Free(&buf, allocTemp); buf.data = tempBuf.data; buf.size = tempBuf.size; sd.Data = buf.data; sd.Size = buf.size; res = ReadID(&sd, &type); } } if (res == SZ_OK) { if (type == k7zIdHeader) { /* CSzData sd2; unsigned ttt; for (ttt = 0; ttt < 40000; ttt++) { SzArEx_Free(p, allocMain); sd2 = sd; res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp); if (res != SZ_OK) break; } */ res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp); } else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buf, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { const SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } SRes SzArEx_Extract( const CSzArEx *p, ILookInStreamPtr inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **tempBuf, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { const UInt32 folderIndex = p->FileToFolder[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { ISzAlloc_Free(allocMain, *tempBuf); *blockIndex = folderIndex; *tempBuf = NULL; *outBufferSize = 0; return SZ_OK; } if (*tempBuf == NULL || *blockIndex != folderIndex) { const UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); /* UInt64 unpackSizeSpec = p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] - p->UnpackPositions[p->FolderToFile[folderIndex]]; */ const size_t unpackSize = (size_t)unpackSizeSpec; if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; ISzAlloc_Free(allocMain, *tempBuf); *tempBuf = NULL; if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize); if (*tempBuf == NULL) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzAr_DecodeFolder(&p->db, folderIndex, inStream, p->dataPos, *tempBuf, unpackSize, allocTemp); } } } if (res == SZ_OK) { const UInt64 unpackPos = p->UnpackPositions[fileIndex]; *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]); *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos); if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; if (SzBitWithVals_Check(&p->CRCs, fileIndex)) if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) res = SZ_ERROR_CRC; } return res; } size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) { const size_t offs = p->FileNameOffsets[fileIndex]; const size_t len = p->FileNameOffsets[fileIndex + 1] - offs; if (dest != 0) { size_t i; const Byte *src = p->FileNames + offs * 2; for (i = 0; i < len; i++) dest[i] = GetUi16(src + i * 2); } return len; } /* size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) { size_t len; if (!p->FileNameOffsets) return 1; len = 0; for (;;) { UInt32 parent = (UInt32)(Int32)-1; len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; if SzBitWithVals_Check(&p->Parents, fileIndex) parent = p->Parents.Vals[fileIndex]; if (parent == (UInt32)(Int32)-1) return len; fileIndex = parent; } } UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) { BoolInt needSlash; if (!p->FileNameOffsets) { *(--dest) = 0; return dest; } needSlash = False; for (;;) { UInt32 parent = (UInt32)(Int32)-1; size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); if (needSlash) *(dest - 1) = '/'; needSlash = True; dest -= curLen; if SzBitWithVals_Check(&p->Parents, fileIndex) parent = p->Parents.Vals[fileIndex]; if (parent == (UInt32)(Int32)-1) return dest; fileIndex = parent; } } */ tmp41wklro_/C/7zBuf.c0000444000175000001440000000106613070443520015465 0ustar nabijaczleweliusers/* 7zBuf.c -- Byte Buffer 2017-04-03 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)ISzAlloc_Alloc(alloc, size); if (p->data) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->data); p->data = 0; p->size = 0; } tmp41wklro_/C/7zBuf.h0000444000175000001440000000123514400622260015466 0ustar nabijaczleweliusers/* 7zBuf.h -- Byte Buffer 2023-03-04 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_BUF_H #define ZIP7_INC_7Z_BUF_H #include "7zTypes.h" EXTERN_C_BEGIN typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc); void Buf_Free(CBuf *p, ISzAllocPtr alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc); void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc); EXTERN_C_END #endif tmp41wklro_/C/7zBuf2.c0000444000175000001440000000171213070443520015545 0ustar nabijaczleweliusers/* 7zBuf2.c -- Byte Buffer 2017-04-03 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)ISzAlloc_Alloc(alloc, newSize); if (!data) return 0; p->size = newSize; if (p->pos != 0) memcpy(data, p->data, p->pos); ISzAlloc_Free(alloc, p->data); p->data = data; } if (size != 0) { memcpy(p->data + p->pos, buf, size); p->pos += size; } return 1; } void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } tmp41wklro_/C/7zCrc.c0000444000175000001440000002536314570267340015500 0ustar nabijaczleweliusers/* 7zCrc.c -- CRC32 calculation and init 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "7zCrc.h" #include "CpuArch.h" // for debug: // #define __ARM_FEATURE_CRC32 1 #ifdef __ARM_FEATURE_CRC32 // #pragma message("__ARM_FEATURE_CRC32") #define Z7_CRC_HW_FORCE #endif // #define Z7_CRC_DEBUG_BE #ifdef Z7_CRC_DEBUG_BE #undef MY_CPU_LE #define MY_CPU_BE #endif #ifdef Z7_CRC_HW_FORCE #define Z7_CRC_NUM_TABLES_USE 1 #else #ifdef Z7_CRC_NUM_TABLES #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES #else #define Z7_CRC_NUM_TABLES_USE 12 #endif #endif #if Z7_CRC_NUM_TABLES_USE < 1 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES #endif #if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1) #define Z7_CRC_NUM_TABLES_TOTAL Z7_CRC_NUM_TABLES_USE #else #define Z7_CRC_NUM_TABLES_TOTAL (Z7_CRC_NUM_TABLES_USE + 1) #endif #ifndef Z7_CRC_HW_FORCE #if Z7_CRC_NUM_TABLES_USE == 1 \ || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define Z7_CRC_UPDATE_T1_FUNC_NAME CrcUpdateGT1 static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size) { const UInt32 *table = g_CrcTable; const Byte *p = (const Byte *)data; const Byte *lim = p + size; for (; p != lim; p++) v = CRC_UPDATE_BYTE_2(v, *p); return v; } #endif #if Z7_CRC_NUM_TABLES_USE != 1 #ifndef MY_CPU_BE #define FUNC_NAME_LE_2(s) CrcUpdateT ## s #define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s) #define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE) UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table); #endif #ifndef MY_CPU_LE #define FUNC_NAME_BE_2(s) CrcUpdateT1_BeT ## s #define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s) #define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE) UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table); #endif #endif #endif // Z7_CRC_HW_FORCE /* ---------- hardware CRC ---------- */ #ifdef MY_CPU_LE #if defined(MY_CPU_ARM_OR_ARM64) // #pragma message("ARM*") #if (defined(__clang__) && (__clang_major__ >= 3)) \ || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \ || defined(__GNUC__) && (__GNUC__ >= 8) #if !defined(__ARM_FEATURE_CRC32) // #pragma message("!defined(__ARM_FEATURE_CRC32)") Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define __ARM_FEATURE_CRC32 1 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #define Z7_ARM_FEATURE_CRC32_WAS_SET #if defined(__clang__) #if defined(MY_CPU_ARM64) #define ATTRIB_CRC __attribute__((__target__("crc"))) #else #define ATTRIB_CRC __attribute__((__target__("armv8-a,crc"))) #endif #else #if defined(MY_CPU_ARM64) #if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000) #define ATTRIB_CRC __attribute__((__target__("+crc"))) #endif #else #if !defined(Z7_GCC_VERSION) || (__GNUC__ >= 8) #if defined(__ARM_FP) && __GNUC__ >= 8 // for -mfloat-abi=hard: similar to #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd"))) #else #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) #endif #endif #endif #endif #endif #if defined(__ARM_FEATURE_CRC32) // #pragma message("") /* arm_acle.h (GGC): before Nov 17, 2017: #ifdef __ARM_FEATURE_CRC32 Nov 17, 2017: gcc10.0 (gcc 9.2.0) checked" #if __ARM_ARCH >= 8 #pragma GCC target ("arch=armv8-a+crc") Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1: #ifdef __ARM_FEATURE_CRC32 #ifdef __ARM_FP #pragma GCC target ("arch=armv8-a+crc+simd") #else #pragma GCC target ("arch=armv8-a+crc") #endif */ #if defined(__ARM_ARCH) && __ARM_ARCH < 8 #if defined(Z7_GCC_VERSION) && (__GNUC__ == 8) && (Z7_GCC_VERSION < 80400) \ || defined(Z7_GCC_VERSION) && (__GNUC__ == 9) && (Z7_GCC_VERSION < 90201) \ || defined(Z7_GCC_VERSION) && (__GNUC__ == 10) && (Z7_GCC_VERSION < 100100) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER // #pragma message("#define __ARM_ARCH 8") #undef __ARM_ARCH #define __ARM_ARCH 8 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif #define Z7_CRC_HW_USE #include #endif #elif defined(_MSC_VER) #if defined(MY_CPU_ARM64) #if (_MSC_VER >= 1910) #ifdef __clang__ // #define Z7_CRC_HW_USE // #include #else #define Z7_CRC_HW_USE #include #endif #endif #endif #endif #else // non-ARM* // #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code #ifdef Z7_CRC_HW_USE #include "7zCrcEmu.h" #endif #endif // non-ARM* #if defined(Z7_CRC_HW_USE) // #pragma message("USE ARM HW CRC") #ifdef MY_CPU_64BIT #define CRC_HW_WORD_TYPE UInt64 #define CRC_HW_WORD_FUNC __crc32d #else #define CRC_HW_WORD_TYPE UInt32 #define CRC_HW_WORD_FUNC __crc32w #endif #define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4) #ifdef ATTRIB_CRC ATTRIB_CRC #endif Z7_NO_INLINE #ifdef Z7_CRC_HW_FORCE UInt32 Z7_FASTCALL CrcUpdate #else static UInt32 Z7_FASTCALL CrcUpdate_HW #endif (UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--) v = __crc32b(v, *p++); if (size >= CRC_HW_UNROLL_BYTES) { const Byte *lim = p + size; size &= CRC_HW_UNROLL_BYTES - 1; lim -= size; do { v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p)); v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE))); p += 2 * sizeof(CRC_HW_WORD_TYPE); v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p)); v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE))); p += 2 * sizeof(CRC_HW_WORD_TYPE); } while (p != lim); } for (; size != 0; size--) v = __crc32b(v, *p++); return v; } #ifdef Z7_ARM_FEATURE_CRC32_WAS_SET Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #undef __ARM_FEATURE_CRC32 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #undef Z7_ARM_FEATURE_CRC32_WAS_SET #endif #endif // defined(Z7_CRC_HW_USE) #endif // MY_CPU_LE #ifndef Z7_CRC_HW_FORCE #if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) /* typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC) (UInt32 v, const void *data, size_t size, const UInt32 *table); Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate; */ static unsigned g_Crc_Algo; #if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) static unsigned g_Crc_Be; #endif #endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) Z7_NO_INLINE #ifdef Z7_CRC_HW_USE static UInt32 Z7_FASTCALL CrcUpdate_Base #else UInt32 Z7_FASTCALL CrcUpdate #endif (UInt32 crc, const void *data, size_t size) { #if Z7_CRC_NUM_TABLES_USE == 1 return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size); #else // Z7_CRC_NUM_TABLES_USE != 1 #ifdef Z7_CRC_UPDATE_T1_FUNC_NAME if (g_Crc_Algo == 1) return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size); #endif #ifdef MY_CPU_LE return FUNC_NAME_LE(crc, data, size, g_CrcTable); #elif defined(MY_CPU_BE) return FUNC_NAME_BE(crc, data, size, g_CrcTable); #else if (g_Crc_Be) return FUNC_NAME_BE(crc, data, size, g_CrcTable); else return FUNC_NAME_LE(crc, data, size, g_CrcTable); #endif #endif // Z7_CRC_NUM_TABLES_USE != 1 } #ifdef Z7_CRC_HW_USE Z7_NO_INLINE UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size) { if (g_Crc_Algo == 0) return CrcUpdate_HW(crc, data, size); return CrcUpdate_Base(crc, data, size); } #endif #endif // !defined(Z7_CRC_HW_FORCE) UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL; } MY_ALIGN(64) UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL]; void Z7_FASTCALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { #if defined(Z7_CRC_HW_FORCE) g_CrcTable[i] = __crc32b(i, 0); #else #define kCrcPoly 0xEDB88320 UInt32 r = i; unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); g_CrcTable[i] = r; #endif } for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++) { const UInt32 r = g_CrcTable[(size_t)i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } #if !defined(Z7_CRC_HW_FORCE) && \ (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE)) #if Z7_CRC_NUM_TABLES_USE <= 1 g_Crc_Algo = 1; #else // Z7_CRC_NUM_TABLES_USE <= 1 #if defined(MY_CPU_LE) g_Crc_Algo = Z7_CRC_NUM_TABLES_USE; #else // !defined(MY_CPU_LE) { #ifndef MY_CPU_BE UInt32 k = 0x01020304; const Byte *p = (const Byte *)&k; if (p[0] == 4 && p[1] == 3) g_Crc_Algo = Z7_CRC_NUM_TABLES_USE; else if (p[0] != 1 || p[1] != 2) g_Crc_Algo = 1; else #endif // MY_CPU_BE { for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--) { const UInt32 x = g_CrcTable[(size_t)i - 256]; g_CrcTable[i] = Z7_BSWAP32(x); } #if defined(Z7_CRC_UPDATE_T1_FUNC_NAME) g_Crc_Algo = Z7_CRC_NUM_TABLES_USE; #endif #if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) g_Crc_Be = 1; #endif } } #endif // !defined(MY_CPU_LE) #ifdef MY_CPU_LE #ifdef Z7_CRC_HW_USE if (CPU_IsSupported_CRC32()) g_Crc_Algo = 0; #endif // Z7_CRC_HW_USE #endif // MY_CPU_LE #endif // Z7_CRC_NUM_TABLES_USE <= 1 #endif // g_Crc_Algo was declared } Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo) { if (algo == 0) return &CrcUpdate; #if defined(Z7_CRC_HW_USE) if (algo == sizeof(CRC_HW_WORD_TYPE) * 8) { #ifdef Z7_CRC_HW_FORCE return &CrcUpdate; #else if (g_Crc_Algo == 0) return &CrcUpdate_HW; #endif } #endif #ifndef Z7_CRC_HW_FORCE if (algo == Z7_CRC_NUM_TABLES_USE) return #ifdef Z7_CRC_HW_USE &CrcUpdate_Base; #else &CrcUpdate; #endif #endif return NULL; } #undef kCrcPoly #undef Z7_CRC_NUM_TABLES_USE #undef Z7_CRC_NUM_TABLES_TOTAL #undef CRC_UPDATE_BYTE_2 #undef FUNC_NAME_LE_2 #undef FUNC_NAME_LE_1 #undef FUNC_NAME_LE #undef FUNC_NAME_BE_2 #undef FUNC_NAME_BE_1 #undef FUNC_NAME_BE #undef CRC_HW_UNROLL_BYTES #undef CRC_HW_WORD_FUNC #undef CRC_HW_WORD_TYPE tmp41wklro_/C/7zCrc.h0000444000175000001440000000143714553463320015476 0ustar nabijaczleweliusers/* 7zCrc.h -- CRC32 calculation 2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_CRC_H #define ZIP7_INC_7Z_CRC_H #include "7zTypes.h" EXTERN_C_BEGIN extern UInt32 g_CrcTable[]; /* Call CrcGenerateTable one time before other CRC functions */ void Z7_FASTCALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size); typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size); Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo); EXTERN_C_END #endif tmp41wklro_/C/7zCrcOpt.c0000444000175000001440000001150614534375020016150 0ustar nabijaczleweliusers/* 7zCrcOpt.c -- CRC32 calculation (optimized functions) 2023-12-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "CpuArch.h" #if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1 // for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu // #define Z7_CRC_DEBUG_BE #ifdef Z7_CRC_DEBUG_BE #undef MY_CPU_LE #define MY_CPU_BE #endif // the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c #ifdef Z7_CRC_NUM_TABLES #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES #else #define Z7_CRC_NUM_TABLES_USE 12 #endif #if Z7_CRC_NUM_TABLES_USE % 4 || \ Z7_CRC_NUM_TABLES_USE < 4 * 1 || \ Z7_CRC_NUM_TABLES_USE > 4 * 6 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES #endif #ifndef MY_CPU_BE #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define Q(n, d) \ ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] ) #define R(a) *((const UInt32 *)(const void *)p + (a)) #define CRC_FUNC_PRE_LE2(step) \ UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table) #define CRC_FUNC_PRE_LE(step) \ CRC_FUNC_PRE_LE2(step); \ CRC_FUNC_PRE_LE2(step) CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE) { const Byte *p = (const Byte *)data; const Byte *lim; for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC_UPDATE_BYTE_2(v, *p); lim = p + size; if (size >= Z7_CRC_NUM_TABLES_USE) { lim -= Z7_CRC_NUM_TABLES_USE; do { v ^= R(0); { #if Z7_CRC_NUM_TABLES_USE == 1 * 4 v = Q(0, v); #else #define U2(r, op) \ { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); } UInt32 d, x; U2(1, =) #if Z7_CRC_NUM_TABLES_USE >= 3 * 4 #define U(r) U2(r, ^=) U(2) #if Z7_CRC_NUM_TABLES_USE >= 4 * 4 U(3) #if Z7_CRC_NUM_TABLES_USE >= 5 * 4 U(4) #if Z7_CRC_NUM_TABLES_USE >= 6 * 4 U(5) #if Z7_CRC_NUM_TABLES_USE >= 7 * 4 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES #endif #endif #endif #endif #endif #undef U #undef U2 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v); #endif } p += Z7_CRC_NUM_TABLES_USE; } while (p <= lim); lim += Z7_CRC_NUM_TABLES_USE; } for (; p < lim; p++) v = CRC_UPDATE_BYTE_2(v, *p); return v; } #undef CRC_UPDATE_BYTE_2 #undef R #undef Q #undef CRC_FUNC_PRE_LE #undef CRC_FUNC_PRE_LE2 #endif #ifndef MY_CPU_LE #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8)) #define Q(n, d) \ ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] ) #ifdef Z7_CRC_DEBUG_BE #define R(a) GetBe32a((const UInt32 *)(const void *)p + (a)) #else #define R(a) *((const UInt32 *)(const void *)p + (a)) #endif #define CRC_FUNC_PRE_BE2(step) \ UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table) #define CRC_FUNC_PRE_BE(step) \ CRC_FUNC_PRE_BE2(step); \ CRC_FUNC_PRE_BE2(step) CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE) { const Byte *p = (const Byte *)data; const Byte *lim; table += 0x100; v = Z7_BSWAP32(v); for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC_UPDATE_BYTE_2_BE(v, *p); lim = p + size; if (size >= Z7_CRC_NUM_TABLES_USE) { lim -= Z7_CRC_NUM_TABLES_USE; do { v ^= R(0); { #if Z7_CRC_NUM_TABLES_USE == 1 * 4 v = Q(0, v); #else #define U2(r, op) \ { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); } UInt32 d, x; U2(1, =) #if Z7_CRC_NUM_TABLES_USE >= 3 * 4 #define U(r) U2(r, ^=) U(2) #if Z7_CRC_NUM_TABLES_USE >= 4 * 4 U(3) #if Z7_CRC_NUM_TABLES_USE >= 5 * 4 U(4) #if Z7_CRC_NUM_TABLES_USE >= 6 * 4 U(5) #if Z7_CRC_NUM_TABLES_USE >= 7 * 4 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES #endif #endif #endif #endif #endif #undef U #undef U2 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v); #endif } p += Z7_CRC_NUM_TABLES_USE; } while (p <= lim); lim += Z7_CRC_NUM_TABLES_USE; } for (; p < lim; p++) v = CRC_UPDATE_BYTE_2_BE(v, *p); return Z7_BSWAP32(v); } #undef CRC_UPDATE_BYTE_2_BE #undef R #undef Q #undef CRC_FUNC_PRE_BE #undef CRC_FUNC_PRE_BE2 #endif #undef Z7_CRC_NUM_TABLES_USE #endif tmp41wklro_/C/7zDec.c0000444000175000001440000004330214570267340015455 0ustar nabijaczleweliusers/* 7zDec.c -- Decoding from 7z folder 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include /* #define Z7_PPMD_SUPPORT */ #include "7z.h" #include "7zCrc.h" #include "Bcj2.h" #include "Bra.h" #include "CpuArch.h" #include "Delta.h" #include "LzmaDec.h" #include "Lzma2Dec.h" #ifdef Z7_PPMD_SUPPORT #include "Ppmd7.h" #endif #define k_Copy 0 #ifndef Z7_NO_METHOD_LZMA2 #define k_LZMA2 0x21 #endif #define k_LZMA 0x30101 #define k_BCJ2 0x303011B #if !defined(Z7_NO_METHODS_FILTERS) #define Z7_USE_BRANCH_FILTER #endif #if !defined(Z7_NO_METHODS_FILTERS) || \ defined(Z7_USE_NATIVE_BRANCH_FILTER) && defined(MY_CPU_ARM64) #define Z7_USE_FILTER_ARM64 #ifndef Z7_USE_BRANCH_FILTER #define Z7_USE_BRANCH_FILTER #endif #define k_ARM64 0xa #endif #if !defined(Z7_NO_METHODS_FILTERS) || \ defined(Z7_USE_NATIVE_BRANCH_FILTER) && defined(MY_CPU_ARMT) #define Z7_USE_FILTER_ARMT #ifndef Z7_USE_BRANCH_FILTER #define Z7_USE_BRANCH_FILTER #endif #define k_ARMT 0x3030701 #endif #ifndef Z7_NO_METHODS_FILTERS #define k_Delta 3 #define k_RISCV 0xb #define k_BCJ 0x3030103 #define k_PPC 0x3030205 #define k_IA64 0x3030401 #define k_ARM 0x3030501 #define k_SPARC 0x3030805 #endif #ifdef Z7_PPMD_SUPPORT #define k_PPMD 0x30401 typedef struct { IByteIn vt; const Byte *cur; const Byte *end; const Byte *begin; UInt64 processed; BoolInt extra; SRes res; ILookInStreamPtr inStream; } CByteInToLook; static Byte ReadByte(IByteInPtr pp) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteInToLook) if (p->cur != p->end) return *p->cur++; if (p->res == SZ_OK) { size_t size = (size_t)(p->cur - p->begin); p->processed += size; p->res = ILookInStream_Skip(p->inStream, size); size = (1 << 25); p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size); p->cur = p->begin; p->end = p->begin + size; if (size != 0) return *p->cur++; } p->extra = True; return 0; } static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CPpmd7 ppmd; CByteInToLook s; SRes res = SZ_OK; s.vt.Read = ReadByte; s.inStream = inStream; s.begin = s.end = s.cur = NULL; s.extra = False; s.res = SZ_OK; s.processed = 0; if (propsSize != 5) return SZ_ERROR_UNSUPPORTED; { unsigned order = props[0]; UInt32 memSize = GetUi32(props + 1); if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return SZ_ERROR_UNSUPPORTED; Ppmd7_Construct(&ppmd); if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) return SZ_ERROR_MEM; Ppmd7_Init(&ppmd, order); } { ppmd.rc.dec.Stream = &s.vt; if (!Ppmd7z_RangeDec_Init(&ppmd.rc.dec)) res = SZ_ERROR_DATA; else if (!s.extra) { Byte *buf = outBuffer; const Byte *lim = buf + outSize; for (; buf != lim; buf++) { int sym = Ppmd7z_DecodeSymbol(&ppmd); if (s.extra || sym < 0) break; *buf = (Byte)sym; } if (buf != lim) res = SZ_ERROR_DATA; else if (!Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) { /* if (Ppmd7z_DecodeSymbol(&ppmd) != PPMD7_SYM_END || !Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) */ res = SZ_ERROR_DATA; } } if (s.extra) res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); else if (s.processed + (size_t)(s.cur - s.begin) != inSize) res = SZ_ERROR_DATA; } Ppmd7_Free(&ppmd, allocMain); return res; } #endif static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_CONSTRUCT(&state) RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)) state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { const void *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = ILookInStream_Look(inStream, &inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (status == LZMA_STATUS_FINISHED_WITH_MARK) { if (outSize != state.dicPos || inSize != 0) res = SZ_ERROR_DATA; break; } if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) break; if (inProcessed == 0 && dicPos == state.dicPos) { res = SZ_ERROR_DATA; break; } res = ILookInStream_Skip(inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } #ifndef Z7_NO_METHOD_LZMA2 static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) { CLzma2Dec state; SRes res = SZ_OK; Lzma2Dec_CONSTRUCT(&state) if (propsSize != 1) return SZ_ERROR_DATA; RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)) state.decoder.dic = outBuffer; state.decoder.dicBufSize = outSize; Lzma2Dec_Init(&state); for (;;) { const void *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = ILookInStream_Look(inStream, &inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; ELzmaStatus status; res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (status == LZMA_STATUS_FINISHED_WITH_MARK) { if (outSize != state.decoder.dicPos || inSize != 0) res = SZ_ERROR_DATA; break; } if (inProcessed == 0 && dicPos == state.decoder.dicPos) { res = SZ_ERROR_DATA; break; } res = ILookInStream_Skip(inStream, inProcessed); if (res != SZ_OK) break; } } Lzma2Dec_FreeProbs(&state, allocMain); return res; } #endif static SRes SzDecodeCopy(UInt64 inSize, ILookInStreamPtr inStream, Byte *outBuffer) { while (inSize > 0) { const void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)) if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(ILookInStream_Skip(inStream, curSize)) } return SZ_OK; } static BoolInt IS_MAIN_METHOD(UInt32 m) { switch (m) { case k_Copy: case k_LZMA: #ifndef Z7_NO_METHOD_LZMA2 case k_LZMA2: #endif #ifdef Z7_PPMD_SUPPORT case k_PPMD: #endif return True; } return False; } static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c) { return c->NumStreams == 1 /* && c->MethodID <= (UInt32)0xFFFFFFFF */ && IS_MAIN_METHOD((UInt32)c->MethodID); } #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) static SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (!IS_SUPPORTED_CODER(&f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } #if defined(Z7_USE_BRANCH_FILTER) if (f->NumCoders == 2) { const CSzCoderInfo *c = &f->Coders[1]; if ( /* c->MethodID > (UInt32)0xFFFFFFFF || */ c->NumStreams != 1 || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 1 || f->Bonds[0].InIndex != 1 || f->Bonds[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; switch ((UInt32)c->MethodID) { #if !defined(Z7_NO_METHODS_FILTERS) case k_Delta: case k_BCJ: case k_PPC: case k_IA64: case k_SPARC: case k_ARM: case k_RISCV: #endif #ifdef Z7_USE_FILTER_ARM64 case k_ARM64: #endif #ifdef Z7_USE_FILTER_ARMT case k_ARMT: #endif break; default: return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } #endif if (f->NumCoders == 4) { if (!IS_SUPPORTED_CODER(&f->Coders[1]) || !IS_SUPPORTED_CODER(&f->Coders[2]) || !IS_BCJ2(&f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBonds != 3 || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } static SRes SzFolder_Decode2(const CSzFolder *folder, const Byte *propsData, const UInt64 *unpackSizes, const UInt64 *packPositions, ILookInStreamPtr inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)) for (ci = 0; ci < folder->NumCoders; ci++) { const CSzCoderInfo *coder = &folder->Coders[ci]; if (IS_MAIN_METHOD((UInt32)coder->MethodID)) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { const UInt32 indices[] = { 3, 2, 0 }; const UInt64 unpackSize = unpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur); if (!temp && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = packPositions[si]; inSize = packPositions[(size_t)si + 1] - offset; RINOK(LookInStream_SeekTo(inStream, startPos + offset)) if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)) } else if (coder->MethodID == k_LZMA) { RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } #ifndef Z7_NO_METHOD_LZMA2 else if (coder->MethodID == k_LZMA2) { RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } #endif #ifdef Z7_PPMD_SUPPORT else if (coder->MethodID == k_PPMD) { RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)) } #endif else return SZ_ERROR_UNSUPPORTED; } else if (coder->MethodID == k_BCJ2) { const UInt64 offset = packPositions[1]; const UInt64 s3Size = packPositions[2] - offset; if (ci != 3) return SZ_ERROR_UNSUPPORTED; tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]); if (!tempBuf[2] && tempSizes[2] != 0) return SZ_ERROR_MEM; RINOK(LookInStream_SeekTo(inStream, startPos + offset)) RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])) if ((tempSizes[0] & 3) != 0 || (tempSizes[1] & 3) != 0 || tempSize3 + tempSizes[0] + tempSizes[1] != outSize) return SZ_ERROR_DATA; { CBcj2Dec p; p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; p.dest = outBuffer; p.destLim = outBuffer + outSize; Bcj2Dec_Init(&p); RINOK(Bcj2Dec_Decode(&p)) { unsigned i; for (i = 0; i < 4; i++) if (p.bufs[i] != p.lims[i]) return SZ_ERROR_DATA; if (p.dest != p.destLim || !Bcj2Dec_IsMaybeFinished(&p)) return SZ_ERROR_DATA; } } } #if defined(Z7_USE_BRANCH_FILTER) else if (ci == 1) { #if !defined(Z7_NO_METHODS_FILTERS) if (coder->MethodID == k_Delta) { if (coder->PropsSize != 1) return SZ_ERROR_UNSUPPORTED; { Byte state[DELTA_STATE_SIZE]; Delta_Init(state); Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); } continue; } #endif #ifdef Z7_USE_FILTER_ARM64 if (coder->MethodID == k_ARM64) { UInt32 pc = 0; if (coder->PropsSize == 4) { pc = GetUi32(propsData + coder->PropsOffset); if (pc & 3) return SZ_ERROR_UNSUPPORTED; } else if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED; z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc); continue; } #endif #if !defined(Z7_NO_METHODS_FILTERS) if (coder->MethodID == k_RISCV) { UInt32 pc = 0; if (coder->PropsSize == 4) { pc = GetUi32(propsData + coder->PropsOffset); if (pc & 1) return SZ_ERROR_UNSUPPORTED; } else if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED; z7_BranchConv_RISCV_Dec(outBuffer, outSize, pc); continue; } #endif #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) { if (coder->PropsSize != 0) return SZ_ERROR_UNSUPPORTED; #define CASE_BRA_CONV(isa) case k_ ## isa: Z7_BRANCH_CONV_DEC(isa)(outBuffer, outSize, 0); break; // pc = 0; switch (coder->MethodID) { #if !defined(Z7_NO_METHODS_FILTERS) case k_BCJ: { UInt32 state = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0 break; } case k_PPC: Z7_BRANCH_CONV_DEC_2(BranchConv_PPC)(outBuffer, outSize, 0); break; // pc = 0; // CASE_BRA_CONV(PPC) CASE_BRA_CONV(IA64) CASE_BRA_CONV(SPARC) CASE_BRA_CONV(ARM) #endif #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) CASE_BRA_CONV(ARMT) #endif default: return SZ_ERROR_UNSUPPORTED; } continue; } #endif } // (c == 1) #endif // Z7_USE_BRANCH_FILTER else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, ILookInStreamPtr inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAllocPtr allocMain) { SRes res; CSzFolder folder; CSzData sd; const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; sd.Data = data; sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex]; res = SzGetNextFolderItem(&folder, &sd); if (res != SZ_OK) return res; if (sd.Size != 0 || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) return SZ_ERROR_FAIL; { unsigned i; Byte *tempBuf[3] = { 0, 0, 0}; res = SzFolder_Decode2(&folder, data, &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], p->PackPositions + p->FoStartPackStreamIndex[folderIndex], inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) ISzAlloc_Free(allocMain, tempBuf[i]); if (res == SZ_OK) if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) res = SZ_ERROR_CRC; return res; } } tmp41wklro_/C/7zFile.c0000444000175000001440000002441214412260060015625 0ustar nabijaczleweliusers/* 7zFile.c -- File IO 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include #ifndef USE_FOPEN #include #include #ifdef _WIN32 #include typedef int ssize_t; typedef int off_t; #else #include #endif #endif #else /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #endif #define kChunkSizeMax (1 << 22) void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #elif defined(USE_FOPEN) p->file = NULL; #else p->fd = -1; #endif } #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #elif defined(USE_FOPEN) p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : #ifdef UNDER_CE 2; /* ENOENT */ #else errno; #endif #else int flags = (writeMode ? (O_CREAT | O_EXCL | O_WRONLY) : O_RDONLY); #ifdef O_BINARY flags |= O_BINARY; #endif p->fd = open(name, flags, 0666); return (p->fd != -1) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { #if defined(USE_WINDOWS_FILE) || defined(USE_FOPEN) return File_Open(p, name, 1); #else p->fd = creat(name, 0666); return (p->fd != -1) ? 0 : errno; #endif } #endif #ifdef USE_WINDOWS_FILE static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) { p->handle = CreateFileW(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); } WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } #endif WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #elif defined(USE_FOPEN) if (p->file != NULL) { int res = fclose(p->file); if (res != 0) { if (res == EOF) return errno; return res; } p->file = NULL; } #else if (p->fd != -1) { if (close(p->fd) != 0) return errno; p->fd = -1; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; *size = 0; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE do { const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; const BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); // debug : we can break here for partial reading mode if (processed == 0) break; } while (originalSize > 0); #elif defined(USE_FOPEN) do { const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; const size_t processed = fread(data, 1, curSize, p->file); data = (void *)((Byte *)data + (size_t)processed); originalSize -= processed; *size += processed; if (processed != curSize) return ferror(p->file); // debug : we can break here for partial reading mode if (processed == 0) break; } while (originalSize > 0); #else do { const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; const ssize_t processed = read(p->fd, data, curSize); if (processed == -1) return errno; if (processed == 0) break; data = (void *)((Byte *)data + (size_t)processed); originalSize -= (size_t)processed; *size += (size_t)processed; // debug : we can break here for partial reading mode // break; } while (originalSize > 0); #endif return 0; } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; *size = 0; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE do { const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; const BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (const void *)((const Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); #elif defined(USE_FOPEN) do { const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; const size_t processed = fwrite(data, 1, curSize, p->file); data = (void *)((Byte *)data + (size_t)processed); originalSize -= processed; *size += processed; if (processed != curSize) return ferror(p->file); if (processed == 0) break; } while (originalSize > 0); #else do { const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; const ssize_t processed = write(p->fd, data, curSize); if (processed == -1) return errno; if (processed == 0) break; data = (const void *)((const Byte *)data + (size_t)processed); originalSize -= (size_t)processed; *size += (size_t)processed; } while (originalSize > 0); #endif return 0; } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE DWORD moveMethod; UInt32 low = (UInt32)*pos; LONG high = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ // (int) to eliminate clang warning switch ((int)origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } low = SetFilePointer(p->handle, (LONG)low, &high, moveMethod); if (low == (UInt32)0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)high << 32) | low; return 0; #else int moveMethod; // = origin; switch ((int)origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return EINVAL; } #if defined(USE_FOPEN) { int res = fseek(p->file, (long)*pos, moveMethod); if (res == -1) return errno; *pos = ftell(p->file); if (*pos == -1) return errno; return 0; } #else { off_t res = lseek(p->fd, (off_t)*pos, moveMethod); if (res == -1) return errno; *pos = res; return 0; } #endif // USE_FOPEN #endif // USE_WINDOWS_FILE } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #elif defined(USE_FOPEN) long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #else off_t pos; *length = 0; pos = lseek(p->fd, 0, SEEK_CUR); if (pos != -1) { const off_t len2 = lseek(p->fd, 0, SEEK_END); const off_t res2 = lseek(p->fd, pos, SEEK_SET); if (len2 != -1) { *length = (UInt64)len2; if (res2 != -1) return 0; } } return errno; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(ISeqInStreamPtr pp, void *buf, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileSeqInStream) const WRes wres = File_Read(&p->file, buf, size); p->wres = wres; return (wres == 0) ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->vt.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(ISeekInStreamPtr pp, void *buf, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream) const WRes wres = File_Read(&p->file, buf, size); p->wres = wres; return (wres == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(ISeekInStreamPtr pp, Int64 *pos, ESzSeek origin) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream) const WRes wres = File_Seek(&p->file, pos, origin); p->wres = wres; return (wres == 0) ? SZ_OK : SZ_ERROR_READ; } void FileInStream_CreateVTable(CFileInStream *p) { p->vt.Read = FileInStream_Read; p->vt.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileOutStream) const WRes wres = File_Write(&p->file, data, &size); p->wres = wres; return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->vt.Write = FileOutStream_Write; } tmp41wklro_/C/7zFile.h0000444000175000001440000000336714401055020015634 0ustar nabijaczleweliusers/* 7zFile.h -- File IO 2023-03-05 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_FILE_H #define ZIP7_INC_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE // #include #endif #ifdef USE_WINDOWS_FILE #include "7zWindows.h" #else // note: USE_FOPEN mode is limited to 32-bit file size // #define USE_FOPEN // #include #endif #include "7zTypes.h" EXTERN_C_BEGIN /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #elif defined(USE_FOPEN) FILE *file; #else int fd; #endif } CSzFile; void File_Construct(CSzFile *p); #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); #endif #ifdef USE_WINDOWS_FILE WRes InFile_OpenW(CSzFile *p, const WCHAR *name); WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); #endif WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream vt; CSzFile file; WRes wres; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream vt; CSzFile file; WRes wres; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream vt; CSzFile file; WRes wres; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); EXTERN_C_END #endif tmp41wklro_/C/7zip_gcc_c.mak0000444000175000001440000001703714567602040017040 0ustar nabijaczleweliusers MY_ARCH_2 = $(MY_ARCH) MY_ASM = jwasm MY_ASM = asmc ifndef RC #RC=windres.exe --target=pe-x86-64 #RC=windres.exe -F pe-i386 RC=windres.exe endif PROGPATH = $(O)/$(PROG) PROGPATH_STATIC = $(O)/$(PROG)s ifneq ($(CC), xlc) CFLAGS_WARN_WALL = -Wall -Werror -Wextra endif # for object file CFLAGS_BASE_LIST = -c # for ASM file # CFLAGS_BASE_LIST = -S FLAGS_FLTO = -flto FLAGS_FLTO = CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif ifdef IS_MINGW LDFLAGS_STATIC_2 = -static else ifndef DEF_FILE ifndef IS_NOT_STANDALONE ifndef MY_DYNAMIC_LINK ifneq ($(CC), clang) LDFLAGS_STATIC_2 = # -static # -static-libstdc++ -static-libgcc endif endif endif endif endif LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) ifdef DEF_FILE ifdef IS_MINGW SHARED_EXT=.dll LDFLAGS = -shared -DEF $(DEF_FILE) $(LDFLAGS_STATIC) else SHARED_EXT=.so LDFLAGS = -shared -fPIC $(LDFLAGS_STATIC) CC_SHARED=-fPIC endif else LDFLAGS = $(LDFLAGS_STATIC) # -s is not required for clang, do we need it for GGC ??? # -s #-static -static-libgcc -static-libstdc++ ifdef IS_MINGW SHARED_EXT=.exe else SHARED_EXT= endif endif PROGPATH = $(O)/$(PROG)$(SHARED_EXT) PROGPATH_STATIC = $(O)/$(PROG)s$(SHARED_EXT) ifndef O O=_o endif ifdef IS_MINGW ifdef MSYSTEM RM = rm -f MY_MKDIR=mkdir -p DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) else RM = del MY_MKDIR=mkdir DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll endif LIB2 = -lOle32 -loleaut32 -luuid -ladvapi32 -lUser32 -lShell32 CFLAGS_EXTRA = -DUNICODE -D_UNICODE # -Wno-delete-non-virtual-dtor else RM = rm -f MY_MKDIR=mkdir -p # CFLAGS_BASE := $(CFLAGS_BASE) -DZ7_ST # CFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE # LOCAL_LIBS=-lpthread # LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl LIB2 = -lpthread -ldl DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) endif ifdef IS_X64 AFLAGS_ABI = -elf64 -DABI_LINUX else AFLAGS_ABI = -elf -DABI_LINUX -DABI_CDECL # -DABI_CDECL # -DABI_LINUX # -DABI_CDECL endif AFLAGS = $(AFLAGS_ABI) -Fo$(O)/ C_WARN_FLAGS = CFLAGS = $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(CFLAGS_EXTRA) $(C_WARN_FLAGS) $(FLAGS_FLTO) $(CC_SHARED) -o $@ STATIC_TARGET= ifdef COMPL_STATIC STATIC_TARGET=$(PROGPATH_STATIC) endif all: $(O) $(PROGPATH) $(STATIC_TARGET) $(O): $(MY_MKDIR) $(O) ifneq ($(CC), $(CROSS_COMPILE)clang) LFLAGS_STRIP = -s endif LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) $(PROGPATH): $(OBJS) $(CC) -o $(PROGPATH) $(LFLAGS_ALL) $(PROGPATH_STATIC): $(OBJS) $(CC) -static -o $(PROGPATH_STATIC) $(LFLAGS_ALL) ifndef NO_DEFAULT_RES # old mingw without -FO # windres.exe $(RFLAGS) resource.rc $O/resource.o $O/resource.o: resource.rc $(RC) $(RFLAGS) resource.rc $(O)/resource.o endif # windres.exe $(RFLAGS) resource.rc $(O)\resource.o # windres.exe $(RFLAGS) resource.rc -FO $(O)/resource.o # $(RC) $(RFLAGS) resource.rc -FO $(O)/resource.o $O/7zAlloc.o: ../../../C/7zAlloc.c $(CC) $(CFLAGS) $< $O/7zArcIn.o: ../../../C/7zArcIn.c $(CC) $(CFLAGS) $< $O/7zBuf.o: ../../../C/7zBuf.c $(CC) $(CFLAGS) $< $O/7zBuf2.o: ../../../C/7zBuf2.c $(CC) $(CFLAGS) $< $O/7zCrc.o: ../../../C/7zCrc.c $(CC) $(CFLAGS) $< $O/7zDec.o: ../../../C/7zDec.c $(CC) $(CFLAGS) $< $O/7zFile.o: ../../../C/7zFile.c $(CC) $(CFLAGS) $< $O/7zStream.o: ../../../C/7zStream.c $(CC) $(CFLAGS) $< $O/Aes.o: ../../../C/Aes.c $(CC) $(CFLAGS) $< $O/Alloc.o: ../../../C/Alloc.c $(CC) $(CFLAGS) $< $O/Bcj2.o: ../../../C/Bcj2.c $(CC) $(CFLAGS) $< $O/Bcj2Enc.o: ../../../C/Bcj2Enc.c $(CC) $(CFLAGS) $< $O/Blake2s.o: ../../../C/Blake2s.c $(CC) $(CFLAGS) $< $O/Bra.o: ../../../C/Bra.c $(CC) $(CFLAGS) $< $O/Bra86.o: ../../../C/Bra86.c $(CC) $(CFLAGS) $< $O/BraIA64.o: ../../../C/BraIA64.c $(CC) $(CFLAGS) $< $O/BwtSort.o: ../../../C/BwtSort.c $(CC) $(CFLAGS) $< $O/CpuArch.o: ../../../C/CpuArch.c $(CC) $(CFLAGS) $< $O/Delta.o: ../../../C/Delta.c $(CC) $(CFLAGS) $< $O/DllSecur.o: ../../../C/DllSecur.c $(CC) $(CFLAGS) $< $O/HuffEnc.o: ../../../C/HuffEnc.c $(CC) $(CFLAGS) $< $O/LzFind.o: ../../../C/LzFind.c $(CC) $(CFLAGS) $< # ifdef MT_FILES $O/LzFindMt.o: ../../../C/LzFindMt.c $(CC) $(CFLAGS) $< $O/LzFindOpt.o: ../../../C/LzFindOpt.c $(CC) $(CFLAGS) $< $O/Threads.o: ../../../C/Threads.c $(CC) $(CFLAGS) $< # endif $O/LzmaEnc.o: ../../../C/LzmaEnc.c $(CC) $(CFLAGS) $< $O/Lzma86Dec.o: ../../../C/Lzma86Dec.c $(CC) $(CFLAGS) $< $O/Lzma86Enc.o: ../../../C/Lzma86Enc.c $(CC) $(CFLAGS) $< $O/Lzma2Dec.o: ../../../C/Lzma2Dec.c $(CC) $(CFLAGS) $< $O/Lzma2DecMt.o: ../../../C/Lzma2DecMt.c $(CC) $(CFLAGS) $< $O/Lzma2Enc.o: ../../../C/Lzma2Enc.c $(CC) $(CFLAGS) $< $O/LzmaLib.o: ../../../C/LzmaLib.c $(CC) $(CFLAGS) $< $O/MtCoder.o: ../../../C/MtCoder.c $(CC) $(CFLAGS) $< $O/MtDec.o: ../../../C/MtDec.c $(CC) $(CFLAGS) $< $O/Ppmd7.o: ../../../C/Ppmd7.c $(CC) $(CFLAGS) $< $O/Ppmd7aDec.o: ../../../C/Ppmd7aDec.c $(CC) $(CFLAGS) $< $O/Ppmd7Dec.o: ../../../C/Ppmd7Dec.c $(CC) $(CFLAGS) $< $O/Ppmd7Enc.o: ../../../C/Ppmd7Enc.c $(CC) $(CFLAGS) $< $O/Ppmd8.o: ../../../C/Ppmd8.c $(CC) $(CFLAGS) $< $O/Ppmd8Dec.o: ../../../C/Ppmd8Dec.c $(CC) $(CFLAGS) $< $O/Ppmd8Enc.o: ../../../C/Ppmd8Enc.c $(CC) $(CFLAGS) $< $O/Sha1.o: ../../../C/Sha1.c $(CC) $(CFLAGS) $< $O/Sha256.o: ../../../C/Sha256.c $(CC) $(CFLAGS) $< $O/Sort.o: ../../../C/Sort.c $(CC) $(CFLAGS) $< $O/SwapBytes.o: ../../../C/SwapBytes.c $(CC) $(CFLAGS) $< $O/Xz.o: ../../../C/Xz.c $(CC) $(CFLAGS) $< $O/XzCrc64.o: ../../../C/XzCrc64.c $(CC) $(CFLAGS) $< $O/XzDec.o: ../../../C/XzDec.c $(CC) $(CFLAGS) $< $O/XzEnc.o: ../../../C/XzEnc.c $(CC) $(CFLAGS) $< $O/XzIn.o: ../../../C/XzIn.c $(CC) $(CFLAGS) $< ifdef USE_ASM ifdef IS_X64 USE_X86_ASM=1 else ifdef IS_X86 USE_X86_ASM=1 endif endif endif ifdef USE_X86_ASM $O/7zCrcOpt.o: ../../../Asm/x86/7zCrcOpt.asm $(MY_ASM) $(AFLAGS) $< $O/XzCrc64Opt.o: ../../../Asm/x86/XzCrc64Opt.asm $(MY_ASM) $(AFLAGS) $< $O/AesOpt.o: ../../../Asm/x86/AesOpt.asm $(MY_ASM) $(AFLAGS) $< $O/Sha1Opt.o: ../../../Asm/x86/Sha1Opt.asm $(MY_ASM) $(AFLAGS) $< $O/Sha256Opt.o: ../../../Asm/x86/Sha256Opt.asm $(MY_ASM) $(AFLAGS) $< else $O/7zCrcOpt.o: ../../7zCrcOpt.c $(CC) $(CFLAGS) $< $O/XzCrc64Opt.o: ../../XzCrc64Opt.c $(CC) $(CFLAGS) $< $O/Sha1Opt.o: ../../Sha1Opt.c $(CC) $(CFLAGS) $< $O/Sha256Opt.o: ../../Sha256Opt.c $(CC) $(CFLAGS) $< $O/AesOpt.o: ../../AesOpt.c $(CC) $(CFLAGS) $< endif ifdef USE_LZMA_DEC_ASM ifdef IS_X64 $O/LzmaDecOpt.o: ../../../Asm/x86/LzmaDecOpt.asm $(MY_ASM) $(AFLAGS) $< endif ifdef IS_ARM64 $O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S $(CC) $(CFLAGS) $(ASM_FLAGS) $< endif $O/LzmaDec.o: ../../LzmaDec.c $(CC) $(CFLAGS) -DZ7_LZMA_DEC_OPT $< else $O/LzmaDec.o: ../../LzmaDec.c $(CC) $(CFLAGS) $< endif $O/7zMain.o: ../../../C/Util/7z/7zMain.c $(CC) $(CFLAGS) $< $O/7zipInstall.o: ../../../C/Util/7zipInstall/7zipInstall.c $(CC) $(CFLAGS) $< $O/7zipUninstall.o: ../../../C/Util/7zipUninstall/7zipUninstall.c $(CC) $(CFLAGS) $< $O/LzmaUtil.o: ../../../C/Util/Lzma/LzmaUtil.c $(CC) $(CFLAGS) $< $O/XzUtil.o: ../../../C/Util/Xz/XzUtil.c $(CC) $(CFLAGS) $< clean: -$(DEL_OBJ_EXE) tmp41wklro_/C/7zStream.c0000444000175000001440000001123614412260060016201 0ustar nabijaczleweliusers/* 7zStream.c -- 7z Stream functions 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "7zTypes.h" SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { size_t cur = size; const SRes res = ISeqInStream_Read(stream, buf, &cur); *processedSize += cur; buf = (void *)((Byte *)buf + cur); size -= cur; if (res != SZ_OK) return res; if (cur == 0) return SZ_OK; } return SZ_OK; } /* SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(ISeqInStream_Read(stream, buf, &processed)) if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } */ SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf) { size_t processed = 1; RINOK(ISeqInStream_Read(stream, buf, &processed)) return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset) { Int64 t = (Int64)offset; return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size) { const void *lookBuf; if (*size == 0) return SZ_OK; RINOK(ILookInStream_Look(stream, &lookBuf, size)) memcpy(buf, lookBuf, *size); return ILookInStream_Skip(stream, *size); } SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(ILookInStream_Read(stream, buf, &processed)) if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } #define GET_LookToRead2 Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLookToRead2) static SRes LookToRead2_Look_Lookahead(ILookInStreamPtr pp, const void **buf, size_t *size) { SRes res = SZ_OK; GET_LookToRead2 size_t size2 = p->size - p->pos; if (size2 == 0 && *size != 0) { p->pos = 0; p->size = 0; size2 = p->bufSize; res = ISeekInStream_Read(p->realStream, p->buf, &size2); p->size = size2; } if (*size > size2) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead2_Look_Exact(ILookInStreamPtr pp, const void **buf, size_t *size) { SRes res = SZ_OK; GET_LookToRead2 size_t size2 = p->size - p->pos; if (size2 == 0 && *size != 0) { p->pos = 0; p->size = 0; if (*size > p->bufSize) *size = p->bufSize; res = ISeekInStream_Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (*size > size2) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead2_Skip(ILookInStreamPtr pp, size_t offset) { GET_LookToRead2 p->pos += offset; return SZ_OK; } static SRes LookToRead2_Read(ILookInStreamPtr pp, void *buf, size_t *size) { GET_LookToRead2 size_t rem = p->size - p->pos; if (rem == 0) return ISeekInStream_Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead2_Seek(ILookInStreamPtr pp, Int64 *pos, ESzSeek origin) { GET_LookToRead2 p->pos = p->size = 0; return ISeekInStream_Seek(p->realStream, pos, origin); } void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) { p->vt.Look = lookahead ? LookToRead2_Look_Lookahead : LookToRead2_Look_Exact; p->vt.Skip = LookToRead2_Skip; p->vt.Read = LookToRead2_Read; p->vt.Seek = LookToRead2_Seek; } static SRes SecToLook_Read(ISeqInStreamPtr pp, void *buf, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToLook) return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->vt.Read = SecToLook_Read; } static SRes SecToRead_Read(ISeqInStreamPtr pp, void *buf, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToRead) return ILookInStream_Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->vt.Read = SecToRead_Read; } tmp41wklro_/C/7zTypes.h0000444000175000001440000003771314553174460016105 0ustar nabijaczleweliusers/* 7zTypes.h -- Basic types 2024-01-24 : Igor Pavlov : Public domain */ #ifndef ZIP7_7Z_TYPES_H #define ZIP7_7Z_TYPES_H #ifdef _WIN32 /* #include */ #else #include #endif #include #ifndef EXTERN_C_BEGIN #ifdef __cplusplus #define EXTERN_C_BEGIN extern "C" { #define EXTERN_C_END } #else #define EXTERN_C_BEGIN #define EXTERN_C_END #endif #endif EXTERN_C_BEGIN #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _MSC_VER #if _MSC_VER > 1200 #define MY_ALIGN(n) __declspec(align(n)) #else #define MY_ALIGN(n) #endif #else /* // C11/C++11: #include #define MY_ALIGN(n) alignas(n) */ #define MY_ALIGN(n) __attribute__ ((aligned(n))) #endif #ifdef _WIN32 /* typedef DWORD WRes; */ typedef unsigned WRes; #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) // #define MY_HRES_ERROR_INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) #else // _WIN32 // #define ENV_HAVE_LSTAT typedef int WRes; // (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT #define MY_FACILITY_ERRNO 0x800 #define MY_FACILITY_WIN32 7 #define MY_FACILITY_WRes MY_FACILITY_ERRNO #define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \ ( (HRESULT)(x) & 0x0000FFFF) \ | (MY_FACILITY_WRes << 16) \ | (HRESULT)0x80000000 )) #define MY_SRes_HRESULT_FROM_WRes(x) \ ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x)) // we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno) #define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x) /* #define ERROR_FILE_NOT_FOUND 2L #define ERROR_ACCESS_DENIED 5L #define ERROR_NO_MORE_FILES 18L #define ERROR_LOCK_VIOLATION 33L #define ERROR_FILE_EXISTS 80L #define ERROR_DISK_FULL 112L #define ERROR_NEGATIVE_SEEK 131L #define ERROR_ALREADY_EXISTS 183L #define ERROR_DIRECTORY 267L #define ERROR_TOO_MANY_POSTS 298L #define ERROR_INTERNAL_ERROR 1359L #define ERROR_INVALID_REPARSE_DATA 4392L #define ERROR_REPARSE_TAG_INVALID 4393L #define ERROR_REPARSE_TAG_MISMATCH 4394L */ // we use errno equivalents for some WIN32 errors: #define ERROR_INVALID_PARAMETER EINVAL #define ERROR_INVALID_FUNCTION EINVAL #define ERROR_ALREADY_EXISTS EEXIST #define ERROR_FILE_EXISTS EEXIST #define ERROR_PATH_NOT_FOUND ENOENT #define ERROR_FILE_NOT_FOUND ENOENT #define ERROR_DISK_FULL ENOSPC // #define ERROR_INVALID_HANDLE EBADF // we use FACILITY_WIN32 for errors that has no errno equivalent // Too many posts were made to a semaphore. #define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL) #define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L) #define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L) // if (MY_FACILITY_WRes != FACILITY_WIN32), // we use FACILITY_WIN32 for COM errors: #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #define MY_E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L) /* // we can use FACILITY_ERRNO for some COM errors, that have errno equivalents: #define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM) #define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) #define MY_E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) */ #define TEXT(quote) quote #define FILE_ATTRIBUTE_READONLY 0x0001 #define FILE_ATTRIBUTE_HIDDEN 0x0002 #define FILE_ATTRIBUTE_SYSTEM 0x0004 #define FILE_ATTRIBUTE_DIRECTORY 0x0010 #define FILE_ATTRIBUTE_ARCHIVE 0x0020 #define FILE_ATTRIBUTE_DEVICE 0x0040 #define FILE_ATTRIBUTE_NORMAL 0x0080 #define FILE_ATTRIBUTE_TEMPORARY 0x0100 #define FILE_ATTRIBUTE_SPARSE_FILE 0x0200 #define FILE_ATTRIBUTE_REPARSE_POINT 0x0400 #define FILE_ATTRIBUTE_COMPRESSED 0x0800 #define FILE_ATTRIBUTE_OFFLINE 0x1000 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000 #define FILE_ATTRIBUTE_ENCRYPTED 0x4000 #define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */ #endif #ifndef RINOK #define RINOK(x) { const int _result_ = (x); if (_result_ != 0) return _result_; } #endif #ifndef RINOK_WRes #define RINOK_WRes(x) { const WRes _result_ = (x); if (_result_ != 0) return _result_; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef Z7_DECL_Int32_AS_long typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifndef _WIN32 typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; #define VOID void #define HRESULT LONG typedef void *LPVOID; // typedef void VOID; // typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; // gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits) typedef long INT_PTR; typedef unsigned long UINT_PTR; typedef long LONG_PTR; typedef unsigned long DWORD_PTR; typedef size_t SIZE_T; #endif // _WIN32 #define MY_HRES_ERROR_INTERNAL_ERROR ((HRESULT)0x8007054FL) #ifdef Z7_DECL_Int64_AS_long typedef long Int64; typedef unsigned long UInt64; #else #if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__clang__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else #if defined(__clang__) || defined(__GNUC__) #include typedef int64_t Int64; typedef uint64_t UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; // #define UINT64_CONST(n) n ## ULL #endif #endif #endif #define UINT64_CONST(n) n #ifdef Z7_DECL_SizeT_AS_unsigned_int typedef unsigned int SizeT; #else typedef size_t SizeT; #endif /* #if (defined(_MSC_VER) && _MSC_VER <= 1200) typedef size_t MY_uintptr_t; #else #include typedef uintptr_t MY_uintptr_t; #endif */ typedef int BoolInt; /* typedef BoolInt Bool; */ #define True 1 #define False 0 #ifdef _WIN32 #define Z7_STDCALL __stdcall #else #define Z7_STDCALL #endif #ifdef _MSC_VER #if _MSC_VER >= 1300 #define Z7_NO_INLINE __declspec(noinline) #else #define Z7_NO_INLINE #endif #define Z7_FORCE_INLINE __forceinline #define Z7_CDECL __cdecl #define Z7_FASTCALL __fastcall #else // _MSC_VER #if (defined(__GNUC__) && (__GNUC__ >= 4)) \ || (defined(__clang__) && (__clang_major__ >= 4)) \ || defined(__INTEL_COMPILER) \ || defined(__xlC__) #define Z7_NO_INLINE __attribute__((noinline)) #define Z7_FORCE_INLINE __attribute__((always_inline)) inline #else #define Z7_NO_INLINE #define Z7_FORCE_INLINE #endif #define Z7_CDECL #if defined(_M_IX86) \ || defined(__i386__) // #define Z7_FASTCALL __attribute__((fastcall)) // #define Z7_FASTCALL __attribute__((cdecl)) #define Z7_FASTCALL #elif defined(MY_CPU_AMD64) // #define Z7_FASTCALL __attribute__((ms_abi)) #define Z7_FASTCALL #else #define Z7_FASTCALL #endif #endif // _MSC_VER /* The following interfaces use first parameter as pointer to structure */ // #define Z7_C_IFACE_CONST_QUAL #define Z7_C_IFACE_CONST_QUAL const #define Z7_C_IFACE_DECL(a) \ struct a ## _; \ typedef Z7_C_IFACE_CONST_QUAL struct a ## _ * a ## Ptr; \ typedef struct a ## _ a; \ struct a ## _ Z7_C_IFACE_DECL (IByteIn) { Byte (*Read)(IByteInPtr p); /* reads one byte, returns 0 in case of EOF or error */ }; #define IByteIn_Read(p) (p)->Read(p) Z7_C_IFACE_DECL (IByteOut) { void (*Write)(IByteOutPtr p, Byte b); }; #define IByteOut_Write(p, b) (p)->Write(p, b) Z7_C_IFACE_DECL (ISeqInStream) { SRes (*Read)(ISeqInStreamPtr p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ }; #define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) /* try to read as much as avail in stream and limited by (*processedSize) */ SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize); /* it can return SZ_ERROR_INPUT_EOF */ // SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size); // SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf); Z7_C_IFACE_DECL (ISeqOutStream) { size_t (*Write)(ISeqOutStreamPtr p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ }; #define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; Z7_C_IFACE_DECL (ISeekInStream) { SRes (*Read)(ISeekInStreamPtr p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(ISeekInStreamPtr p, Int64 *pos, ESzSeek origin); }; #define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) Z7_C_IFACE_DECL (ILookInStream) { SRes (*Look)(ILookInStreamPtr p, const void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(ILookInStreamPtr p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(ILookInStreamPtr p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(ILookInStreamPtr p, Int64 *pos, ESzSeek origin); }; #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) #define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) #define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size); typedef struct { ILookInStream vt; ISeekInStreamPtr realStream; size_t pos; size_t size; /* it's data size */ /* the following variables must be set outside */ Byte *buf; size_t bufSize; } CLookToRead2; void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); #define LookToRead2_INIT(p) { (p)->pos = (p)->size = 0; } typedef struct { ISeqInStream vt; ILookInStreamPtr realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream vt; ILookInStreamPtr realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); Z7_C_IFACE_DECL (ICompressProgress) { SRes (*Progress)(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ }; #define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) typedef struct ISzAlloc ISzAlloc; typedef const ISzAlloc * ISzAllocPtr; struct ISzAlloc { void *(*Alloc)(ISzAllocPtr p, size_t size); void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ }; #define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) #define ISzAlloc_Free(p, a) (p)->Free(p, a) /* deprecated */ #define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) #define IAlloc_Free(p, a) ISzAlloc_Free(p, a) #ifndef MY_offsetof #ifdef offsetof #define MY_offsetof(type, m) offsetof(type, m) /* #define MY_offsetof(type, m) FIELD_OFFSET(type, m) */ #else #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) #endif #endif #ifndef Z7_container_of /* #define Z7_container_of(ptr, type, m) container_of(ptr, type, m) #define Z7_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) #define Z7_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) #define Z7_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) */ /* GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" GCC 3.4.4 : classes with constructor GCC 4.8.1 : classes with non-public variable members" */ #define Z7_container_of(ptr, type, m) \ ((type *)(void *)((char *)(void *) \ (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) #define Z7_container_of_CONST(ptr, type, m) \ ((const type *)(const void *)((const char *)(const void *) \ (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) /* #define Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) \ ((type *)(void *)(const void *)((const char *)(const void *) \ (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m))) */ #endif #define Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) // #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of(ptr, type, m) // #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) #define Z7_CONTAINER_FROM_VTBL_CONST(ptr, type, m) Z7_container_of_CONST(ptr, type, m) #define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) /* #define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m) */ #if defined (__clang__) || defined(__GNUC__) #define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") #define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \ _Pragma("GCC diagnostic pop") #else #define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL #define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL #endif #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \ Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \ type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \ Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \ Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p) // #define ZIP7_DECLARE_HANDLE(name) typedef void *name; #define Z7_DECLARE_HANDLE(name) struct name##_dummy{int unused;}; typedef struct name##_dummy *name; #define Z7_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) #ifndef Z7_ARRAY_SIZE #define Z7_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif #ifdef _WIN32 #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #endif #define k_PropVar_TimePrec_0 0 #define k_PropVar_TimePrec_Unix 1 #define k_PropVar_TimePrec_DOS 2 #define k_PropVar_TimePrec_HighPrec 3 #define k_PropVar_TimePrec_Base 16 #define k_PropVar_TimePrec_100ns (k_PropVar_TimePrec_Base + 7) #define k_PropVar_TimePrec_1ns (k_PropVar_TimePrec_Base + 9) EXTERN_C_END #endif /* #ifndef Z7_ST #ifdef _7ZIP_ST #define Z7_ST #endif #endif */ tmp41wklro_/C/7zVersion.h0000644000175000001440000000142014656123700016405 0ustar nabijaczleweliusers#define MY_VER_MAJOR 24 #define MY_VER_MINOR 8 #define MY_VER_BUILD 0 #define MY_VERSION_NUMBERS "24.08" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME #define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")" #else #define MY_VERSION_CPU MY_VERSION #endif #define MY_DATE "2024-08-11" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" #define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov" #ifdef USE_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR #else #define MY_COPYRIGHT MY_COPYRIGHT_PD #endif #define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE tmp41wklro_/C/7zVersion.rc0000444000175000001440000000277211553076040016570 0ustar nabijaczleweliusers#define MY_VS_FFI_FILEFLAGSMASK 0x0000003FL #define MY_VOS_NT_WINDOWS32 0x00040004L #define MY_VOS_CE_WINDOWS32 0x00050004L #define MY_VFT_APP 0x00000001L #define MY_VFT_DLL 0x00000002L // #include #ifndef MY_VERSION #include "7zVersion.h" #endif #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS MY_VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll") tmp41wklro_/C/7zWindows.h0000444000175000001440000000435514412260060016411 0ustar nabijaczleweliusers/* 7zWindows.h -- StdAfx 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_WINDOWS_H #define ZIP7_INC_7Z_WINDOWS_H #ifdef _WIN32 #if defined(__clang__) # pragma clang diagnostic push #endif #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4668) // '_WIN32_WINNT' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' #if _MSC_VER == 1900 // for old kit10 versions // #pragma warning(disable : 4255) // winuser.h(13979): warning C4255: 'GetThreadDpiAwarenessContext': #endif // win10 Windows Kit: #endif // _MSC_VER #if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64) // for msvc6 without sdk2003 #define RPC_NO_WINDOWS_H #endif #if defined(__MINGW32__) || defined(__MINGW64__) // #if defined(__GNUC__) && !defined(__clang__) #include #else #include #endif // #include // #include // but if precompiled with clang-cl then we need // #include #if defined(_MSC_VER) #pragma warning(pop) #endif #if defined(__clang__) # pragma clang diagnostic pop #endif #if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64) #ifndef _W64 typedef long LONG_PTR, *PLONG_PTR; typedef unsigned long ULONG_PTR, *PULONG_PTR; typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; #define Z7_OLD_WIN_SDK #endif // _W64 #endif // _MSC_VER == 1200 #ifdef Z7_OLD_WIN_SDK #ifndef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif #ifndef FILE_SPECIAL_ACCESS #define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) #endif // ShlObj.h: // #define BIF_NEWDIALOGSTYLE 0x0040 #pragma warning(disable : 4201) // #pragma warning(disable : 4115) #undef VARIANT_TRUE #define VARIANT_TRUE ((VARIANT_BOOL)-1) #endif #endif // Z7_OLD_WIN_SDK #ifdef UNDER_CE #undef VARIANT_TRUE #define VARIANT_TRUE ((VARIANT_BOOL)-1) #endif #if defined(_MSC_VER) #if _MSC_VER >= 1400 && _MSC_VER <= 1600 // BaseTsd.h(148) : 'HandleToULong' : unreferenced inline function has been removed // string.h // #pragma warning(disable : 4514) #endif #endif /* #include "7zTypes.h" */ #endif tmp41wklro_/C/Aes.c0000444000175000001440000002533414570332460015212 0ustar nabijaczleweliusers/* Aes.c -- AES encryption / decryption 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "CpuArch.h" #include "Aes.h" AES_CODE_FUNC g_AesCbc_Decode; #ifndef Z7_SFX AES_CODE_FUNC g_AesCbc_Encode; AES_CODE_FUNC g_AesCtr_Code; UInt32 g_Aes_SupportedFunctions_Flags; #endif MY_ALIGN(64) static UInt32 T[256 * 4]; MY_ALIGN(64) static const Byte Sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; MY_ALIGN(64) static UInt32 D[256 * 4]; MY_ALIGN(64) static Byte InvS[256]; #define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) #define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24)) #define gb0(x) ( (x) & 0xFF) #define gb1(x) (((x) >> ( 8)) & 0xFF) #define gb2(x) (((x) >> (16)) & 0xFF) #define gb3(x) (((x) >> (24))) #define gb(n, x) gb ## n(x) #define TT(x) (T + (x << 8)) #define DD(x) (D + (x << 8)) // #define Z7_SHOW_AES_STATUS #ifdef MY_CPU_X86_OR_AMD64 #if defined(__INTEL_COMPILER) #if (__INTEL_COMPILER >= 1110) #define USE_HW_AES #if (__INTEL_COMPILER >= 1900) #define USE_HW_VAES #endif #endif #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) #define USE_HW_AES #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 8) #define USE_HW_VAES #endif #elif defined(_MSC_VER) #define USE_HW_AES #define USE_HW_VAES #endif #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__ARM_FEATURE_AES) \ || defined(__ARM_FEATURE_CRYPTO) #define USE_HW_AES #else #if defined(MY_CPU_ARM64) \ || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \ || defined(Z7_MSC_VER_ORIGINAL) #if defined(__ARM_FP) && \ ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) \ ) \ || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) && \ (Z7_CLANG_VERSION < 170000 || \ Z7_CLANG_VERSION > 170001) #define USE_HW_AES #endif #endif #endif #endif #endif #ifdef USE_HW_AES // #pragma message("=== Aes.c USE_HW_AES === ") #ifdef Z7_SHOW_AES_STATUS #include #define PRF(x) x #else #define PRF(x) #endif #endif void AesGenTables(void) { unsigned i; for (i = 0; i < 256; i++) InvS[Sbox[i]] = (Byte)i; for (i = 0; i < 256; i++) { { const UInt32 a1 = Sbox[i]; const UInt32 a2 = xtime(a1); const UInt32 a3 = a2 ^ a1; TT(0)[i] = Ui32(a2, a1, a1, a3); TT(1)[i] = Ui32(a3, a2, a1, a1); TT(2)[i] = Ui32(a1, a3, a2, a1); TT(3)[i] = Ui32(a1, a1, a3, a2); } { const UInt32 a1 = InvS[i]; const UInt32 a2 = xtime(a1); const UInt32 a4 = xtime(a2); const UInt32 a8 = xtime(a4); const UInt32 a9 = a8 ^ a1; const UInt32 aB = a8 ^ a2 ^ a1; const UInt32 aD = a8 ^ a4 ^ a1; const UInt32 aE = a8 ^ a4 ^ a2; DD(0)[i] = Ui32(aE, a9, aD, aB); DD(1)[i] = Ui32(aB, aE, a9, aD); DD(2)[i] = Ui32(aD, aB, aE, a9); DD(3)[i] = Ui32(a9, aD, aB, aE); } } { AES_CODE_FUNC d = AesCbc_Decode; #ifndef Z7_SFX AES_CODE_FUNC e = AesCbc_Encode; AES_CODE_FUNC c = AesCtr_Code; UInt32 flags = 0; #endif #ifdef USE_HW_AES if (CPU_IsSupported_AES()) { // #pragma message ("AES HW") PRF(printf("\n===AES HW\n")); d = AesCbc_Decode_HW; #ifndef Z7_SFX e = AesCbc_Encode_HW; c = AesCtr_Code_HW; flags = k_Aes_SupportedFunctions_HW; #endif #ifdef MY_CPU_X86_OR_AMD64 #ifdef USE_HW_VAES if (CPU_IsSupported_VAES_AVX2()) { PRF(printf("\n===vaes avx2\n")); d = AesCbc_Decode_HW_256; #ifndef Z7_SFX c = AesCtr_Code_HW_256; flags |= k_Aes_SupportedFunctions_HW_256; #endif } #endif #endif } #endif g_AesCbc_Decode = d; #ifndef Z7_SFX g_AesCbc_Encode = e; g_AesCtr_Code = c; g_Aes_SupportedFunctions_Flags = flags; #endif } } #define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])] #define HT4(m, i, s, p) m[i] = \ HT(i, 0, s) ^ \ HT(i, 1, s) ^ \ HT(i, 2, s) ^ \ HT(i, 3, s) ^ w[p + i] #define HT16(m, s, p) \ HT4(m, 0, s, p); \ HT4(m, 1, s, p); \ HT4(m, 2, s, p); \ HT4(m, 3, s, p); \ #define FT(i, x) Sbox[gb(x, m[(i + x) & 3])] #define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; #define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])] #define HD4(m, i, s, p) m[i] = \ HD(i, 0, s) ^ \ HD(i, 1, s) ^ \ HD(i, 2, s) ^ \ HD(i, 3, s) ^ w[p + i]; #define HD16(m, s, p) \ HD4(m, 0, s, p); \ HD4(m, 1, s, p); \ HD4(m, 2, s, p); \ HD4(m, 3, s, p); \ #define FD(i, x) InvS[gb(x, m[(i - x) & 3])] #define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; void Z7_FASTCALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) { unsigned i, m; const UInt32 *wLim; UInt32 t; UInt32 rcon = 1; keySize /= 4; w[0] = ((UInt32)keySize / 2) + 3; w += 4; for (i = 0; i < keySize; i++, key += 4) w[i] = GetUi32(key); t = w[(size_t)keySize - 1]; wLim = w + (size_t)keySize * 3 + 28; m = 0; do { if (m == 0) { t = Ui32(Sbox[gb1(t)] ^ rcon, Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); rcon <<= 1; if (rcon & 0x100) rcon = 0x1b; m = keySize; } else if (m == 4 && keySize > 6) t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]); m--; t ^= w[0]; w[keySize] = t; } while (++w != wLim); } void Z7_FASTCALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize) { unsigned i, num; Aes_SetKey_Enc(w, key, keySize); num = keySize + 20; w += 8; for (i = 0; i < num; i++) { UInt32 r = w[i]; w[i] = DD(0)[Sbox[gb0(r)]] ^ DD(1)[Sbox[gb1(r)]] ^ DD(2)[Sbox[gb2(r)]] ^ DD(3)[Sbox[gb3(r)]]; } } /* Aes_Encode and Aes_Decode functions work with little-endian words. src and dest are pointers to 4 UInt32 words. src and dest can point to same block */ // Z7_FORCE_INLINE static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src) { UInt32 s[4]; UInt32 m[4]; UInt32 numRounds2 = w[0]; w += 4; s[0] = src[0] ^ w[0]; s[1] = src[1] ^ w[1]; s[2] = src[2] ^ w[2]; s[3] = src[3] ^ w[3]; w += 4; for (;;) { HT16(m, s, 0) if (--numRounds2 == 0) break; HT16(s, m, 4) w += 8; } w += 4; FT4(0) FT4(1) FT4(2) FT4(3) } Z7_FORCE_INLINE static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src) { UInt32 s[4]; UInt32 m[4]; UInt32 numRounds2 = w[0]; w += 4 + numRounds2 * 8; s[0] = src[0] ^ w[0]; s[1] = src[1] ^ w[1]; s[2] = src[2] ^ w[2]; s[3] = src[3] ^ w[3]; for (;;) { w -= 8; HD16(m, s, 4) if (--numRounds2 == 0) break; HD16(s, m, 0) } FD4(0) FD4(1) FD4(2) FD4(3) } void AesCbc_Init(UInt32 *p, const Byte *iv) { unsigned i; for (i = 0; i < 4; i++) p[i] = GetUi32(iv + i * 4); } void Z7_FASTCALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks) { for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) { p[0] ^= GetUi32(data); p[1] ^= GetUi32(data + 4); p[2] ^= GetUi32(data + 8); p[3] ^= GetUi32(data + 12); Aes_Encode(p + 4, p, p); SetUi32(data, p[0]) SetUi32(data + 4, p[1]) SetUi32(data + 8, p[2]) SetUi32(data + 12, p[3]) } } void Z7_FASTCALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks) { UInt32 in[4], out[4]; for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) { in[0] = GetUi32(data); in[1] = GetUi32(data + 4); in[2] = GetUi32(data + 8); in[3] = GetUi32(data + 12); Aes_Decode(p + 4, out, in); SetUi32(data, p[0] ^ out[0]) SetUi32(data + 4, p[1] ^ out[1]) SetUi32(data + 8, p[2] ^ out[2]) SetUi32(data + 12, p[3] ^ out[3]) p[0] = in[0]; p[1] = in[1]; p[2] = in[2]; p[3] = in[3]; } } void Z7_FASTCALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks) { for (; numBlocks != 0; numBlocks--) { UInt32 temp[4]; unsigned i; if (++p[0] == 0) p[1]++; Aes_Encode(p + 4, temp, p); for (i = 0; i < 4; i++, data += 4) { const UInt32 t = temp[i]; #ifdef MY_CPU_LE_UNALIGN *((UInt32 *)(void *)data) ^= t; #else data[0] = (Byte)(data[0] ^ (t & 0xFF)); data[1] = (Byte)(data[1] ^ ((t >> 8) & 0xFF)); data[2] = (Byte)(data[2] ^ ((t >> 16) & 0xFF)); data[3] = (Byte)(data[3] ^ ((t >> 24))); #endif } } } #undef xtime #undef Ui32 #undef gb0 #undef gb1 #undef gb2 #undef gb3 #undef gb #undef TT #undef DD #undef USE_HW_AES #undef PRF tmp41wklro_/C/Aes.h0000444000175000001440000000376314412260060015210 0ustar nabijaczleweliusers/* Aes.h -- AES encryption / decryption 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_AES_H #define ZIP7_INC_AES_H #include "7zTypes.h" EXTERN_C_BEGIN #define AES_BLOCK_SIZE 16 /* Call AesGenTables one time before other AES functions */ void AesGenTables(void); /* UInt32 pointers must be 16-byte aligned */ /* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */ #define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4) /* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */ /* keySize = 16 or 24 or 32 (bytes) */ typedef void (Z7_FASTCALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize); void Z7_FASTCALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize); void Z7_FASTCALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize); /* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */ void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */ /* data - 16-byte aligned pointer to data */ /* numBlocks - the number of 16-byte blocks in data array */ typedef void (Z7_FASTCALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks); extern AES_CODE_FUNC g_AesCbc_Decode; #ifndef Z7_SFX extern AES_CODE_FUNC g_AesCbc_Encode; extern AES_CODE_FUNC g_AesCtr_Code; #define k_Aes_SupportedFunctions_HW (1 << 2) #define k_Aes_SupportedFunctions_HW_256 (1 << 3) extern UInt32 g_Aes_SupportedFunctions_Flags; #endif #define Z7_DECLARE_AES_CODE_FUNC(funcName) \ void Z7_FASTCALL funcName(UInt32 *ivAes, Byte *data, size_t numBlocks); Z7_DECLARE_AES_CODE_FUNC (AesCbc_Encode) Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode) Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code) Z7_DECLARE_AES_CODE_FUNC (AesCbc_Encode_HW) Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW) Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW) Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW_256) Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW_256) EXTERN_C_END #endif tmp41wklro_/C/AesOpt.c0000444000175000001440000006020514570332460015671 0ustar nabijaczleweliusers/* AesOpt.c -- AES optimized code for x86 AES hardware instructions 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Aes.h" #include "CpuArch.h" #ifdef MY_CPU_X86_OR_AMD64 #if defined(__INTEL_COMPILER) #if (__INTEL_COMPILER >= 1110) #define USE_INTEL_AES #if (__INTEL_COMPILER >= 1900) #define USE_INTEL_VAES #endif #endif #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) #define USE_INTEL_AES #if !defined(__AES__) #define ATTRIB_AES __attribute__((__target__("aes"))) #endif #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 8) #define USE_INTEL_VAES #if !defined(__AES__) || !defined(__VAES__) || !defined(__AVX__) || !defined(__AVX2__) #define ATTRIB_VAES __attribute__((__target__("aes,vaes,avx,avx2"))) #endif #endif #elif defined(_MSC_VER) #if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729) #define USE_INTEL_AES #if (_MSC_VER >= 1910) #define USE_INTEL_VAES #endif #endif #ifndef USE_INTEL_AES #define Z7_USE_AES_HW_STUB #endif #ifndef USE_INTEL_VAES #define Z7_USE_VAES_HW_STUB #endif #endif #ifndef USE_INTEL_AES // #define Z7_USE_AES_HW_STUB // for debug #endif #ifndef USE_INTEL_VAES // #define Z7_USE_VAES_HW_STUB // for debug #endif #ifdef USE_INTEL_AES #include #if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB) #define AES_TYPE_keys UInt32 #define AES_TYPE_data Byte // #define AES_TYPE_keys __m128i // #define AES_TYPE_data __m128i #endif #ifndef ATTRIB_AES #define ATTRIB_AES #endif #define AES_FUNC_START(name) \ void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks) // void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks) #define AES_FUNC_START2(name) \ AES_FUNC_START (name); \ ATTRIB_AES \ AES_FUNC_START (name) #define MM_OP(op, dest, src) dest = op(dest, src); #define MM_OP_m(op, src) MM_OP(op, m, src) #define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src) AES_FUNC_START2 (AesCbc_Encode_HW) { __m128i *p = (__m128i *)(void *)ivAes; __m128i *data = (__m128i *)(void *)data8; __m128i m = *p; const __m128i k0 = p[2]; const __m128i k1 = p[3]; const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; for (; numBlocks != 0; numBlocks--, data++) { UInt32 r = numRounds2; const __m128i *w = p + 4; __m128i temp = *data; MM_XOR (temp, k0) MM_XOR (m, temp) MM_OP_m (_mm_aesenc_si128, k1) do { MM_OP_m (_mm_aesenc_si128, w[0]) MM_OP_m (_mm_aesenc_si128, w[1]) w += 2; } while (--r); MM_OP_m (_mm_aesenclast_si128, w[0]) *data = m; } *p = m; } #define WOP_1(op) #define WOP_2(op) WOP_1 (op) op (m1, 1) #define WOP_3(op) WOP_2 (op) op (m2, 2) #define WOP_4(op) WOP_3 (op) op (m3, 3) #ifdef MY_CPU_AMD64 #define WOP_5(op) WOP_4 (op) op (m4, 4) #define WOP_6(op) WOP_5 (op) op (m5, 5) #define WOP_7(op) WOP_6 (op) op (m6, 6) #define WOP_8(op) WOP_7 (op) op (m7, 7) #endif /* #define WOP_9(op) WOP_8 (op) op (m8, 8); #define WOP_10(op) WOP_9 (op) op (m9, 9); #define WOP_11(op) WOP_10(op) op (m10, 10); #define WOP_12(op) WOP_11(op) op (m11, 11); #define WOP_13(op) WOP_12(op) op (m12, 12); #define WOP_14(op) WOP_13(op) op (m13, 13); */ #ifdef MY_CPU_AMD64 #define NUM_WAYS 8 #define WOP_M1 WOP_8 #else #define NUM_WAYS 4 #define WOP_M1 WOP_4 #endif #define WOP(op) op (m0, 0) WOP_M1(op) #define DECLARE_VAR(reg, ii) __m128i reg; #define LOAD_data( reg, ii) reg = data[ii]; #define STORE_data( reg, ii) data[ii] = reg; #if (NUM_WAYS > 1) #define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]) #endif #define MM_OP_key(op, reg) MM_OP(op, reg, key); #define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg) #define AES_DEC_LAST( reg, ii) MM_OP_key (_mm_aesdeclast_si128, reg) #define AES_ENC( reg, ii) MM_OP_key (_mm_aesenc_si128, reg) #define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg) #define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) #define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr; #define CTR_END( reg, ii) MM_XOR (data[ii], reg) #define WOP_KEY(op, n) { \ const __m128i key = w[n]; \ WOP(op); } #define WIDE_LOOP_START \ dataEnd = data + numBlocks; \ if (numBlocks >= NUM_WAYS) \ { dataEnd -= NUM_WAYS; do { \ #define WIDE_LOOP_END \ data += NUM_WAYS; \ } while (data <= dataEnd); \ dataEnd += NUM_WAYS; } \ #define SINGLE_LOOP \ for (; data < dataEnd; data++) #ifdef USE_INTEL_VAES #define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src) #define AVX_DECLARE_VAR(reg, ii) __m256i reg; #define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii]; #define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg; /* AVX_XOR_data_M1() needs unaligned memory load if (we don't use _mm256_loadu_si256() here) { Most compilers with enabled optimizations generate fused AVX (LOAD + OP) instruction that can load unaligned data. But GCC and CLANG without -O2 or -O1 optimizations can generate separated LOAD-ALIGNED (vmovdqa) instruction that will fail on execution. } Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here. v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler. */ #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii]))) // for debug only: the following code will fail on execution, if compiled by some compilers: // #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii])) #define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg) #define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg) #define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg) #define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg) #define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg) #define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key); #define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg) #define AVX_WOP_KEY(op, n) { \ const __m256i key = w[n]; \ WOP(op); } #define NUM_AES_KEYS_MAX 15 #define WIDE_LOOP_START_AVX(OP) \ dataEnd = data + numBlocks; \ if (numBlocks >= NUM_WAYS * 2) \ { __m256i keys[NUM_AES_KEYS_MAX]; \ UInt32 ii; \ OP \ for (ii = 0; ii < numRounds; ii++) \ keys[ii] = _mm256_broadcastsi128_si256(p[ii]); \ dataEnd -= NUM_WAYS * 2; do { \ #define WIDE_LOOP_END_AVX(OP) \ data += NUM_WAYS * 2; \ } while (data <= dataEnd); \ dataEnd += NUM_WAYS * 2; \ OP \ _mm256_zeroupper(); \ } \ /* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, MSVC still can insert vzeroupper instruction. */ #endif AES_FUNC_START2 (AesCbc_Decode_HW) { __m128i *p = (__m128i *)(void *)ivAes; __m128i *data = (__m128i *)(void *)data8; __m128i iv = *p; const __m128i *wStart = p + *(const UInt32 *)(p + 1) * 2 + 2 - 1; const __m128i *dataEnd; p += 2; WIDE_LOOP_START { const __m128i *w = wStart; WOP (DECLARE_VAR) WOP (LOAD_data) WOP_KEY (AES_XOR, 1) do { WOP_KEY (AES_DEC, 0) w--; } while (w != p); WOP_KEY (AES_DEC_LAST, 0) MM_XOR (m0, iv) WOP_M1 (XOR_data_M1) iv = data[NUM_WAYS - 1]; WOP (STORE_data) } WIDE_LOOP_END SINGLE_LOOP { const __m128i *w = wStart - 1; __m128i m = _mm_xor_si128 (w[2], *data); do { MM_OP_m (_mm_aesdec_si128, w[1]) MM_OP_m (_mm_aesdec_si128, w[0]) w -= 2; } while (w != p); MM_OP_m (_mm_aesdec_si128, w[1]) MM_OP_m (_mm_aesdeclast_si128, w[0]) MM_XOR (m, iv) iv = *data; *data = m; } p[-2] = iv; } AES_FUNC_START2 (AesCtr_Code_HW) { __m128i *p = (__m128i *)(void *)ivAes; __m128i *data = (__m128i *)(void *)data8; __m128i ctr = *p; UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1; const __m128i *dataEnd; __m128i one = _mm_cvtsi32_si128(1); p += 2; WIDE_LOOP_START { const __m128i *w = p; UInt32 r = numRoundsMinus2; WOP (DECLARE_VAR) WOP (CTR_START) WOP_KEY (AES_XOR, 0) w += 1; do { WOP_KEY (AES_ENC, 0) w += 1; } while (--r); WOP_KEY (AES_ENC_LAST, 0) WOP (CTR_END) } WIDE_LOOP_END SINGLE_LOOP { UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1; const __m128i *w = p; __m128i m; MM_OP (_mm_add_epi64, ctr, one) m = _mm_xor_si128 (ctr, p[0]); w += 1; do { MM_OP_m (_mm_aesenc_si128, w[0]) MM_OP_m (_mm_aesenc_si128, w[1]) w += 2; } while (--numRounds2); MM_OP_m (_mm_aesenc_si128, w[0]) MM_OP_m (_mm_aesenclast_si128, w[1]) MM_XOR (*data, m) } p[-2] = ctr; } #ifdef USE_INTEL_VAES /* GCC before 2013-Jun: : #ifdef __AVX__ #include #endif GCC after 2013-Jun: : #include CLANG 3.8+: { : #if !defined(_MSC_VER) || defined(__AVX__) #include #endif if (the compiler is clang for Windows and if global arch is not set for __AVX__) [ if (defined(_MSC_VER) && !defined(__AVX__)) ] { doesn't include and we have 2 ways to fix it: 1) we can define required __AVX__ before or 2) we can include after } } If we include manually for GCC/CLANG, it's required that must be included before . */ /* #if defined(__clang__) && defined(_MSC_VER) #define __AVX__ #define __AVX2__ #define __VAES__ #endif */ #include #if defined(__clang__) && defined(_MSC_VER) #if !defined(__AVX__) #include #endif #if !defined(__AVX2__) #include #endif #if !defined(__VAES__) #include #endif #endif // __clang__ && _MSC_VER #ifndef ATTRIB_VAES #define ATTRIB_VAES #endif #define VAES_FUNC_START2(name) \ AES_FUNC_START (name); \ ATTRIB_VAES \ AES_FUNC_START (name) VAES_FUNC_START2 (AesCbc_Decode_HW_256) { __m128i *p = (__m128i *)(void *)ivAes; __m128i *data = (__m128i *)(void *)data8; __m128i iv = *p; const __m128i *dataEnd; UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; p += 2; WIDE_LOOP_START_AVX(;) { const __m256i *w = keys + numRounds - 2; WOP (AVX_DECLARE_VAR) WOP (AVX_LOAD_data) AVX_WOP_KEY (AVX_AES_XOR, 1) do { AVX_WOP_KEY (AVX_AES_DEC, 0) w--; } while (w != keys); AVX_WOP_KEY (AVX_AES_DEC_LAST, 0) AVX_XOR (m0, _mm256_setr_m128i(iv, data[0])) WOP_M1 (AVX_XOR_data_M1) iv = data[NUM_WAYS * 2 - 1]; WOP (AVX_STORE_data) } WIDE_LOOP_END_AVX(;) SINGLE_LOOP { const __m128i *w = p + *(const UInt32 *)(p + 1 - 2) * 2 + 1 - 3; __m128i m = _mm_xor_si128 (w[2], *data); do { MM_OP_m (_mm_aesdec_si128, w[1]) MM_OP_m (_mm_aesdec_si128, w[0]) w -= 2; } while (w != p); MM_OP_m (_mm_aesdec_si128, w[1]) MM_OP_m (_mm_aesdeclast_si128, w[0]) MM_XOR (m, iv) iv = *data; *data = m; } p[-2] = iv; } /* SSE2: _mm_cvtsi32_si128 : movd AVX: _mm256_setr_m128i : vinsertf128 AVX2: _mm256_add_epi64 : vpaddq ymm, ymm, ymm _mm256_extracti128_si256 : vextracti128 _mm256_broadcastsi128_si256 : vbroadcasti128 */ #define AVX_CTR_LOOP_START \ ctr2 = _mm256_setr_m128i(_mm_sub_epi64(ctr, one), ctr); \ two = _mm256_setr_m128i(one, one); \ two = _mm256_add_epi64(two, two); \ // two = _mm256_setr_epi64x(2, 0, 2, 0); #define AVX_CTR_LOOP_ENC \ ctr = _mm256_extracti128_si256 (ctr2, 1); \ VAES_FUNC_START2 (AesCtr_Code_HW_256) { __m128i *p = (__m128i *)(void *)ivAes; __m128i *data = (__m128i *)(void *)data8; __m128i ctr = *p; UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; const __m128i *dataEnd; __m128i one = _mm_cvtsi32_si128(1); __m256i ctr2, two; p += 2; WIDE_LOOP_START_AVX (AVX_CTR_LOOP_START) { const __m256i *w = keys; UInt32 r = numRounds - 2; WOP (AVX_DECLARE_VAR) AVX_WOP_KEY (AVX_CTR_START, 0) w += 1; do { AVX_WOP_KEY (AVX_AES_ENC, 0) w += 1; } while (--r); AVX_WOP_KEY (AVX_AES_ENC_LAST, 0) WOP (AVX_CTR_END) } WIDE_LOOP_END_AVX (AVX_CTR_LOOP_ENC) SINGLE_LOOP { UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1; const __m128i *w = p; __m128i m; MM_OP (_mm_add_epi64, ctr, one) m = _mm_xor_si128 (ctr, p[0]); w += 1; do { MM_OP_m (_mm_aesenc_si128, w[0]) MM_OP_m (_mm_aesenc_si128, w[1]) w += 2; } while (--numRounds2); MM_OP_m (_mm_aesenc_si128, w[0]) MM_OP_m (_mm_aesenclast_si128, w[1]) MM_XOR (*data, m) } p[-2] = ctr; } #endif // USE_INTEL_VAES #else // USE_INTEL_AES /* no USE_INTEL_AES */ #if defined(Z7_USE_AES_HW_STUB) // We can compile this file with another C compiler, // or we can compile asm version. // So we can generate real code instead of this stub function. // #if defined(_MSC_VER) #pragma message("AES HW_SW stub was used") // #endif #if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB) #define AES_TYPE_keys UInt32 #define AES_TYPE_data Byte #endif #define AES_FUNC_START(name) \ void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \ #define AES_COMPAT_STUB(name) \ AES_FUNC_START(name); \ AES_FUNC_START(name ## _HW) \ { name(p, data, numBlocks); } AES_COMPAT_STUB (AesCbc_Encode) AES_COMPAT_STUB (AesCbc_Decode) AES_COMPAT_STUB (AesCtr_Code) #endif // Z7_USE_AES_HW_STUB #endif // USE_INTEL_AES #ifndef USE_INTEL_VAES #if defined(Z7_USE_VAES_HW_STUB) // #if defined(_MSC_VER) #pragma message("VAES HW_SW stub was used") // #endif #define VAES_COMPAT_STUB(name) \ void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \ void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks) \ { name((AES_TYPE_keys *)(void *)p, (AES_TYPE_data *)(void *)data, numBlocks); } VAES_COMPAT_STUB (AesCbc_Decode_HW) VAES_COMPAT_STUB (AesCtr_Code_HW) #endif #endif // ! USE_INTEL_VAES #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__ARM_FEATURE_AES) \ || defined(__ARM_FEATURE_CRYPTO) #define USE_HW_AES #else #if defined(MY_CPU_ARM64) \ || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \ || defined(Z7_MSC_VER_ORIGINAL) #if defined(__ARM_FP) && \ ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) \ ) \ || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) && \ (Z7_CLANG_VERSION < 170000 || \ Z7_CLANG_VERSION > 170001) #define USE_HW_AES #endif #endif #endif #endif #ifdef USE_HW_AES // #pragma message("=== AES HW === ") // __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_AES #if defined(__clang__) || defined(__GNUC__) #if !defined(__ARM_FEATURE_AES) && \ !defined(__ARM_FEATURE_CRYPTO) #ifdef MY_CPU_ARM64 #if defined(__clang__) #define ATTRIB_AES __attribute__((__target__("crypto"))) #else #define ATTRIB_AES __attribute__((__target__("+crypto"))) #endif #else #if defined(__clang__) #define ATTRIB_AES __attribute__((__target__("armv8-a,aes"))) #else #define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #endif #endif #endif #else // _MSC_VER // for arm32 #define _ARM_USE_NEW_NEON_INTRINSICS #endif #ifndef ATTRIB_AES #define ATTRIB_AES #endif #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) #include #else /* clang-17.0.1: error : Cannot select: intrinsic %llvm.arm.neon.aese clang 3.8.1 : __ARM_NEON : defined(__ARM_FEATURE_CRYPTO) 7.0.1 : __ARM_NEON : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO) 11.?.0 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO) 13.0.1 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_AES) 16 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 */ #if defined(__clang__) && __clang_major__ < 16 #if !defined(__ARM_FEATURE_AES) && \ !defined(__ARM_FEATURE_CRYPTO) // #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ") Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1 // #if defined(__clang__) && __clang_major__ < 13 #define __ARM_FEATURE_CRYPTO 1 // #else #define __ARM_FEATURE_AES 1 // #endif Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // clang #if defined(__clang__) #if defined(__ARM_ARCH) && __ARM_ARCH < 8 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER // #pragma message("#define __ARM_ARCH 8") #undef __ARM_ARCH #define __ARM_ARCH 8 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // clang #include #if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \ defined(__ARM_FEATURE_CRYPTO) && \ defined(__ARM_FEATURE_AES) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #undef __ARM_FEATURE_CRYPTO #undef __ARM_FEATURE_AES #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER // #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ") #endif #endif // Z7_MSC_VER_ORIGINAL typedef uint8x16_t v128; #define AES_FUNC_START(name) \ void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks) // void Z7_FASTCALL name(v128 *p, v128 *data, size_t numBlocks) #define AES_FUNC_START2(name) \ AES_FUNC_START (name); \ ATTRIB_AES \ AES_FUNC_START (name) #define MM_OP(op, dest, src) dest = op(dest, src); #define MM_OP_m(op, src) MM_OP(op, m, src) #define MM_OP1_m(op) m = op(m); #define MM_XOR( dest, src) MM_OP(veorq_u8, dest, src) #define MM_XOR_m( src) MM_XOR(m, src) #define AES_E_m(k) MM_OP_m (vaeseq_u8, k) #define AES_E_MC_m(k) AES_E_m (k) MM_OP1_m(vaesmcq_u8) AES_FUNC_START2 (AesCbc_Encode_HW) { v128 * const p = (v128*)(void*)ivAes; v128 *data = (v128*)(void*)data8; v128 m = *p; const v128 k0 = p[2]; const v128 k1 = p[3]; const v128 k2 = p[4]; const v128 k3 = p[5]; const v128 k4 = p[6]; const v128 k5 = p[7]; const v128 k6 = p[8]; const v128 k7 = p[9]; const v128 k8 = p[10]; const v128 k9 = p[11]; const UInt32 numRounds2 = *(const UInt32 *)(p + 1); const v128 *w = p + ((size_t)numRounds2 * 2); const v128 k_z1 = w[1]; const v128 k_z0 = w[2]; for (; numBlocks != 0; numBlocks--, data++) { MM_XOR_m (*data) AES_E_MC_m (k0) AES_E_MC_m (k1) AES_E_MC_m (k2) AES_E_MC_m (k3) AES_E_MC_m (k4) AES_E_MC_m (k5) AES_E_MC_m (k6) AES_E_MC_m (k7) AES_E_MC_m (k8) if (numRounds2 >= 6) { AES_E_MC_m (k9) AES_E_MC_m (p[12]) if (numRounds2 != 6) { AES_E_MC_m (p[13]) AES_E_MC_m (p[14]) } } AES_E_m (k_z1) MM_XOR_m (k_z0) *data = m; } *p = m; } #define WOP_1(op) #define WOP_2(op) WOP_1 (op) op (m1, 1) #define WOP_3(op) WOP_2 (op) op (m2, 2) #define WOP_4(op) WOP_3 (op) op (m3, 3) #define WOP_5(op) WOP_4 (op) op (m4, 4) #define WOP_6(op) WOP_5 (op) op (m5, 5) #define WOP_7(op) WOP_6 (op) op (m6, 6) #define WOP_8(op) WOP_7 (op) op (m7, 7) #define NUM_WAYS 8 #define WOP_M1 WOP_8 #define WOP(op) op (m0, 0) WOP_M1(op) #define DECLARE_VAR(reg, ii) v128 reg; #define LOAD_data( reg, ii) reg = data[ii]; #define STORE_data( reg, ii) data[ii] = reg; #if (NUM_WAYS > 1) #define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]) #endif #define MM_OP_key(op, reg) MM_OP (op, reg, key) #define AES_D_m(k) MM_OP_m (vaesdq_u8, k) #define AES_D_IMC_m(k) AES_D_m (k) MM_OP1_m (vaesimcq_u8) #define AES_XOR( reg, ii) MM_OP_key (veorq_u8, reg) #define AES_D( reg, ii) MM_OP_key (vaesdq_u8, reg) #define AES_E( reg, ii) MM_OP_key (vaeseq_u8, reg) #define AES_D_IMC( reg, ii) AES_D (reg, ii) reg = vaesimcq_u8(reg); #define AES_E_MC( reg, ii) AES_E (reg, ii) reg = vaesmcq_u8(reg); #define CTR_START(reg, ii) MM_OP (vaddq_u64, ctr, one) reg = vreinterpretq_u8_u64(ctr); #define CTR_END( reg, ii) MM_XOR (data[ii], reg) #define WOP_KEY(op, n) { \ const v128 key = w[n]; \ WOP(op) } #define WIDE_LOOP_START \ dataEnd = data + numBlocks; \ if (numBlocks >= NUM_WAYS) \ { dataEnd -= NUM_WAYS; do { \ #define WIDE_LOOP_END \ data += NUM_WAYS; \ } while (data <= dataEnd); \ dataEnd += NUM_WAYS; } \ #define SINGLE_LOOP \ for (; data < dataEnd; data++) AES_FUNC_START2 (AesCbc_Decode_HW) { v128 *p = (v128*)(void*)ivAes; v128 *data = (v128*)(void*)data8; v128 iv = *p; const v128 *wStart = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; const v128 *dataEnd; p += 2; WIDE_LOOP_START { const v128 *w = wStart; WOP (DECLARE_VAR) WOP (LOAD_data) WOP_KEY (AES_D_IMC, 2) do { WOP_KEY (AES_D_IMC, 1) WOP_KEY (AES_D_IMC, 0) w -= 2; } while (w != p); WOP_KEY (AES_D, 1) WOP_KEY (AES_XOR, 0) MM_XOR (m0, iv) WOP_M1 (XOR_data_M1) iv = data[NUM_WAYS - 1]; WOP (STORE_data) } WIDE_LOOP_END SINGLE_LOOP { const v128 *w = wStart; v128 m = *data; AES_D_IMC_m (w[2]) do { AES_D_IMC_m (w[1]) AES_D_IMC_m (w[0]) w -= 2; } while (w != p); AES_D_m (w[1]) MM_XOR_m (w[0]) MM_XOR_m (iv) iv = *data; *data = m; } p[-2] = iv; } AES_FUNC_START2 (AesCtr_Code_HW) { v128 *p = (v128*)(void*)ivAes; v128 *data = (v128*)(void*)data8; uint64x2_t ctr = vreinterpretq_u64_u8(*p); const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; const v128 *dataEnd; uint64x2_t one = vdupq_n_u64(0); // the bug in clang: // __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2); #if defined(__clang__) && (__clang_major__ <= 9) #pragma GCC diagnostic ignored "-Wvector-conversion" #endif one = vsetq_lane_u64(1, one, 0); p += 2; WIDE_LOOP_START { const v128 *w = p; WOP (DECLARE_VAR) WOP (CTR_START) do { WOP_KEY (AES_E_MC, 0) WOP_KEY (AES_E_MC, 1) w += 2; } while (w != wEnd); WOP_KEY (AES_E_MC, 0) WOP_KEY (AES_E, 1) WOP_KEY (AES_XOR, 2) WOP (CTR_END) } WIDE_LOOP_END SINGLE_LOOP { const v128 *w = p; v128 m; CTR_START (m, 0) do { AES_E_MC_m (w[0]) AES_E_MC_m (w[1]) w += 2; } while (w != wEnd); AES_E_MC_m (w[0]) AES_E_m (w[1]) MM_XOR_m (w[2]) CTR_END (m, 0) } p[-2] = vreinterpretq_u8_u64(ctr); } #endif // USE_HW_AES #endif // MY_CPU_ARM_OR_ARM64 #undef NUM_WAYS #undef WOP_M1 #undef WOP #undef DECLARE_VAR #undef LOAD_data #undef STORE_data #undef USE_INTEL_AES #undef USE_HW_AES tmp41wklro_/C/Alloc.c0000444000175000001440000003223414564442640015536 0ustar nabijaczleweliusers/* Alloc.c -- Memory allocation functions 2024-02-18 : Igor Pavlov : Public domain */ #include "Precomp.h" #ifdef _WIN32 #include "7zWindows.h" #endif #include #include "Alloc.h" #if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \ (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502) // < Win2003 (xp-64) #define Z7_USE_DYN_GetLargePageMinimum #endif // for debug: #if 0 #if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16) // #pragma message("=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === ") #define Z7_ALLOC_NO_OFFSET_ALLOCATOR #endif #endif // #define SZ_ALLOC_DEBUG /* #define SZ_ALLOC_DEBUG */ /* use SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef SZ_ALLOC_DEBUG #include #include static int g_allocCount = 0; #ifdef _WIN32 static int g_allocCountMid = 0; static int g_allocCountBig = 0; #endif #define CONVERT_INT_TO_STR(charType, tempSize) \ char temp[tempSize]; unsigned i = 0; \ while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } \ *s++ = (charType)('0' + (unsigned)val); \ while (i != 0) { i--; *s++ = temp[i]; } \ *s = 0; static void ConvertUInt64ToString(UInt64 val, char *s) { CONVERT_INT_TO_STR(char, 24) } #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) static void ConvertUInt64ToHex(UInt64 val, char *s) { UInt64 v = val; unsigned i; for (i = 1;; i++) { v >>= 4; if (v == 0) break; } s[i] = 0; do { unsigned t = (unsigned)(val & 0xF); val >>= 4; s[--i] = GET_HEX_CHAR(t); } while (i); } #define DEBUG_OUT_STREAM stderr static void Print(const char *s) { fputs(s, DEBUG_OUT_STREAM); } static void PrintAligned(const char *s, size_t align) { size_t len = strlen(s); for(;;) { fputc(' ', DEBUG_OUT_STREAM); if (len >= align) break; ++len; } Print(s); } static void PrintLn(void) { Print("\n"); } static void PrintHex(UInt64 v, size_t align) { char s[32]; ConvertUInt64ToHex(v, s); PrintAligned(s, align); } static void PrintDec(int v, size_t align) { char s[32]; ConvertUInt64ToString((unsigned)v, s); PrintAligned(s, align); } static void PrintAddr(void *p) { PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12); } #define PRINT_REALLOC(name, cnt, size, ptr) { \ Print(name " "); \ if (!ptr) PrintDec(cnt++, 10); \ PrintHex(size, 10); \ PrintAddr(ptr); \ PrintLn(); } #define PRINT_ALLOC(name, cnt, size, ptr) { \ Print(name " "); \ PrintDec(cnt++, 10); \ PrintHex(size, 10); \ PrintAddr(ptr); \ PrintLn(); } #define PRINT_FREE(name, cnt, ptr) if (ptr) { \ Print(name " "); \ PrintDec(--cnt, 10); \ PrintAddr(ptr); \ PrintLn(); } #else #ifdef _WIN32 #define PRINT_ALLOC(name, cnt, size, ptr) #endif #define PRINT_FREE(name, cnt, ptr) #define Print(s) #define PrintLn() #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR #define PrintHex(v, align) #endif #define PrintAddr(p) #endif /* by specification: malloc(non_NULL, 0) : returns NULL or a unique pointer value that can later be successfully passed to free() realloc(NULL, size) : the call is equivalent to malloc(size) realloc(non_NULL, 0) : the call is equivalent to free(ptr) in main compilers: malloc(0) : returns non_NULL realloc(NULL, 0) : returns non_NULL realloc(non_NULL, 0) : returns NULL */ void *MyAlloc(size_t size) { if (size == 0) return NULL; // PRINT_ALLOC("Alloc ", g_allocCount, size, NULL) #ifdef SZ_ALLOC_DEBUG { void *p = malloc(size); if (p) { PRINT_ALLOC("Alloc ", g_allocCount, size, p) } return p; } #else return malloc(size); #endif } void MyFree(void *address) { PRINT_FREE("Free ", g_allocCount, address) free(address); } void *MyRealloc(void *address, size_t size) { if (size == 0) { MyFree(address); return NULL; } // PRINT_REALLOC("Realloc ", g_allocCount, size, address) #ifdef SZ_ALLOC_DEBUG { void *p = realloc(address, size); if (p) { PRINT_REALLOC("Realloc ", g_allocCount, size, address) } return p; } #else return realloc(address, size); #endif } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return NULL; #ifdef SZ_ALLOC_DEBUG { void *p = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); if (p) { PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, p) } return p; } #else return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); #endif } void MidFree(void *address) { PRINT_FREE("Free-Mid", g_allocCountMid, address) if (!address) return; VirtualFree(address, 0, MEM_RELEASE); } #ifdef Z7_LARGE_PAGES #ifdef MEM_LARGE_PAGES #define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES #else #define MY_MEM_LARGE_PAGES 0x20000000 #endif extern SIZE_T g_LargePageSize; SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); void SetLargePageSize(void) { SIZE_T size; #ifdef Z7_USE_DYN_GetLargePageMinimum Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION const Func_GetLargePageMinimum fn = (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (!fn) return; size = fn(); #else size = GetLargePageMinimum(); #endif if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; } #endif // Z7_LARGE_PAGES void *BigAlloc(size_t size) { if (size == 0) return NULL; PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL) #ifdef Z7_LARGE_PAGES { SIZE_T ps = g_LargePageSize; if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) { size_t size2; ps--; size2 = (size + ps) & ~ps; if (size2 >= size) { void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE); if (p) { PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) return p; } } } } #endif return MidAlloc(size); } void BigFree(void *address) { PRINT_FREE("Free-Big", g_allocCountBig, address) MidFree(address); } #endif // _WIN32 static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MyAlloc(size); } static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MyFree(address); } const ISzAlloc g_Alloc = { SzAlloc, SzFree }; #ifdef _WIN32 static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); } static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); } static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); } static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); } const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; #endif #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR #define ADJUST_ALLOC_SIZE 0 /* #define ADJUST_ALLOC_SIZE (sizeof(void *) - 1) */ /* Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if MyAlloc() can return address that is NOT multiple of sizeof(void *). */ /* uintptr_t : C99 (optional) : unsupported in VS6 */ typedef #ifdef _WIN32 UINT_PTR #elif 1 uintptr_t #else ptrdiff_t #endif MY_uintptr_t; #if 0 \ || (defined(__CHERI__) \ || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8)) // for 128-bit pointers (cheri): #define MY_ALIGN_PTR_DOWN(p, align) \ ((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1)))) #else #define MY_ALIGN_PTR_DOWN(p, align) \ ((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1)))) #endif #endif #if !defined(_WIN32) \ && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \ || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) #define USE_posix_memalign #endif #ifndef USE_posix_memalign #define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align) #endif /* This posix_memalign() is for test purposes only. We also need special Free() function instead of free(), if this posix_memalign() is used. */ /* static int posix_memalign(void **ptr, size_t align, size_t size) { size_t newSize = size + align; void *p; void *pAligned; *ptr = NULL; if (newSize < size) return 12; // ENOMEM p = MyAlloc(newSize); if (!p) return 12; // ENOMEM pAligned = MY_ALIGN_PTR_UP_PLUS(p, align); ((void **)pAligned)[-1] = p; *ptr = pAligned; return 0; } */ /* ALLOC_ALIGN_SIZE >= sizeof(void *) ALLOC_ALIGN_SIZE >= cache_line_size */ #define ALLOC_ALIGN_SIZE ((size_t)1 << 7) void *z7_AlignedAlloc(size_t size) { #ifndef USE_posix_memalign void *p; void *pAligned; size_t newSize; /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned block to prevent cache line sharing with another allocated blocks */ newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE; if (newSize < size) return NULL; p = MyAlloc(newSize); if (!p) return NULL; pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE); Print(" size="); PrintHex(size, 8); Print(" a_size="); PrintHex(newSize, 8); Print(" ptr="); PrintAddr(p); Print(" a_ptr="); PrintAddr(pAligned); PrintLn(); ((void **)pAligned)[-1] = p; return pAligned; #else void *p; if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) return NULL; Print(" posix_memalign="); PrintAddr(p); PrintLn(); return p; #endif } void z7_AlignedFree(void *address) { #ifndef USE_posix_memalign if (address) MyFree(((void **)address)[-1]); #else free(address); #endif } static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) { UNUSED_VAR(pp) return z7_AlignedAlloc(size); } static void SzAlignedFree(ISzAllocPtr pp, void *address) { UNUSED_VAR(pp) #ifndef USE_posix_memalign if (address) MyFree(((void **)address)[-1]); #else free(address); #endif } const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; /* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR #if 1 #define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) #define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] #else // we can use this simplified code, // if (CAlignOffsetAlloc::offset == (k * sizeof(void *)) #define REAL_BLOCK_PTR_VAR(p) (((void **)(p))[-1]) #endif #endif #if 0 #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR #include static void PrintPtr(const char *s, const void *p) { const Byte *p2 = (const Byte *)&p; unsigned i; printf("%s %p ", s, p); for (i = sizeof(p); i != 0;) { i--; printf("%02x", p2[i]); } printf("\n"); } #endif #endif static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) { #if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) UNUSED_VAR(pp) return z7_AlignedAlloc(size); #else const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); void *adr; void *pAligned; size_t newSize; size_t extra; size_t alignSize = (size_t)1 << p->numAlignBits; if (alignSize < sizeof(void *)) alignSize = sizeof(void *); if (p->offset >= alignSize) return NULL; /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned block to prevent cache line sharing with another allocated blocks */ extra = p->offset & (sizeof(void *) - 1); newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE; if (newSize < size) return NULL; adr = ISzAlloc_Alloc(p->baseAlloc, newSize); if (!adr) return NULL; pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; #if 0 printf("\nalignSize = %6x, offset=%6x, size=%8x \n", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size); PrintPtr("base", adr); PrintPtr("alig", pAligned); #endif PrintLn(); Print("- Aligned: "); Print(" size="); PrintHex(size, 8); Print(" a_size="); PrintHex(newSize, 8); Print(" ptr="); PrintAddr(adr); Print(" a_ptr="); PrintAddr(pAligned); PrintLn(); REAL_BLOCK_PTR_VAR(pAligned) = adr; return pAligned; #endif } static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) { #if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) UNUSED_VAR(pp) z7_AlignedFree(address); #else if (address) { const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); PrintLn(); Print("- Aligned Free: "); PrintLn(); ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); } #endif } void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p) { p->vt.Alloc = AlignOffsetAlloc_Alloc; p->vt.Free = AlignOffsetAlloc_Free; } tmp41wklro_/C/Alloc.h0000444000175000001440000000365314553463320015542 0ustar nabijaczleweliusers/* Alloc.h -- Memory allocation functions 2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_ALLOC_H #define ZIP7_INC_ALLOC_H #include "7zTypes.h" EXTERN_C_BEGIN /* MyFree(NULL) : is allowed, as free(NULL) MyAlloc(0) : returns NULL : but malloc(0) is allowed to return NULL or non_NULL MyRealloc(NULL, 0) : returns NULL : but realloc(NULL, 0) is allowed to return NULL or non_NULL MyRealloc() is similar to realloc() for the following cases: MyRealloc(non_NULL, 0) : returns NULL and always calls MyFree(ptr) MyRealloc(NULL, non_ZERO) : returns NULL, if allocation failed MyRealloc(non_NULL, non_ZERO) : returns NULL, if reallocation failed */ void *MyAlloc(size_t size); void MyFree(void *address); void *MyRealloc(void *address, size_t size); void *z7_AlignedAlloc(size_t size); void z7_AlignedFree(void *p); #ifdef _WIN32 #ifdef Z7_LARGE_PAGES void SetLargePageSize(void); #endif void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); /* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */ #else #define MidAlloc(size) z7_AlignedAlloc(size) #define MidFree(address) z7_AlignedFree(address) #define BigAlloc(size) z7_AlignedAlloc(size) #define BigFree(address) z7_AlignedFree(address) #endif extern const ISzAlloc g_Alloc; #ifdef _WIN32 extern const ISzAlloc g_BigAlloc; extern const ISzAlloc g_MidAlloc; #else #define g_BigAlloc g_AlignedAlloc #define g_MidAlloc g_AlignedAlloc #endif extern const ISzAlloc g_AlignedAlloc; typedef struct { ISzAlloc vt; ISzAllocPtr baseAlloc; unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */ size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */ } CAlignOffsetAlloc; void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p); EXTERN_C_END #endif tmp41wklro_/C/Asm_c.mak0000444000175000001440000000051114576764400016051 0ustar nabijaczleweliusers!IFDEF ASM_OBJS !IF "$(PLATFORM)" == "arm64" $(ASM_OBJS): ../../../Asm/arm64/$(*B).S $(COMPL_ASM_CLANG) !ELSEIF "$(PLATFORM)" == "arm" $(ASM_OBJS): ../../../Asm/arm/$(*B).asm $(COMPL_ASM) !ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" $(ASM_OBJS): ../../../Asm/x86/$(*B).asm $(COMPL_ASM) !ENDIF !ENDIF tmp41wklro_/C/Bcj2.c0000444000175000001440000002025414377637100015262 0ustar nabijaczleweliusers/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) 2023-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bcj2.h" #include "CpuArch.h" #define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 // UInt32 bcj2_stats[256 + 2][2]; void Bcj2Dec_Init(CBcj2Dec *p) { unsigned i; p->state = BCJ2_STREAM_RC; // BCJ2_DEC_STATE_OK; p->ip = 0; p->temp = 0; p->range = 0; p->code = 0; for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) p->probs[i] = kBitModelTotal >> 1; } SRes Bcj2Dec_Decode(CBcj2Dec *p) { UInt32 v = p->temp; // const Byte *src; if (p->range <= 5) { UInt32 code = p->code; p->state = BCJ2_DEC_STATE_ERROR; /* for case if we return SZ_ERROR_DATA; */ for (; p->range != 5; p->range++) { if (p->range == 1 && code != 0) return SZ_ERROR_DATA; if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) { p->state = BCJ2_STREAM_RC; return SZ_OK; } code = (code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; p->code = code; } if (code == 0xffffffff) return SZ_ERROR_DATA; p->range = 0xffffffff; } // else { unsigned state = p->state; // we check BCJ2_IS_32BIT_STREAM() here instead of check in the main loop if (BCJ2_IS_32BIT_STREAM(state)) { const Byte *cur = p->bufs[state]; if (cur == p->lims[state]) return SZ_OK; p->bufs[state] = cur + 4; { const UInt32 ip = p->ip + 4; v = GetBe32a(cur) - ip; p->ip = ip; } state = BCJ2_DEC_STATE_ORIG_0; } if ((unsigned)(state - BCJ2_DEC_STATE_ORIG_0) < 4) { Byte *dest = p->dest; for (;;) { if (dest == p->destLim) { p->state = state; p->temp = v; return SZ_OK; } *dest++ = (Byte)v; p->dest = dest; if (++state == BCJ2_DEC_STATE_ORIG_3 + 1) break; v >>= 8; } } } // src = p->bufs[BCJ2_STREAM_MAIN]; for (;;) { /* if (BCJ2_IS_32BIT_STREAM(p->state)) p->state = BCJ2_DEC_STATE_OK; else */ { if (p->range < kTopValue) { if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) { p->state = BCJ2_STREAM_RC; p->temp = v; return SZ_OK; } p->range <<= 8; p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; } { const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; const Byte *srcLim; Byte *dest = p->dest; { const SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); SizeT num = (SizeT)(p->destLim - dest); if (num >= rem) num = rem; #define NUM_ITERS 4 #if (NUM_ITERS & (NUM_ITERS - 1)) == 0 num &= ~((SizeT)NUM_ITERS - 1); // if (NUM_ITERS == (1 << x)) #else num -= num % NUM_ITERS; // if (NUM_ITERS != (1 << x)) #endif srcLim = src + num; } #define NUM_SHIFT_BITS 24 #define ONE_ITER(indx) { \ const unsigned b = src[indx]; \ *dest++ = (Byte)b; \ v = (v << NUM_SHIFT_BITS) | b; \ if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \ if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \ ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \ /* ++dest */; /* v = b; */ } if (src != srcLim) for (;;) { /* The dependency chain of 2-cycle for (v) calculation is not big problem here. But we can remove dependency chain with v = b in the end of loop. */ ONE_ITER(0) #if (NUM_ITERS > 1) ONE_ITER(1) #if (NUM_ITERS > 2) ONE_ITER(2) #if (NUM_ITERS > 3) ONE_ITER(3) #if (NUM_ITERS > 4) ONE_ITER(4) #if (NUM_ITERS > 5) ONE_ITER(5) #if (NUM_ITERS > 6) ONE_ITER(6) #if (NUM_ITERS > 7) ONE_ITER(7) #endif #endif #endif #endif #endif #endif #endif src += NUM_ITERS; if (src == srcLim) break; } if (src == srcLim) #if (NUM_ITERS > 1) for (;;) #endif { #if (NUM_ITERS > 1) if (src == p->lims[BCJ2_STREAM_MAIN] || dest == p->destLim) #endif { const SizeT num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); p->bufs[BCJ2_STREAM_MAIN] = src; p->dest = dest; p->ip += (UInt32)num; /* state BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ p->state = src == p->lims[BCJ2_STREAM_MAIN] ? (unsigned)BCJ2_STREAM_MAIN : (unsigned)BCJ2_DEC_STATE_ORIG; p->temp = v; return SZ_OK; } #if (NUM_ITERS > 1) ONE_ITER(0) src++; #endif } { const SizeT num = (SizeT)(dest - p->dest); p->dest = dest; // p->dest += num; p->bufs[BCJ2_STREAM_MAIN] += num; // = src; p->ip += (UInt32)num; } { UInt32 bound, ttt; CBcj2Prob *prob; // unsigned index; /* prob = p->probs + (unsigned)((Byte)v == 0xe8 ? 2 + (Byte)(v >> 8) : ((v >> 5) & 1)); // ((Byte)v < 0xe8 ? 0 : 1)); */ { const unsigned c = ((v + 0x17) >> 6) & 1; prob = p->probs + (unsigned) (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1)); // (Byte) // 8x->0 : e9->1 : xxe8->xx+2 // 8x->0x100 : e9->0x101 : xxe8->xx // (((0x100 - (e & ~v)) & (0x100 | (v >> 8))) + (e & v)); // (((0x101 + (~e | v)) & (0x100 | (v >> 8))) + (e & v)); } ttt = *prob; bound = (p->range >> kNumBitModelTotalBits) * ttt; if (p->code < bound) { // bcj2_stats[prob - p->probs][0]++; p->range = bound; *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); continue; } { // bcj2_stats[prob - p->probs][1]++; p->range -= bound; p->code -= bound; *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits)); } } } } { /* (v == 0xe8 ? 0 : 1) uses setcc instruction with additional zero register usage in x64 MSVC. */ // const unsigned cj = ((Byte)v == 0xe8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL; const Byte *cur = p->bufs[cj]; Byte *dest; SizeT rem; if (cur == p->lims[cj]) { p->state = cj; break; } v = GetBe32a(cur); p->bufs[cj] = cur + 4; { const UInt32 ip = p->ip + 4; v -= ip; p->ip = ip; } dest = p->dest; rem = (SizeT)(p->destLim - dest); if (rem < 4) { if ((unsigned)rem > 0) { dest[0] = (Byte)v; v >>= 8; if ((unsigned)rem > 1) { dest[1] = (Byte)v; v >>= 8; if ((unsigned)rem > 2) { dest[2] = (Byte)v; v >>= 8; }}} p->temp = v; p->dest = dest + rem; p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; break; } SetUi32(dest, v) v >>= 24; p->dest = dest + 4; } } if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) { p->range <<= 8; p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; } return SZ_OK; } #undef NUM_ITERS #undef ONE_ITER #undef NUM_SHIFT_BITS #undef kTopValue #undef kNumBitModelTotalBits #undef kBitModelTotal #undef kNumMoveBits tmp41wklro_/C/Bcj2.h0000444000175000001440000003014114400153020015240 0ustar nabijaczleweliusers/* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2) 2023-03-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_BCJ2_H #define ZIP7_INC_BCJ2_H #include "7zTypes.h" EXTERN_C_BEGIN #define BCJ2_NUM_STREAMS 4 enum { BCJ2_STREAM_MAIN, BCJ2_STREAM_CALL, BCJ2_STREAM_JUMP, BCJ2_STREAM_RC }; enum { BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, BCJ2_DEC_STATE_ORIG_1, BCJ2_DEC_STATE_ORIG_2, BCJ2_DEC_STATE_ORIG_3, BCJ2_DEC_STATE_ORIG, BCJ2_DEC_STATE_ERROR /* after detected data error */ }; enum { BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, BCJ2_ENC_STATE_FINISHED /* it's state after fully encoded stream */ }; /* #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) */ #define BCJ2_IS_32BIT_STREAM(s) ((unsigned)((unsigned)(s) - (unsigned)BCJ2_STREAM_CALL) < 2) /* CBcj2Dec / CBcj2Enc bufs sizes: BUF_SIZE(n) = lims[n] - bufs[n] bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4: (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 */ // typedef UInt32 CBcj2Prob; typedef UInt16 CBcj2Prob; /* BCJ2 encoder / decoder internal requirements: - If last bytes of stream contain marker (e8/e8/0f8x), then there is also encoded symbol (0 : no conversion) in RC stream. - One case of overlapped instructions is supported, if last byte of converted instruction is (0f) and next byte is (8x): marker [xx xx xx 0f] 8x then the pair (0f 8x) is treated as marker. */ /* ---------- BCJ2 Decoder ---------- */ /* CBcj2Dec: (dest) is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: bufs[BCJ2_STREAM_MAIN] >= dest && bufs[BCJ2_STREAM_MAIN] - dest >= BUF_SIZE(BCJ2_STREAM_CALL) + BUF_SIZE(BCJ2_STREAM_JUMP) reserve = bufs[BCJ2_STREAM_MAIN] - dest - ( BUF_SIZE(BCJ2_STREAM_CALL) + BUF_SIZE(BCJ2_STREAM_JUMP) ) and additional conditions: if (it's first call of Bcj2Dec_Decode() after Bcj2Dec_Init()) { (reserve != 1) : if (ver < v23.00) } else // if there are more than one calls of Bcj2Dec_Decode() after Bcj2Dec_Init()) { (reserve >= 6) : if (ver < v23.00) (reserve >= 4) : if (ver >= v23.00) We need that (reserve) because after first call of Bcj2Dec_Decode(), CBcj2Dec::temp can contain up to 4 bytes for writing to (dest). } (reserve == 0) is allowed, if we decode full stream via single call of Bcj2Dec_Decode(). (reserve == 0) also is allowed in case of multi-call, if we use fixed buffers, and (reserve) is calculated from full (final) sizes of all streams before first call. */ typedef struct { const Byte *bufs[BCJ2_NUM_STREAMS]; const Byte *lims[BCJ2_NUM_STREAMS]; Byte *dest; const Byte *destLim; unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ UInt32 ip; /* property of starting base for decoding */ UInt32 temp; /* Byte temp[4]; */ UInt32 range; UInt32 code; CBcj2Prob probs[2 + 256]; } CBcj2Dec; /* Note: Bcj2Dec_Init() sets (CBcj2Dec::ip = 0) if (ip != 0) property is required, the caller must set CBcj2Dec::ip after Bcj2Dec_Init() */ void Bcj2Dec_Init(CBcj2Dec *p); /* Bcj2Dec_Decode(): returns: SZ_OK SZ_ERROR_DATA : if data in 5 starting bytes of BCJ2_STREAM_RC stream are not correct */ SRes Bcj2Dec_Decode(CBcj2Dec *p); /* To check that decoding was finished you can compare sizes of processed streams with sizes known from another sources. You must do at least one mandatory check from the two following options: - the check for size of processed output (ORIG) stream. - the check for size of processed input (MAIN) stream. additional optional checks: - the checks for processed sizes of all input streams (MAIN, CALL, JUMP, RC) - the checks Bcj2Dec_IsMaybeFinished*() also before actual decoding you can check that the following condition is met for stream sizes: ( size(ORIG) == size(MAIN) + size(CALL) + size(JUMP) ) */ /* (state == BCJ2_STREAM_MAIN) means that decoder is ready for additional input data in BCJ2_STREAM_MAIN stream. Note that (state == BCJ2_STREAM_MAIN) is allowed for non-finished decoding. */ #define Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) ((_p_)->state == BCJ2_STREAM_MAIN) /* if the stream decoding was finished correctly, then range decoder part of CBcj2Dec also was finished, and then (CBcj2Dec::code == 0). Note that (CBcj2Dec::code == 0) is allowed for non-finished decoding. */ #define Bcj2Dec_IsMaybeFinished_code(_p_) ((_p_)->code == 0) /* use Bcj2Dec_IsMaybeFinished() only as additional check after at least one mandatory check from the two following options: - the check for size of processed output (ORIG) stream. - the check for size of processed input (MAIN) stream. */ #define Bcj2Dec_IsMaybeFinished(_p_) ( \ Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) && \ Bcj2Dec_IsMaybeFinished_code(_p_)) /* ---------- BCJ2 Encoder ---------- */ typedef enum { BCJ2_ENC_FINISH_MODE_CONTINUE, BCJ2_ENC_FINISH_MODE_END_BLOCK, BCJ2_ENC_FINISH_MODE_END_STREAM } EBcj2Enc_FinishMode; /* BCJ2_ENC_FINISH_MODE_CONTINUE: process non finished encoding. It notifies the encoder that additional further calls can provide more input data (src) than provided by current call. In that case the CBcj2Enc encoder still can move (src) pointer up to (srcLim), but CBcj2Enc encoder can store some of the last processed bytes (up to 4 bytes) from src to internal CBcj2Enc::temp[] buffer. at return: (CBcj2Enc::src will point to position that includes processed data and data copied to (temp[]) buffer) That data from (temp[]) buffer will be used in further calls. BCJ2_ENC_FINISH_MODE_END_BLOCK: finish encoding of current block (ended at srcLim) without RC flushing. at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_ORIG) && CBcj2Enc::src == CBcj2Enc::srcLim) : it shows that block encoding was finished. And the encoder is ready for new (src) data or for stream finish operation. finished block means { CBcj2Enc has completed block encoding up to (srcLim). (1 + 4 bytes) or (2 + 4 bytes) CALL/JUMP cortages will not cross block boundary at (srcLim). temporary CBcj2Enc buffer for (ORIG) src data is empty. 3 output uncompressed streams (MAIN, CALL, JUMP) were flushed. RC stream was not flushed. And RC stream will cross block boundary. } Note: some possible implementation of BCJ2 encoder could write branch marker (e8/e8/0f8x) in one call of Bcj2Enc_Encode(), and it could calculate symbol for RC in another call of Bcj2Enc_Encode(). BCJ2 encoder uses ip/fileIp/fileSize/relatLimit values to calculate RC symbol. And these CBcj2Enc variables can have different values in different Bcj2Enc_Encode() calls. So caller must finish each block with BCJ2_ENC_FINISH_MODE_END_BLOCK to ensure that RC symbol is calculated and written in proper block. BCJ2_ENC_FINISH_MODE_END_STREAM finish encoding of stream (ended at srcLim) fully including RC flushing. at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_FINISHED) : it shows that stream encoding was finished fully, and all output streams were flushed fully. also Bcj2Enc_IsFinished() can be called. */ /* 32-bit relative offset in JUMP/CALL commands is - (mod 4 GiB) for 32-bit x86 code - signed Int32 for 64-bit x86-64 code BCJ2 encoder also does internal relative to absolute address conversions. And there are 2 possible ways to do it: before v23: we used 32-bit variables and (mod 4 GiB) conversion since v23: we use 64-bit variables and (signed Int32 offset) conversion. The absolute address condition for conversion in v23: ((UInt64)((Int64)ip64 - (Int64)fileIp64 + 5 + (Int32)offset) < (UInt64)fileSize64) note that if (fileSize64 > 2 GiB). there is difference between old (mod 4 GiB) way (v22) and new (signed Int32 offset) way (v23). And new (v23) way is more suitable to encode 64-bit x86-64 code for (fileSize64 > 2 GiB) cases. */ /* // for old (v22) way for conversion: typedef UInt32 CBcj2Enc_ip_unsigned; typedef Int32 CBcj2Enc_ip_signed; #define BCJ2_ENC_FileSize_MAX ((UInt32)1 << 31) */ typedef UInt64 CBcj2Enc_ip_unsigned; typedef Int64 CBcj2Enc_ip_signed; /* maximum size of file that can be used for conversion condition */ #define BCJ2_ENC_FileSize_MAX ((CBcj2Enc_ip_unsigned)0 - 2) /* default value of fileSize64_minus1 variable that means that absolute address limitation will not be used */ #define BCJ2_ENC_FileSizeField_UNLIMITED ((CBcj2Enc_ip_unsigned)0 - 1) /* calculate value that later can be set to CBcj2Enc::fileSize64_minus1 */ #define BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize) \ ((CBcj2Enc_ip_unsigned)(fileSize) - 1) /* set CBcj2Enc::fileSize64_minus1 variable from size of file */ #define Bcj2Enc_SET_FileSize(p, fileSize) \ (p)->fileSize64_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize); typedef struct { Byte *bufs[BCJ2_NUM_STREAMS]; const Byte *lims[BCJ2_NUM_STREAMS]; const Byte *src; const Byte *srcLim; unsigned state; EBcj2Enc_FinishMode finishMode; Byte context; Byte flushRem; Byte isFlushState; Byte cache; UInt32 range; UInt64 low; UInt64 cacheSize; // UInt32 context; // for marker version, it can include marker flag. /* (ip64) and (fileIp64) correspond to virtual source stream position that doesn't include data in temp[] */ CBcj2Enc_ip_unsigned ip64; /* current (ip) position */ CBcj2Enc_ip_unsigned fileIp64; /* start (ip) position of current file */ CBcj2Enc_ip_unsigned fileSize64_minus1; /* size of current file (for conversion limitation) */ UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)) : 0 means disable_conversion */ // UInt32 relatExcludeBits; UInt32 tempTarget; unsigned tempPos; /* the number of bytes that were copied to temp[] buffer (tempPos <= 4) outside of Bcj2Enc_Encode() */ // Byte temp[4]; // for marker version Byte temp[8]; CBcj2Prob probs[2 + 256]; } CBcj2Enc; void Bcj2Enc_Init(CBcj2Enc *p); /* Bcj2Enc_Encode(): at exit: p->State < BCJ2_NUM_STREAMS : we need more buffer space for output stream (bufs[p->State] == lims[p->State]) p->State == BCJ2_ENC_STATE_ORIG : we need more data in input src stream (src == srcLim) p->State == BCJ2_ENC_STATE_FINISHED : after fully encoded stream */ void Bcj2Enc_Encode(CBcj2Enc *p); /* Bcj2Enc encoder can look ahead for up 4 bytes of source stream. CBcj2Enc::tempPos : is the number of bytes that were copied from input stream to temp[] buffer. (CBcj2Enc::src) after Bcj2Enc_Encode() is starting position after fully processed data and after data copied to temp buffer. So if the caller needs to get real number of fully processed input bytes (without look ahead data in temp buffer), the caller must subtruct (CBcj2Enc::tempPos) value from processed size value that is calculated based on current (CBcj2Enc::src): cur_processed_pos = Calc_Big_Processed_Pos(enc.src)) - Bcj2Enc_Get_AvailInputSize_in_Temp(&enc); */ /* get the size of input data that was stored in temp[] buffer: */ #define Bcj2Enc_Get_AvailInputSize_in_Temp(p) ((p)->tempPos) #define Bcj2Enc_IsFinished(p) ((p)->flushRem == 0) /* Note : the decoder supports overlapping of marker (0f 80). But we can eliminate such overlapping cases by setting the limit for relative offset conversion as CBcj2Enc::relatLimit <= (0x0f << 24) == (240 MiB) */ /* default value for CBcj2Enc::relatLimit */ #define BCJ2_ENC_RELAT_LIMIT_DEFAULT ((UInt32)0x0f << 24) #define BCJ2_ENC_RELAT_LIMIT_MAX ((UInt32)1 << 31) // #define BCJ2_RELAT_EXCLUDE_NUM_BITS 5 EXTERN_C_END #endif tmp41wklro_/C/Bcj2Enc.c0000444000175000001440000004157614412260060015705 0ustar nabijaczleweliusers/* Bcj2Enc.c -- BCJ2 Encoder converter for x86 code (Branch CALL/JUMP variant2) 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" /* #define SHOW_STAT */ #ifdef SHOW_STAT #include #define PRF2(s) printf("%s ip=%8x tempPos=%d src= %8x\n", s, (unsigned)p->ip64, p->tempPos, (unsigned)(p->srcLim - p->src)); #else #define PRF2(s) #endif #include "Bcj2.h" #include "CpuArch.h" #define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 void Bcj2Enc_Init(CBcj2Enc *p) { unsigned i; p->state = BCJ2_ENC_STATE_ORIG; p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; p->context = 0; p->flushRem = 5; p->isFlushState = 0; p->cache = 0; p->range = 0xffffffff; p->low = 0; p->cacheSize = 1; p->ip64 = 0; p->fileIp64 = 0; p->fileSize64_minus1 = BCJ2_ENC_FileSizeField_UNLIMITED; p->relatLimit = BCJ2_ENC_RELAT_LIMIT_DEFAULT; // p->relatExcludeBits = 0; p->tempPos = 0; for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) p->probs[i] = kBitModelTotal >> 1; } // Z7_NO_INLINE Z7_FORCE_INLINE static BoolInt Bcj2_RangeEnc_ShiftLow(CBcj2Enc *p) { const UInt32 low = (UInt32)p->low; const unsigned high = (unsigned) #if defined(Z7_MSC_VER_ORIGINAL) \ && defined(MY_CPU_X86) \ && defined(MY_CPU_LE) \ && !defined(MY_CPU_64BIT) // we try to rid of __aullshr() call in MSVS-x86 (((const UInt32 *)&p->low)[1]); // [1] : for little-endian only #else (p->low >> 32); #endif if (low < (UInt32)0xff000000 || high != 0) { Byte *buf = p->bufs[BCJ2_STREAM_RC]; do { if (buf == p->lims[BCJ2_STREAM_RC]) { p->state = BCJ2_STREAM_RC; p->bufs[BCJ2_STREAM_RC] = buf; return True; } *buf++ = (Byte)(p->cache + high); p->cache = 0xff; } while (--p->cacheSize); p->bufs[BCJ2_STREAM_RC] = buf; p->cache = (Byte)(low >> 24); } p->cacheSize++; p->low = low << 8; return False; } /* We can use 2 alternative versions of code: 1) non-marker version: Byte CBcj2Enc::context Byte temp[8]; Last byte of marker (e8/e9/[0f]8x) can be written to temp[] buffer. Encoder writes last byte of marker (e8/e9/[0f]8x) to dest, only in conjunction with writing branch symbol to range coder in same Bcj2Enc_Encode_2() call. 2) marker version: UInt32 CBcj2Enc::context Byte CBcj2Enc::temp[4]; MARKER_FLAG in CBcj2Enc::context shows that CBcj2Enc::context contains finded marker. it's allowed that one call of Bcj2Enc_Encode_2() writes last byte of marker (e8/e9/[0f]8x) to dest, and another call of Bcj2Enc_Encode_2() does offset conversion. So different values of (fileIp) and (fileSize) are possible in these different Bcj2Enc_Encode_2() calls. Also marker version requires additional if((v & MARKER_FLAG) == 0) check in main loop. So we use non-marker version. */ /* Corner cases with overlap in multi-block. before v23: there was one corner case, where converted instruction could start in one sub-stream and finish in next sub-stream. If multi-block (solid) encoding is used, and BCJ2_ENC_FINISH_MODE_END_BLOCK is used for each sub-stream. and (0f) is last byte of previous sub-stream and (8x) is first byte of current sub-stream then (0f 8x) pair is treated as marker by BCJ2 encoder and decoder. BCJ2 encoder can converts 32-bit offset for that (0f 8x) cortage, if that offset meets limit requirements. If encoder allows 32-bit offset conversion for such overlap case, then the data in 3 uncompressed BCJ2 streams for some sub-stream can depend from data of previous sub-stream. That corner case is not big problem, and it's rare case. Since v23.00 we do additional check to prevent conversions in such overlap cases. */ /* Bcj2Enc_Encode_2() output variables at exit: { if (Bcj2Enc_Encode_2() exits with (p->state == BCJ2_ENC_STATE_ORIG)) { it means that encoder needs more input data. if (p->srcLim == p->src) at exit, then { (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) all input data were read and processed, and we are ready for new input data. } else { (p->srcLim != p->src) (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) The encoder have found e8/e9/0f_8x marker, and p->src points to last byte of that marker, Bcj2Enc_Encode_2() needs more input data to get totally 5 bytes (last byte of marker and 32-bit branch offset) as continuous array starting from p->src. (p->srcLim - p->src < 5) requirement is met after exit. So non-processed resedue from p->src to p->srcLim is always less than 5 bytes. } } } */ Z7_NO_INLINE static void Bcj2Enc_Encode_2(CBcj2Enc *p) { if (!p->isFlushState) { const Byte *src; UInt32 v; { const unsigned state = p->state; if (BCJ2_IS_32BIT_STREAM(state)) { Byte *cur = p->bufs[state]; if (cur == p->lims[state]) return; SetBe32a(cur, p->tempTarget) p->bufs[state] = cur + 4; } } p->state = BCJ2_ENC_STATE_ORIG; // for main reason of exit src = p->src; v = p->context; // #define WRITE_CONTEXT p->context = v; // for marker version #define WRITE_CONTEXT p->context = (Byte)v; #define WRITE_CONTEXT_AND_SRC p->src = src; WRITE_CONTEXT for (;;) { // const Byte *src; // UInt32 v; CBcj2Enc_ip_unsigned ip; if (p->range < kTopValue) { // to reduce register pressure and code size: we save and restore local variables. WRITE_CONTEXT_AND_SRC if (Bcj2_RangeEnc_ShiftLow(p)) return; p->range <<= 8; src = p->src; v = p->context; } // src = p->src; // #define MARKER_FLAG ((UInt32)1 << 17) // if ((v & MARKER_FLAG) == 0) // for marker version { const Byte *srcLim; Byte *dest = p->bufs[BCJ2_STREAM_MAIN]; { const SizeT remSrc = (SizeT)(p->srcLim - src); SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest); if (rem >= remSrc) rem = remSrc; srcLim = src + rem; } /* p->context contains context of previous byte: bits [0 : 7] : src[-1], if (src) was changed in this call bits [8 : 31] : are undefined for non-marker version */ // v = p->context; #define NUM_SHIFT_BITS 24 #define CONV_FLAG ((UInt32)1 << 16) #define ONE_ITER { \ b = src[0]; \ *dest++ = (Byte)b; \ v = (v << NUM_SHIFT_BITS) | b; \ if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \ if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \ ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \ src++; if (src == srcLim) { break; } } if (src != srcLim) for (;;) { /* clang can generate ineffective code with setne instead of two jcc instructions. we can use 2 iterations and external (unsigned b) to avoid that ineffective code genaration. */ unsigned b; ONE_ITER ONE_ITER } ip = p->ip64 + (CBcj2Enc_ip_unsigned)(SizeT)(dest - p->bufs[BCJ2_STREAM_MAIN]); p->bufs[BCJ2_STREAM_MAIN] = dest; p->ip64 = ip; if (src == srcLim) { WRITE_CONTEXT_AND_SRC if (src != p->srcLim) { p->state = BCJ2_STREAM_MAIN; return; } /* (p->src == p->srcLim) (p->state == BCJ2_ENC_STATE_ORIG) */ if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) return; /* (p->finishMode == BCJ2_ENC_FINISH_MODE_END_STREAM */ // (p->flushRem == 5); p->isFlushState = 1; break; } src++; // p->src = src; } // ip = p->ip; // for marker version /* marker was found */ /* (v) contains marker that was found: bits [NUM_SHIFT_BITS : NUM_SHIFT_BITS + 7] : value of src[-2] : xx/xx/0f bits [0 : 7] : value of src[-1] : e8/e9/8x */ { { #if NUM_SHIFT_BITS != 24 v &= ~(UInt32)CONV_FLAG; #endif // UInt32 relat = 0; if ((SizeT)(p->srcLim - src) >= 4) { /* if (relat != 0 || (Byte)v != 0xe8) BoolInt isBigOffset = True; */ const UInt32 relat = GetUi32(src); /* #define EXCLUDE_FLAG ((UInt32)1 << 4) #define NEED_CONVERT(rel) ((((rel) + EXCLUDE_FLAG) & (0 - EXCLUDE_FLAG * 2)) != 0) if (p->relatExcludeBits != 0) { const UInt32 flag = (UInt32)1 << (p->relatExcludeBits - 1); isBigOffset = (((relat + flag) & (0 - flag * 2)) != 0); } // isBigOffset = False; // for debug */ ip -= p->fileIp64; // Use the following if check, if (ip) is 64-bit: if (ip > (((v + 0x20) >> 5) & 1)) // 23.00 : we eliminate milti-block overlap for (Of 80) and (e8/e9) if ((CBcj2Enc_ip_unsigned)((CBcj2Enc_ip_signed)ip + 4 + (Int32)relat) <= p->fileSize64_minus1) if (((UInt32)(relat + p->relatLimit) >> 1) < p->relatLimit) v |= CONV_FLAG; } else if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) { // (p->srcLim - src < 4) // /* // for non-marker version p->ip64--; // p->ip = ip - 1; p->bufs[BCJ2_STREAM_MAIN]--; src--; v >>= NUM_SHIFT_BITS; // (0 < p->srcLim - p->src <= 4) // */ // v |= MARKER_FLAG; // for marker version /* (p->state == BCJ2_ENC_STATE_ORIG) */ WRITE_CONTEXT_AND_SRC return; } { const unsigned c = ((v + 0x17) >> 6) & 1; CBcj2Prob *prob = p->probs + (unsigned) (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1)); /* ((Byte)v == 0xe8 ? 2 + ((Byte)(v >> 8)) : ((Byte)v < 0xe8 ? 0 : 1)); // ((v >> 5) & 1)); */ const unsigned ttt = *prob; const UInt32 bound = (p->range >> kNumBitModelTotalBits) * ttt; if ((v & CONV_FLAG) == 0) { // static int yyy = 0; yyy++; printf("\n!needConvert = %d\n", yyy); // v = (Byte)v; // for marker version p->range = bound; *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); // WRITE_CONTEXT_AND_SRC continue; } p->low += bound; p->range -= bound; *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits)); } // p->context = src[3]; { // const unsigned cj = ((Byte)v == 0xe8 ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP); const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL; ip = p->ip64; v = GetUi32(src); // relat ip += 4; p->ip64 = ip; src += 4; // p->src = src; { const UInt32 absol = (UInt32)ip + v; Byte *cur = p->bufs[cj]; v >>= 24; // WRITE_CONTEXT if (cur == p->lims[cj]) { p->state = cj; p->tempTarget = absol; WRITE_CONTEXT_AND_SRC return; } SetBe32a(cur, absol) p->bufs[cj] = cur + 4; } } } } } // end of loop } for (; p->flushRem != 0; p->flushRem--) if (Bcj2_RangeEnc_ShiftLow(p)) return; p->state = BCJ2_ENC_STATE_FINISHED; } /* BCJ2 encoder needs look ahead for up to 4 bytes in (src) buffer. So base function Bcj2Enc_Encode_2() in BCJ2_ENC_FINISH_MODE_CONTINUE mode can return with (p->state == BCJ2_ENC_STATE_ORIG && p->src < p->srcLim) Bcj2Enc_Encode() solves that look ahead problem by using p->temp[] buffer. so if (p->state == BCJ2_ENC_STATE_ORIG) after Bcj2Enc_Encode(), then (p->src == p->srcLim). And the caller's code is simpler with Bcj2Enc_Encode(). */ Z7_NO_INLINE void Bcj2Enc_Encode(CBcj2Enc *p) { PRF2("\n----") if (p->tempPos != 0) { /* extra: number of bytes that were copied from (src) to (temp) buffer in this call */ unsigned extra = 0; /* We will touch only minimal required number of bytes in input (src) stream. So we will add input bytes from (src) stream to temp[] with step of 1 byte. We don't add new bytes to temp[] before Bcj2Enc_Encode_2() call in first loop iteration because - previous call of Bcj2Enc_Encode() could use another (finishMode), - previous call could finish with (p->state != BCJ2_ENC_STATE_ORIG). the case with full temp[] buffer (p->tempPos == 4) is possible here. */ for (;;) { // (0 < p->tempPos <= 5) // in non-marker version /* p->src : the current src data position including extra bytes that were copied to temp[] buffer in this call */ const Byte *src = p->src; const Byte *srcLim = p->srcLim; const EBcj2Enc_FinishMode finishMode = p->finishMode; if (src != srcLim) { /* if there are some src data after the data copied to temp[], then we use MODE_CONTINUE for temp data */ p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; } p->src = p->temp; p->srcLim = p->temp + p->tempPos; PRF2(" ") Bcj2Enc_Encode_2(p); { const unsigned num = (unsigned)(p->src - p->temp); const unsigned tempPos = p->tempPos - num; unsigned i; p->tempPos = tempPos; for (i = 0; i < tempPos; i++) p->temp[i] = p->temp[(SizeT)i + num]; // tempPos : number of bytes in temp buffer p->src = src; p->srcLim = srcLim; p->finishMode = finishMode; if (p->state != BCJ2_ENC_STATE_ORIG) { // (p->tempPos <= 4) // in non-marker version /* if (the reason of exit from Bcj2Enc_Encode_2() is not BCJ2_ENC_STATE_ORIG), then we exit from Bcj2Enc_Encode() with same reason */ // optional code begin : we rollback (src) and tempPos, if it's possible: if (extra >= tempPos) extra = tempPos; p->src = src - extra; p->tempPos = tempPos - extra; // optional code end : rollback of (src) and tempPos return; } /* (p->tempPos <= 4) (p->state == BCJ2_ENC_STATE_ORIG) so encoder needs more data than in temp[] */ if (src == srcLim) return; // src buffer has no more input data. /* (src != srcLim) so we can provide more input data from src for Bcj2Enc_Encode_2() */ if (extra >= tempPos) { /* (extra >= tempPos) means that temp buffer contains only data from src buffer of this call. So now we can encode without temp buffer */ p->src = src - tempPos; // rollback (src) p->tempPos = 0; break; } // we append one additional extra byte from (src) to temp[] buffer: p->temp[tempPos] = *src; p->tempPos = tempPos + 1; // (0 < p->tempPos <= 5) // in non-marker version p->src = src + 1; extra++; } } } PRF2("++++") // (p->tempPos == 0) Bcj2Enc_Encode_2(p); PRF2("====") if (p->state == BCJ2_ENC_STATE_ORIG) { const Byte *src = p->src; const Byte *srcLim = p->srcLim; const unsigned rem = (unsigned)(srcLim - src); /* (rem <= 4) here. if (p->src != p->srcLim), then - we copy non-processed bytes from (p->src) to temp[] buffer, - we set p->src equal to p->srcLim. */ if (rem) { unsigned i = 0; p->src = srcLim; p->tempPos = rem; // (0 < p->tempPos <= 4) do p->temp[i] = src[i]; while (++i != rem); } // (p->tempPos <= 4) // (p->src == p->srcLim) } } #undef PRF2 #undef CONV_FLAG #undef MARKER_FLAG #undef WRITE_CONTEXT #undef WRITE_CONTEXT_AND_SRC #undef ONE_ITER #undef NUM_SHIFT_BITS #undef kTopValue #undef kNumBitModelTotalBits #undef kBitModelTotal #undef kNumMoveBits tmp41wklro_/C/Bra.c0000444000175000001440000004522014553005040015172 0ustar nabijaczleweliusers/* Bra.c -- Branch converters for RISC code 2024-01-20 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bra.h" #include "RotateDefs.h" #include "CpuArch.h" #if defined(MY_CPU_SIZEOF_POINTER) \ && ( MY_CPU_SIZEOF_POINTER == 4 \ || MY_CPU_SIZEOF_POINTER == 8) #define BR_CONV_USE_OPT_PC_PTR #endif #ifdef BR_CONV_USE_OPT_PC_PTR #define BR_PC_INIT pc -= (UInt32)(SizeT)p; #define BR_PC_GET (pc + (UInt32)(SizeT)p) #else #define BR_PC_INIT pc += (UInt32)size; #define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p)) // #define BR_PC_INIT // #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data)) #endif #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; #define Z7_BRANCH_CONV(name) z7_ ## name #define Z7_BRANCH_FUNC_MAIN(name) \ static \ Z7_FORCE_INLINE \ Z7_ATTRIB_NO_VECTOR \ Byte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding) #define Z7_BRANCH_FUNC_IMP(name, m, encoding) \ Z7_NO_INLINE \ Z7_ATTRIB_NO_VECTOR \ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \ { return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \ #ifdef Z7_EXTRACT_ONLY #define Z7_BRANCH_FUNCS_IMP(name) \ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) #else #define Z7_BRANCH_FUNCS_IMP(name) \ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1) #endif #if defined(__clang__) #define BR_EXTERNAL_FOR #define BR_NEXT_ITERATION continue; #else #define BR_EXTERNAL_FOR for (;;) #define BR_NEXT_ITERATION break; #endif #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 1000) \ // GCC is not good for __builtin_expect() here /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */ // #define Z7_unlikely [[unlikely]] // #define Z7_LIKELY(x) (__builtin_expect((x), 1)) #define Z7_UNLIKELY(x) (__builtin_expect((x), 0)) // #define Z7_likely [[likely]] #else // #define Z7_LIKELY(x) (x) #define Z7_UNLIKELY(x) (x) // #define Z7_likely #endif Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64) { // Byte *p = data; const Byte *lim; const UInt32 flag = (UInt32)1 << (24 - 4); const UInt32 mask = ((UInt32)1 << 24) - (flag << 1); size &= ~(SizeT)3; // if (size == 0) return p; lim = p + size; BR_PC_INIT pc -= 4; // because (p) will point to next instruction BR_EXTERNAL_FOR { // Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (;;) { UInt32 v; if Z7_UNLIKELY(p == lim) return p; v = GetUi32a(p); p += 4; if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0) { UInt32 c = BR_PC_GET >> 2; BR_CONVERT_VAL(v, c) v &= 0x03ffffff; v |= 0x94000000; SetUi32a(p - 4, v) BR_NEXT_ITERATION } // v = rotlFixed(v, 8); v += (flag << 8) - 0x90; if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0) v -= 0x90000000; if Z7_UNLIKELY((v & 0x9f000000) == 0) { UInt32 z, c; // v = rotrFixed(v, 8); v += flag; if Z7_UNLIKELY(v & mask) continue; z = (v & 0xffffffe0) | (v >> 26); c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7; BR_CONVERT_VAL(z, c) v &= 0x1f; v |= 0x90000000; v |= z << 26; v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag); SetUi32a(p - 4, v) } } } } Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64) Z7_BRANCH_FUNC_MAIN(BranchConv_ARM) { // Byte *p = data; const Byte *lim; size &= ~(SizeT)3; lim = p + size; BR_PC_INIT /* in ARM: branch offset is relative to the +2 instructions from current instruction. (p) will point to next instruction */ pc += 8 - 4; for (;;) { for (;;) { if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break; if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break; } { UInt32 v = GetUi32a(p - 4); UInt32 c = BR_PC_GET >> 2; BR_CONVERT_VAL(v, c) v &= 0x00ffffff; v |= 0xeb000000; SetUi32a(p - 4, v) } } } Z7_BRANCH_FUNCS_IMP(BranchConv_ARM) Z7_BRANCH_FUNC_MAIN(BranchConv_PPC) { // Byte *p = data; const Byte *lim; size &= ~(SizeT)3; lim = p + size; BR_PC_INIT pc -= 4; // because (p) will point to next instruction for (;;) { UInt32 v; for (;;) { if Z7_UNLIKELY(p == lim) return p; // v = GetBe32a(p); v = *(UInt32 *)(void *)p; p += 4; // if ((v & 0xfc000003) == 0x48000001) break; // if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break; if Z7_UNLIKELY( ((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001)) & Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break; } { v = Z7_CONV_NATIVE_TO_BE_32(v); { UInt32 c = BR_PC_GET; BR_CONVERT_VAL(v, c) } v &= 0x03ffffff; v |= 0x48000000; SetBe32a(p - 4, v) } } } Z7_BRANCH_FUNCS_IMP(BranchConv_PPC) #ifdef Z7_CPU_FAST_ROTATE_SUPPORTED #define BR_SPARC_USE_ROTATE #endif Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC) { // Byte *p = data; const Byte *lim; const UInt32 flag = (UInt32)1 << 22; size &= ~(SizeT)3; lim = p + size; BR_PC_INIT pc -= 4; // because (p) will point to next instruction for (;;) { UInt32 v; for (;;) { if Z7_UNLIKELY(p == lim) return p; /* // the code without GetBe32a(): { const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; } */ v = GetBe32a(p); p += 4; #ifdef BR_SPARC_USE_ROTATE v = rotlFixed(v, 2); v += (flag << 2) - 1; if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0) #else v += (UInt32)5 << 29; v ^= (UInt32)7 << 29; v += flag; if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0) #endif break; } { // UInt32 v = GetBe32a(p - 4); #ifndef BR_SPARC_USE_ROTATE v <<= 2; #endif { UInt32 c = BR_PC_GET; BR_CONVERT_VAL(v, c) } v &= (flag << 3) - 1; #ifdef BR_SPARC_USE_ROTATE v -= (flag << 2) - 1; v = rotrFixed(v, 2); #else v -= (flag << 2); v >>= 2; v |= (UInt32)1 << 30; #endif SetBe32a(p - 4, v) } } } Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC) Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT) { // Byte *p = data; Byte *lim; size &= ~(SizeT)1; // if (size == 0) return p; if (size <= 2) return p; size -= 2; lim = p + size; BR_PC_INIT /* in ARM: branch offset is relative to the +2 instructions from current instruction. (p) will point to the +2 instructions from current instruction */ // pc += 4 - 4; // if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1; // #define ARMT_TAIL_PROC { goto armt_tail; } #define ARMT_TAIL_PROC { return p; } do { /* in MSVC 32-bit x86 compilers: UInt32 version : it loads value from memory with movzx Byte version : it loads value to 8-bit register (AL/CL) movzx version is slightly faster in some cpus */ unsigned b1; // Byte / unsigned b1 = p[1]; // optimized version to reduce one (p >= lim) check: // unsigned a1 = p[1]; b1 = p[3]; p += 2; if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8) for (;;) { unsigned b3; // Byte / UInt32 /* (Byte)(b3) normalization can use low byte computations in MSVC. It gives smaller code, and no loss of speed in some compilers/cpus. But new MSVC 32-bit x86 compilers use more slow load from memory to low byte register in that case. So we try to use full 32-bit computations for faster code. */ // if (p >= lim) { ARMT_TAIL_PROC } b3 = b1 + 8; b1 = p[3]; p += 2; if ((b3 & b1) >= 0xf8) break; if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b3 = p[3]; p += 2; if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break; if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b1 = p[3]; p += 2; if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break; } { /* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation. But gcc/clang for arm64 can use bfi instruction for full code here */ UInt32 v = ((UInt32)GetUi16a(p - 2) << 11) | ((UInt32)GetUi16a(p) & 0x7FF); /* UInt32 v = ((UInt32)p[1 - 2] << 19) + (((UInt32)p[1] & 0x7) << 8) + (((UInt32)p[-2] << 11)) + (p[0]); */ p += 2; { UInt32 c = BR_PC_GET >> 1; BR_CONVERT_VAL(v, c) } SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000)) SetUi16a(p - 2, (UInt16)(v | 0xf800)) /* p[-4] = (Byte)(v >> 11); p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7)); p[-2] = (Byte)v; p[-1] = (Byte)(0xf8 | (v >> 8)); */ } } while (p < lim); return p; // armt_tail: // if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; } return lim; // return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2)); // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2)); // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2)); } Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT) // #define BR_IA64_NO_INLINE Z7_BRANCH_FUNC_MAIN(BranchConv_IA64) { // Byte *p = data; const Byte *lim; size &= ~(SizeT)15; lim = p + size; pc -= 1 << 4; pc >>= 4 - 1; // pc -= 1 << 1; for (;;) { unsigned m; for (;;) { if Z7_UNLIKELY(p == lim) return p; m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e)); p += 16; pc += 1 << 1; if (m &= 3) break; } { p += (ptrdiff_t)m * 5 - 20; // negative value is expected here. do { const UInt32 t = #if defined(MY_CPU_X86_OR_AMD64) // we use 32-bit load here to reduce code size on x86: GetUi32(p); #else GetUi16(p); #endif UInt32 z = GetUi32(p + 1) >> m; p += 5; if (((t >> m) & (0x70 << 1)) == 0 && ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0) { UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z; z ^= v; #ifdef BR_IA64_NO_INLINE v |= (v & ((UInt32)1 << (23 + 1))) >> 3; { UInt32 c = pc; BR_CONVERT_VAL(v, c) } v &= (0x1fffff << 1) | 1; #else { if (encoding) { // pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits pc &= (0x1fffff << 1) | 1; v += pc; } else { // pc |= 0xc00000 << 1; // we need to set at least 2 bits pc |= ~(UInt32)((0x1fffff << 1) | 1); v -= pc; } } v &= ~(UInt32)(0x600000 << 1); #endif v += (0x700000 << 1); v &= (0x8fffff << 1) | 1; z |= v; z <<= m; SetUi32(p + 1 - 5, z) } m++; } while (m &= 3); // while (m < 4); } } } Z7_BRANCH_FUNCS_IMP(BranchConv_IA64) #define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET; #define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET; #if 1 && defined(MY_CPU_LE_UNALIGN) #define RISCV_USE_UNALIGNED_LOAD #endif #ifdef RISCV_USE_UNALIGNED_LOAD #define RISCV_GET_UI32(p) GetUi32(p) #define RISCV_SET_UI32(p, v) { SetUi32(p, v) } #else #define RISCV_GET_UI32(p) \ ((UInt32)GetUi16a(p) + \ ((UInt32)GetUi16a((p) + 2) << 16)) #define RISCV_SET_UI32(p, v) { \ SetUi16a(p, (UInt16)(v)) \ SetUi16a((p) + 2, (UInt16)(v >> 16)) } #endif #if 1 && defined(MY_CPU_LE) #define RISCV_USE_16BIT_LOAD #endif #ifdef RISCV_USE_16BIT_LOAD #define RISCV_LOAD_VAL(p) GetUi16a(p) #else #define RISCV_LOAD_VAL(p) (*(p)) #endif #define RISCV_INSTR_SIZE 2 #define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE) #define RISCV_STEP_2 4 #define RISCV_REG_VAL (2 << 7) #define RISCV_CMD_VAL 3 #if 1 // for code size optimization: #define RISCV_DELTA_7F 0x7f #else #define RISCV_DELTA_7F 0 #endif #define RISCV_CHECK_1(v, b) \ (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0) #if 1 #define RISCV_CHECK_2(v, r) \ ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \ << 18) \ < ((r) & 0x1d)) #else // this branch gives larger code, because // compilers generate larger code for big constants. #define RISCV_CHECK_2(v, r) \ ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \ & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \ < ((r) & 0x1d)) #endif #define RISCV_SCAN_LOOP \ Byte *lim; \ size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \ if (size <= 6) return p; \ size -= 6; \ lim = p + size; \ BR_PC_INIT \ for (;;) \ { \ UInt32 a, v; \ /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \ for (;;) \ { \ if Z7_UNLIKELY(p >= lim) { return p; } \ a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \ if ((a & 0x77) == 0) break; \ a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \ p += RISCV_INSTR_SIZE * 2; \ if ((a & 0x77) == 0) \ { \ p -= RISCV_INSTR_SIZE; \ if Z7_UNLIKELY(p >= lim) { return p; } \ break; \ } \ } // (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL // (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL // (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC // (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc) { RISCV_SCAN_LOOP v = a; a = RISCV_GET_UI32(p); #ifndef RISCV_USE_16BIT_LOAD v += (UInt32)p[1] << 8; #endif if ((v & 8) == 0) // JAL { if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80) { p += RISCV_INSTR_SIZE; continue; } { v = ((a & 1u << 31) >> 11) | ((a & 0x3ff << 21) >> 20) | ((a & 1 << 20) >> 9) | (a & 0xff << 12); BR_CONVERT_VAL_ENC(v) // ((v & 1) == 0) // v: bits [1 : 20] contain offset bits #if 0 && defined(RISCV_USE_UNALIGNED_LOAD) a &= 0xfff; a |= ((UInt32)(v << 23)) | ((UInt32)(v << 7) & ((UInt32)0xff << 16)) | ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8)); RISCV_SET_UI32(p, a) #else // aligned #if 0 SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff))) #else p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf)); #endif #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE) v <<= 15; v = Z7_BSWAP32(v); SetUi16a(p + 2, (UInt16)v) #else p[2] = (Byte)(v >> 9); p[3] = (Byte)(v >> 1); #endif #endif // aligned } p += 4; continue; } // JAL { // AUIPC if (v & 0xe80) // (not x0) and (not x2) { const UInt32 b = RISCV_GET_UI32(p + 4); if (RISCV_CHECK_1(v, b)) { { const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL); RISCV_SET_UI32(p, temp) } a &= 0xfffff000; { #if 1 const int t = -1 >> 1; if (t != -1) a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation else #endif a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension). } BR_CONVERT_VAL_ENC(a) #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE) a = Z7_BSWAP32(a); RISCV_SET_UI32(p + 4, a) #else SetBe32(p + 4, a) #endif p += 8; } else p += RISCV_STEP_1; } else { UInt32 r = a >> 27; if (RISCV_CHECK_2(v, r)) { v = RISCV_GET_UI32(p + 4); r = (r << 7) + 0x17 + (v & 0xfffff000); a = (a >> 12) | (v << 20); RISCV_SET_UI32(p, r) RISCV_SET_UI32(p + 4, a) p += 8; } else p += RISCV_STEP_2; } } } // for } Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc) { RISCV_SCAN_LOOP #ifdef RISCV_USE_16BIT_LOAD if ((a & 8) == 0) { #else v = a; a += (UInt32)p[1] << 8; if ((v & 8) == 0) { #endif // JAL a -= 0x100 - RISCV_DELTA_7F; if (a & 0xd80) { p += RISCV_INSTR_SIZE; continue; } { const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff; #if 0 // unaligned a = GetUi32(p); v = (UInt32)(a >> 23) & ((UInt32)0xff << 1) | (UInt32)(a >> 7) & ((UInt32)0xff << 9) #elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE) v = GetUi16a(p + 2); v = Z7_BSWAP32(v) >> 15 #else v = (UInt32)p[3] << 1 | (UInt32)p[2] << 9 #endif | (UInt32)((a & 0xf000) << 5); BR_CONVERT_VAL_DEC(v) a = a_old | (v << 11 & 1u << 31) | (v << 20 & 0x3ff << 21) | (v << 9 & 1 << 20) | (v & 0xff << 12); RISCV_SET_UI32(p, a) } p += 4; continue; } // JAL { // AUIPC v = a; #if 1 && defined(RISCV_USE_UNALIGNED_LOAD) a = GetUi32(p); #else a |= (UInt32)GetUi16a(p + 2) << 16; #endif if ((v & 0xe80) == 0) // x0/x2 { const UInt32 r = a >> 27; if (RISCV_CHECK_2(v, r)) { UInt32 b; #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE) b = RISCV_GET_UI32(p + 4); b = Z7_BSWAP32(b); #else b = GetBe32(p + 4); #endif v = a >> 12; BR_CONVERT_VAL_DEC(b) a = (r << 7) + 0x17; a += (b + 0x800) & 0xfffff000; v |= b << 20; RISCV_SET_UI32(p, a) RISCV_SET_UI32(p + 4, v) p += 8; } else p += RISCV_STEP_2; } else { const UInt32 b = RISCV_GET_UI32(p + 4); if (!RISCV_CHECK_1(v, b)) p += RISCV_STEP_1; else { v = (a & 0xfffff000) | (b >> 20); a = (b << 12) | (0x17 + RISCV_REG_VAL); RISCV_SET_UI32(p, a) RISCV_SET_UI32(p + 4, v) p += 8; } } } } // for } tmp41wklro_/C/Bra.h0000444000175000001440000000731314552776020015214 0ustar nabijaczleweliusers/* Bra.h -- Branch converters for executables 2024-01-20 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_BRA_H #define ZIP7_INC_BRA_H #include "7zTypes.h" EXTERN_C_BEGIN /* #define PPC BAD_PPC_11 // for debug */ #define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec #define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc #define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name) #define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name) #define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec #define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc #define Z7_BRANCH_CONV_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc) #define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state) typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv)); typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); #define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86)); Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86)); #define Z7_BRANCH_FUNCS_DECL(name) \ Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \ Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name)); Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64) Z7_BRANCH_FUNCS_DECL (BranchConv_ARM) Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT) Z7_BRANCH_FUNCS_DECL (BranchConv_PPC) Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC) Z7_BRANCH_FUNCS_DECL (BranchConv_IA64) Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV) /* These functions convert data that contain CPU instructions. Each such function converts relative addresses to absolute addresses in some branch instructions: CALL (in all converters) and JUMP (X86 converter only). Such conversion allows to increase compression ratio, if we compress that data. There are 2 types of converters: Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc); Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state); Each Converter supports 2 versions: one for encoding and one for decoding (_Enc/_Dec postfixes in function name). In params: data : data buffer size : size of data pc : current virtual Program Counter (Instruction Pointer) value In/Out param: state : pointer to state variable (for X86 converter only) Return: The pointer to position in (data) buffer after last byte that was processed. If the caller calls converter again, it must call it starting with that position. But the caller is allowed to move data in buffer. So pointer to current processed position also will be changed for next call. Also the caller must increase internal (pc) value for next call. Each converter has some characteristics: Endian, Alignment, LookAhead. Type Endian Alignment LookAhead X86 little 1 4 ARMT little 2 2 RISCV little 2 6 ARM little 4 0 ARM64 little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 (data) must be aligned for (Alignment). processed size can be calculated as: SizeT processed = Conv(data, size, pc) - data; if (processed == 0) it means that converter needs more data for processing. If (size < Alignment + LookAhead) then (processed == 0) is allowed. Example code for conversion in loop: UInt32 pc = 0; size = 0; for (;;) { size += Load_more_input_data(data + size); SizeT processed = Conv(data, size, pc) - data; if (processed == 0 && no_more_input_data_after_size) break; // we stop convert loop data += processed; size -= processed; pc += processed; } */ EXTERN_C_END #endif tmp41wklro_/C/Bra86.c0000444000175000001440000001172014412260060015345 0ustar nabijaczleweliusers/* Bra86.c -- Branch converter for X86 code (BCJ) 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Bra.h" #include "CpuArch.h" #if defined(MY_CPU_SIZEOF_POINTER) \ && ( MY_CPU_SIZEOF_POINTER == 4 \ || MY_CPU_SIZEOF_POINTER == 8) #define BR_CONV_USE_OPT_PC_PTR #endif #ifdef BR_CONV_USE_OPT_PC_PTR #define BR_PC_INIT pc -= (UInt32)(SizeT)p; // (MY_uintptr_t) #define BR_PC_GET (pc + (UInt32)(SizeT)p) #else #define BR_PC_INIT pc += (UInt32)size; #define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p)) // #define BR_PC_INIT // #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data)) #endif #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; #define Z7_BRANCH_CONV_ST(name) z7_BranchConvSt_ ## name #define BR86_NEED_CONV_FOR_MS_BYTE(b) ((((b) + 1) & 0xfe) == 0) #ifdef MY_CPU_LE_UNALIGN #define BR86_PREPARE_BCJ_SCAN const UInt32 v = GetUi32(p) ^ 0xe8e8e8e8; #define BR86_IS_BCJ_BYTE(n) ((v & ((UInt32)0xfe << (n) * 8)) == 0) #else #define BR86_PREPARE_BCJ_SCAN // bad for MSVC X86 (partial write to byte reg): #define BR86_IS_BCJ_BYTE(n) ((p[n - 4] & 0xfe) == 0xe8) // bad for old MSVC (partial write to byte reg): // #define BR86_IS_BCJ_BYTE(n) (((*p ^ 0xe8) & 0xfe) == 0) #endif static Z7_FORCE_INLINE Z7_ATTRIB_NO_VECTOR Byte *Z7_BRANCH_CONV_ST(X86)(Byte *p, SizeT size, UInt32 pc, UInt32 *state, int encoding) { if (size < 5) return p; { // Byte *p = data; const Byte *lim = p + size - 4; unsigned mask = (unsigned)*state; // & 7; #ifdef BR_CONV_USE_OPT_PC_PTR /* if BR_CONV_USE_OPT_PC_PTR is defined: we need to adjust (pc) for (+4), because call/jump offset is relative to the next instruction. if BR_CONV_USE_OPT_PC_PTR is not defined : we don't need to adjust (pc) for (+4), because BR_PC_GET uses (pc - (lim - p)), and lim was adjusted for (-4) before. */ pc += 4; #endif BR_PC_INIT goto start; for (;; mask |= 4) { // cont: mask |= 4; start: if (p >= lim) goto fin; { BR86_PREPARE_BCJ_SCAN p += 4; if (BR86_IS_BCJ_BYTE(0)) { goto m0; } mask >>= 1; if (BR86_IS_BCJ_BYTE(1)) { goto m1; } mask >>= 1; if (BR86_IS_BCJ_BYTE(2)) { goto m2; } mask = 0; if (BR86_IS_BCJ_BYTE(3)) { goto a3; } } goto main_loop; m0: p--; m1: p--; m2: p--; if (mask == 0) goto a3; if (p > lim) goto fin_p; // if (((0x17u >> mask) & 1) == 0) if (mask > 4 || mask == 3) { mask >>= 1; continue; // goto cont; } mask >>= 1; if (BR86_NEED_CONV_FOR_MS_BYTE(p[mask])) continue; // goto cont; // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont; { UInt32 v = GetUi32(p); UInt32 c; v += (1 << 24); if (v & 0xfe000000) continue; // goto cont; c = BR_PC_GET; BR_CONVERT_VAL(v, c) { mask <<= 3; if (BR86_NEED_CONV_FOR_MS_BYTE(v >> mask)) { v ^= (((UInt32)0x100 << mask) - 1); #ifdef MY_CPU_X86 // for X86 : we can recalculate (c) to reduce register pressure c = BR_PC_GET; #endif BR_CONVERT_VAL(v, c) } mask = 0; } // v = (v & ((1 << 24) - 1)) - (v & (1 << 24)); v &= (1 << 25) - 1; v -= (1 << 24); SetUi32(p, v) p += 4; goto main_loop; } main_loop: if (p >= lim) goto fin; for (;;) { BR86_PREPARE_BCJ_SCAN p += 4; if (BR86_IS_BCJ_BYTE(0)) { goto a0; } if (BR86_IS_BCJ_BYTE(1)) { goto a1; } if (BR86_IS_BCJ_BYTE(2)) { goto a2; } if (BR86_IS_BCJ_BYTE(3)) { goto a3; } if (p >= lim) goto fin; } a0: p--; a1: p--; a2: p--; a3: if (p > lim) goto fin_p; // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont; { UInt32 v = GetUi32(p); UInt32 c; v += (1 << 24); if (v & 0xfe000000) continue; // goto cont; c = BR_PC_GET; BR_CONVERT_VAL(v, c) // v = (v & ((1 << 24) - 1)) - (v & (1 << 24)); v &= (1 << 25) - 1; v -= (1 << 24); SetUi32(p, v) p += 4; goto main_loop; } } fin_p: p--; fin: // the following processing for tail is optional and can be commented /* lim += 4; for (; p < lim; p++, mask >>= 1) if ((*p & 0xfe) == 0xe8) break; */ *state = (UInt32)mask; return p; } } #define Z7_BRANCH_CONV_ST_FUNC_IMP(name, m, encoding) \ Z7_NO_INLINE \ Z7_ATTRIB_NO_VECTOR \ Byte *m(name)(Byte *data, SizeT size, UInt32 pc, UInt32 *state) \ { return Z7_BRANCH_CONV_ST(name)(data, size, pc, state, encoding); } Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_DEC, 0) #ifndef Z7_EXTRACT_ONLY Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_ENC, 1) #endif tmp41wklro_/C/BraIA64.c0000444000175000001440000000054414374642240015570 0ustar nabijaczleweliusers/* BraIA64.c -- Converter for IA-64 code 2023-02-20 : Igor Pavlov : Public domain */ #include "Precomp.h" // the code was moved to Bra.c #ifdef _MSC_VER #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty #endif #if defined(__clang__) #pragma GCC diagnostic ignored "-Wempty-translation-unit" #endif tmp41wklro_/C/Compiler.h0000444000175000001440000001660014570366560016265 0ustar nabijaczleweliusers/* Compiler.h : Compiler specific defines and pragmas 2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_COMPILER_H #define ZIP7_INC_COMPILER_H #if defined(__clang__) # define Z7_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #endif #if defined(__clang__) && defined(__apple_build_version__) # define Z7_APPLE_CLANG_VERSION Z7_CLANG_VERSION #elif defined(__clang__) # define Z7_LLVM_CLANG_VERSION Z7_CLANG_VERSION #elif defined(__GNUC__) # define Z7_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #ifdef _MSC_VER #if !defined(__clang__) && !defined(__GNUC__) #define Z7_MSC_VER_ORIGINAL _MSC_VER #endif #endif #if defined(__MINGW32__) || defined(__MINGW64__) #define Z7_MINGW #endif #if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__)) #define Z7_MCST_LCC #define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__) #endif /* #if defined(__AVX2__) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \ || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \ || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \ || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \ || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400) #define Z7_COMPILER_AVX2_SUPPORTED #endif #endif */ // #pragma GCC diagnostic ignored "-Wunknown-pragmas" #ifdef __clang__ // padding size of '' with 4 bytes to alignment boundary #pragma GCC diagnostic ignored "-Wpadded" #if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \ && defined(__FreeBSD__) // freebsd: #pragma GCC diagnostic ignored "-Wexcess-padding" #endif #if __clang_major__ >= 16 #pragma GCC diagnostic ignored "-Wunsafe-buffer-usage" #endif #if __clang_major__ == 13 #if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16) // cheri #pragma GCC diagnostic ignored "-Wcapability-to-integer-cast" #endif #endif #if __clang_major__ == 13 // for #pragma GCC diagnostic ignored "-Wreserved-identifier" #endif #endif // __clang__ #if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16 // #pragma GCC diagnostic ignored "-Wcast-function-type-strict" #define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \ _Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"") #else #define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION #endif typedef void (*Z7_void_Function)(void); #if defined(__clang__) || defined(__GNUC__) #define Z7_CAST_FUNC_C (Z7_void_Function) #elif defined(_MSC_VER) && _MSC_VER > 1920 #define Z7_CAST_FUNC_C (void *) // #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' #else #define Z7_CAST_FUNC_C #endif /* #if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__) // #pragma GCC diagnostic ignored "-Wcast-function-type" #endif */ #ifdef __GNUC__ #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000) #pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif #endif #ifdef _MSC_VER #ifdef UNDER_CE #define RPC_NO_WINDOWS_H /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int #endif #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif // == 1200 : -O1 : for __forceinline // >= 1900 : -O1 : for printf #pragma warning(disable : 4710) // function not inlined #if _MSC_VER < 1900 // winnt.h: 'Int64ShllMod32' #pragma warning(disable : 4514) // unreferenced inline function has been removed #endif #if _MSC_VER < 1300 // #pragma warning(disable : 4702) // unreachable code // Bra.c : -O1: #pragma warning(disable : 4714) // function marked as __forceinline not inlined #endif /* #if _MSC_VER > 1400 && _MSC_VER <= 1900 // strcat: This function or variable may be unsafe // sysinfoapi.h: kit10: GetVersion was declared deprecated #pragma warning(disable : 4996) #endif */ #if _MSC_VER > 1200 // -Wall warnings #pragma warning(disable : 4711) // function selected for automatic inline expansion #pragma warning(disable : 4820) // '2' bytes padding added after data member #if _MSC_VER >= 1400 && _MSC_VER < 1920 // 1400: string.h: _DBG_MEMCPY_INLINE_ // 1600 - 191x : smmintrin.h __cplusplus' // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' #pragma warning(disable : 4668) // 1400 - 1600 : WinDef.h : 'FARPROC' : // 1900 - 191x : immintrin.h: _readfsbase_u32 // no function prototype given : converting '()' to '(void)' #pragma warning(disable : 4255) #endif #if _MSC_VER >= 1914 // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified #pragma warning(disable : 5045) #endif #endif // _MSC_VER > 1200 #endif // _MSC_VER #if defined(__clang__) && (__clang_major__ >= 4) #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \ _Pragma("clang loop unroll(disable)") \ _Pragma("clang loop vectorize(disable)") #define Z7_ATTRIB_NO_VECTORIZE #elif defined(__GNUC__) && (__GNUC__ >= 5) \ && (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610)) #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) // __attribute__((optimize("no-unroll-loops"))); #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE #elif defined(_MSC_VER) && (_MSC_VER >= 1920) #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \ _Pragma("loop( no_vector )") #define Z7_ATTRIB_NO_VECTORIZE #else #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE #define Z7_ATTRIB_NO_VECTORIZE #endif #if defined(MY_CPU_X86_OR_AMD64) && ( \ defined(__clang__) && (__clang_major__ >= 4) \ || defined(__GNUC__) && (__GNUC__ >= 5)) #define Z7_ATTRIB_NO_SSE __attribute__((__target__("no-sse"))) #else #define Z7_ATTRIB_NO_SSE #endif #define Z7_ATTRIB_NO_VECTOR \ Z7_ATTRIB_NO_VECTORIZE \ Z7_ATTRIB_NO_SSE #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 1000) \ /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */ // GCC is not good for __builtin_expect() #define Z7_LIKELY(x) (__builtin_expect((x), 1)) #define Z7_UNLIKELY(x) (__builtin_expect((x), 0)) // #define Z7_unlikely [[unlikely]] // #define Z7_likely [[likely]] #else #define Z7_LIKELY(x) (x) #define Z7_UNLIKELY(x) (x) // #define Z7_likely #endif #if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600)) #if (Z7_CLANG_VERSION < 130000) #define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wreserved-id-macro\"") #else #define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"") #endif #define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \ _Pragma("GCC diagnostic pop") #else #define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #define UNUSED_VAR(x) (void)x; /* #define UNUSED_VAR(x) x=x; */ #endif tmp41wklro_/C/CpuArch.c0000444000175000001440000005720514641453200016024 0ustar nabijaczleweliusers/* CpuArch.c -- CPU specific code 2024-07-04 : Igor Pavlov : Public domain */ #include "Precomp.h" // #include #include "CpuArch.h" #ifdef MY_CPU_X86_OR_AMD64 #undef NEED_CHECK_FOR_CPUID #if !defined(MY_CPU_AMD64) #define NEED_CHECK_FOR_CPUID #endif /* cpuid instruction supports (subFunction) parameter in ECX, that is used only with some specific (function) parameter values. But we always use only (subFunction==0). */ /* __cpuid(): MSVC and GCC/CLANG use same function/macro name but parameters are different. We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function. */ #if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \ || defined(__clang__) /* && (__clang_major__ >= 10) */ /* there was some CLANG/GCC compilers that have issues with rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined). compiler's contains the macro __cpuid() that is similar to our code. The history of __cpuid() changes in CLANG/GCC: GCC: 2007: it preserved ebx for (__PIC__ && __i386__) 2013: it preserved rbx and ebx for __PIC__ 2014: it doesn't preserves rbx and ebx anymore we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem. CLANG: 2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check. Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)? Do we need __PIC__ test for CLANG or we must care about rbx even if __PIC__ is not defined? */ #define ASM_LN "\n" #if defined(MY_CPU_AMD64) && defined(__PIC__) \ && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) #define x86_cpuid_MACRO(p, func) { \ __asm__ __volatile__ ( \ ASM_LN "mov %%rbx, %q1" \ ASM_LN "cpuid" \ ASM_LN "xchg %%rbx, %q1" \ : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } /* "=&r" selects free register. It can select even rbx, if that register is free. "=&D" for (RDI) also works, but the code can be larger with "=&D" "2"(0) means (subFunction = 0), 2 is (zero-based) index in the output constraint list "=c" (ECX). */ #elif defined(MY_CPU_X86) && defined(__PIC__) \ && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) #define x86_cpuid_MACRO(p, func) { \ __asm__ __volatile__ ( \ ASM_LN "mov %%ebx, %k1" \ ASM_LN "cpuid" \ ASM_LN "xchg %%ebx, %k1" \ : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } #else #define x86_cpuid_MACRO(p, func) { \ __asm__ __volatile__ ( \ ASM_LN "cpuid" \ : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } #endif void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { x86_cpuid_MACRO(p, func) } Z7_NO_INLINE UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) { #if defined(NEED_CHECK_FOR_CPUID) #define EFALGS_CPUID_BIT 21 UInt32 a; __asm__ __volatile__ ( ASM_LN "pushf" ASM_LN "pushf" ASM_LN "pop %0" // ASM_LN "movl %0, %1" // ASM_LN "xorl $0x200000, %0" ASM_LN "btc %1, %0" ASM_LN "push %0" ASM_LN "popf" ASM_LN "pushf" ASM_LN "pop %0" ASM_LN "xorl (%%esp), %0" ASM_LN "popf" ASM_LN : "=&r" (a) // "=a" : "i" (EFALGS_CPUID_BIT) ); if ((a & (1 << EFALGS_CPUID_BIT)) == 0) return 0; #endif { UInt32 p[4]; x86_cpuid_MACRO(p, 0) return p[0]; } } #undef ASM_LN #elif !defined(_MSC_VER) /* // for gcc/clang and other: we can try to use __cpuid macro: #include void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { __cpuid(func, p[0], p[1], p[2], p[3]); } UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) { return (UInt32)__get_cpuid_max(0, NULL); } */ // for unsupported cpuid: void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { UNUSED_VAR(func) p[0] = p[1] = p[2] = p[3] = 0; } UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) { return 0; } #else // _MSC_VER #if !defined(MY_CPU_AMD64) UInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) { #if defined(NEED_CHECK_FOR_CPUID) #define EFALGS_CPUID_BIT 21 __asm pushfd __asm pushfd /* __asm pop eax // __asm mov edx, eax __asm btc eax, EFALGS_CPUID_BIT __asm push eax */ __asm btc dword ptr [esp], EFALGS_CPUID_BIT __asm popfd __asm pushfd __asm pop eax // __asm xor eax, edx __asm xor eax, [esp] // __asm push edx __asm popfd __asm and eax, (1 shl EFALGS_CPUID_BIT) __asm jz end_func #endif __asm push ebx __asm xor eax, eax // func __asm xor ecx, ecx // subFunction (optional) for (func == 0) __asm cpuid __asm pop ebx #if defined(NEED_CHECK_FOR_CPUID) end_func: #endif __asm ret 0 } void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { UNUSED_VAR(p) UNUSED_VAR(func) __asm push ebx __asm push edi __asm mov edi, ecx // p __asm mov eax, edx // func __asm xor ecx, ecx // subfunction (optional) for (func == 0) __asm cpuid __asm mov [edi ], eax __asm mov [edi + 4], ebx __asm mov [edi + 8], ecx __asm mov [edi + 12], edx __asm pop edi __asm pop ebx __asm ret 0 } #else // MY_CPU_AMD64 #if _MSC_VER >= 1600 #include #define MY_cpuidex __cpuidex #else /* __cpuid (func == (0 or 7)) requires subfunction number in ECX. MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction. __cpuid() in new MSVC clears ECX. __cpuid() in old MSVC (14.00) x64 doesn't clear ECX We still can use __cpuid for low (func) values that don't require ECX, but __cpuid() in old MSVC will be incorrect for some func values: (func == 7). So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, where ECX value is first parameter for FASTCALL / NO_INLINE func, So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!! */ static Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo) { UNUSED_VAR(subFunction) __cpuid(CPUInfo, func); } #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info) #pragma message("======== MY_cpuidex_HACK WAS USED ========") #endif // _MSC_VER >= 1600 #if !defined(MY_CPU_AMD64) /* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code, so we disable inlining here */ Z7_NO_INLINE #endif void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) { MY_cpuidex((Int32 *)p, (Int32)func, 0); } Z7_NO_INLINE UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) { Int32 a[4]; MY_cpuidex(a, 0, 0); return a[0]; } #endif // MY_CPU_AMD64 #endif // _MSC_VER #if defined(NEED_CHECK_FOR_CPUID) #define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; } #else #define CHECK_CPUID_IS_SUPPORTED #endif #undef NEED_CHECK_FOR_CPUID static BoolInt x86cpuid_Func_1(UInt32 *p) { CHECK_CPUID_IS_SUPPORTED z7_x86_cpuid(p, 1); return True; } /* static const UInt32 kVendors[][1] = { { 0x756E6547 }, // , 0x49656E69, 0x6C65746E }, { 0x68747541 }, // , 0x69746E65, 0x444D4163 }, { 0x746E6543 } // , 0x48727561, 0x736C7561 } }; */ /* typedef struct { UInt32 maxFunc; UInt32 vendor[3]; UInt32 ver; UInt32 b; UInt32 c; UInt32 d; } Cx86cpuid; enum { CPU_FIRM_INTEL, CPU_FIRM_AMD, CPU_FIRM_VIA }; int x86cpuid_GetFirm(const Cx86cpuid *p); #define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf)) #define x86cpuid_ver_GetModel(ver) (((ver >> 12) & 0xf0) | ((ver >> 4) & 0xf)) #define x86cpuid_ver_GetStepping(ver) (ver & 0xf) int x86cpuid_GetFirm(const Cx86cpuid *p) { unsigned i; for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++) { const UInt32 *v = kVendors[i]; if (v[0] == p->vendor[0] // && v[1] == p->vendor[1] // && v[2] == p->vendor[2] ) return (int)i; } return -1; } BoolInt CPU_Is_InOrder() { Cx86cpuid p; UInt32 family, model; if (!x86cpuid_CheckAndRead(&p)) return True; family = x86cpuid_ver_GetFamily(p.ver); model = x86cpuid_ver_GetModel(p.ver); switch (x86cpuid_GetFirm(&p)) { case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( // In-Order Atom CPU model == 0x1C // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 || model == 0x26 // 45 nm, Z6xx || model == 0x27 // 32 nm, Z2460 || model == 0x35 // 32 nm, Z2760 || model == 0x36 // 32 nm, N2xxx, D2xxx ))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); } return False; // v23 : unknown processors are not In-Order } */ #ifdef _WIN32 #include "7zWindows.h" #endif #if !defined(MY_CPU_AMD64) && defined(_WIN32) /* for legacy SSE ia32: there is no user-space cpu instruction to check that OS supports SSE register storing/restoring on context switches. So we need some OS-specific function to check that it's safe to use SSE registers. */ Z7_FORCE_INLINE static BoolInt CPU_Sys_Is_SSE_Supported(void) { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4996) // `GetVersion': was declared deprecated #endif /* low byte is major version of Windows We suppose that any Windows version since Windows2000 (major == 5) supports SSE registers */ return (Byte)GetVersion() >= 5; #if defined(_MSC_VER) #pragma warning(pop) #endif } #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; #else #define CHECK_SYS_SSE_SUPPORT #endif #if !defined(MY_CPU_AMD64) BoolInt CPU_IsSupported_CMOV(void) { UInt32 a[4]; if (!x86cpuid_Func_1(&a[0])) return 0; return (BoolInt)(a[3] >> 15) & 1; } BoolInt CPU_IsSupported_SSE(void) { UInt32 a[4]; CHECK_SYS_SSE_SUPPORT if (!x86cpuid_Func_1(&a[0])) return 0; return (BoolInt)(a[3] >> 25) & 1; } BoolInt CPU_IsSupported_SSE2(void) { UInt32 a[4]; CHECK_SYS_SSE_SUPPORT if (!x86cpuid_Func_1(&a[0])) return 0; return (BoolInt)(a[3] >> 26) & 1; } #endif static UInt32 x86cpuid_Func_1_ECX(void) { UInt32 a[4]; CHECK_SYS_SSE_SUPPORT if (!x86cpuid_Func_1(&a[0])) return 0; return a[2]; } BoolInt CPU_IsSupported_AES(void) { return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1; } BoolInt CPU_IsSupported_SSSE3(void) { return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1; } BoolInt CPU_IsSupported_SSE41(void) { return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1; } BoolInt CPU_IsSupported_SHA(void) { CHECK_SYS_SSE_SUPPORT if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { UInt32 d[4]; z7_x86_cpuid(d, 7); return (BoolInt)(d[1] >> 29) & 1; } } /* MSVC: _xgetbv() intrinsic is available since VS2010SP1. MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in that we can use or check. For any 32-bit x86 we can use asm code in MSVC, but MSVC asm code is huge after compilation. So _xgetbv() is better ICC: _xgetbv() intrinsic is available (in what version of ICC?) ICC defines (__GNUC___) and it supports gnu assembler also ICC supports MASM style code with -use-msasm switch. but ICC doesn't support __attribute__((__target__)) GCC/CLANG 9: _xgetbv() is macro that works via __builtin_ia32_xgetbv() and we need __attribute__((__target__("xsave")). But with __target__("xsave") the function will be not inlined to function that has no __target__("xsave") attribute. If we want _xgetbv() call inlining, then we should use asm version instead of calling _xgetbv(). Note:intrinsic is broke before GCC 8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684 */ #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \ || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219) \ || defined(__GNUC__) && (__GNUC__ >= 9) \ || defined(__clang__) && (__clang_major__ >= 9) // we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler #if defined(__INTEL_COMPILER) #define ATTRIB_XGETBV #elif defined(__GNUC__) || defined(__clang__) // we don't define ATTRIB_XGETBV here, because asm version is better for inlining. // #define ATTRIB_XGETBV __attribute__((__target__("xsave"))) #else #define ATTRIB_XGETBV #endif #endif #if defined(ATTRIB_XGETBV) #include #endif // XFEATURE_ENABLED_MASK/XCR0 #define MY_XCR_XFEATURE_ENABLED_MASK 0 #if defined(ATTRIB_XGETBV) ATTRIB_XGETBV #endif static UInt64 x86_xgetbv_0(UInt32 num) { #if defined(ATTRIB_XGETBV) { return #if (defined(_MSC_VER)) _xgetbv(num); #else __builtin_ia32_xgetbv( #if !defined(__clang__) (int) #endif num); #endif } #elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC) UInt32 a, d; #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) __asm__ ( "xgetbv" : "=a"(a), "=d"(d) : "c"(num) : "cc" ); #else // is old gcc __asm__ ( ".byte 0x0f, 0x01, 0xd0" "\n\t" : "=a"(a), "=d"(d) : "c"(num) : "cc" ); #endif return ((UInt64)d << 32) | a; // return a; #elif defined(_MSC_VER) && !defined(MY_CPU_AMD64) UInt32 a, d; __asm { push eax push edx push ecx mov ecx, num; // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK _emit 0x0f _emit 0x01 _emit 0xd0 mov a, eax mov d, edx pop ecx pop edx pop eax } return ((UInt64)d << 32) | a; // return a; #else // it's unknown compiler // #error "Need xgetbv function" UNUSED_VAR(num) // for MSVC-X64 we could call external function from external file. /* Actually we had checked OSXSAVE/AVX in cpuid before. So it's expected that OS supports at least AVX and below. */ // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0 return // (1 << 0) | // x87 (1 << 1) // SSE | (1 << 2); // AVX #endif } #ifdef _WIN32 /* Windows versions do not know about new ISA extensions that can be introduced. But we still can use new extensions, even if Windows doesn't report about supporting them, But we can use new extensions, only if Windows knows about new ISA extension that changes the number or size of registers: SSE, AVX/XSAVE, AVX512 So it's enough to check MY_PF_AVX_INSTRUCTIONS_AVAILABLE instead of MY_PF_AVX2_INSTRUCTIONS_AVAILABLE */ #define MY_PF_XSAVE_ENABLED 17 // #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE 36 // #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37 // #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38 // #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE 39 // #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE 40 // #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE 41 #endif BoolInt CPU_IsSupported_AVX(void) { #ifdef _WIN32 if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED)) return False; /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from some latest Win10 revisions. But we need AVX in older Windows also. So we don't use the following check: */ /* if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE)) return False; */ #endif /* OS must use new special XSAVE/XRSTOR instructions to save AVX registers when it required for context switching. At OS statring: OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions. Also OS sets bitmask in XCR0 register that defines what registers will be processed by XSAVE instruction: XCR0.SSE[bit 0] - x87 registers and state XCR0.SSE[bit 1] - SSE registers and state XCR0.AVX[bit 2] - AVX registers and state CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27]. So we can read that bit in user-space. XCR0 is available for reading in user-space by new XGETBV instruction. */ { const UInt32 c = x86cpuid_Func_1_ECX(); if (0 == (1 & (c >> 28) // AVX instructions are supported by hardware & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS. return False; } /* also we can check CPUID.1:ECX.XSAVE [bit 26] : that shows that XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware. But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */ /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1), in most cases we expect that OS also will support storing/restoring for AVX and SSE states at least. But to be ensure for that we call user-space instruction XGETBV(0) to get XCR0 value that contains bitmask that defines what exact states(registers) OS have enabled for storing/restoring. */ { const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK); // printf("\n=== XGetBV=0x%x\n", bm); return 1 & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring } // since Win7SP1: we can use GetEnabledXStateFeatures(); } BoolInt CPU_IsSupported_AVX2(void) { if (!CPU_IsSupported_AVX()) return False; if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { UInt32 d[4]; z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1 & (BoolInt)(d[1] >> 5); // avx2 } } #if 0 BoolInt CPU_IsSupported_AVX512F_AVX512VL(void) { if (!CPU_IsSupported_AVX()) return False; if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { UInt32 d[4]; BoolInt v; z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); v = 1 & (BoolInt)(d[1] >> 16) // avx512f & (BoolInt)(d[1] >> 31); // avx512vl if (!v) return False; } { const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK); // printf("\n=== XGetBV=0x%x\n", bm); return 1 & (BoolInt)(bm >> 5) // OPMASK & (BoolInt)(bm >> 6) // ZMM upper 256-bit & (BoolInt)(bm >> 7); // ZMM16 ... ZMM31 } } #endif BoolInt CPU_IsSupported_VAES_AVX2(void) { if (!CPU_IsSupported_AVX()) return False; if (z7_x86_cpuid_GetMaxFunc() < 7) return False; { UInt32 d[4]; z7_x86_cpuid(d, 7); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); return 1 & (BoolInt)(d[1] >> 5) // avx2 // & (d[1] >> 31) // avx512vl & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX } } BoolInt CPU_IsSupported_PageGB(void) { CHECK_CPUID_IS_SUPPORTED { UInt32 d[4]; z7_x86_cpuid(d, 0x80000000); if (d[0] < 0x80000001) return False; z7_x86_cpuid(d, 0x80000001); return (BoolInt)(d[3] >> 26) & 1; } } #elif defined(MY_CPU_ARM_OR_ARM64) #ifdef _WIN32 #include "7zWindows.h" BoolInt CPU_IsSupported_CRC32(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } BoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } BoolInt CPU_IsSupported_NEON(void) { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } #else #if defined(__APPLE__) /* #include #include static void Print_sysctlbyname(const char *name) { size_t bufSize = 256; char buf[256]; int res = sysctlbyname(name, &buf, &bufSize, NULL, 0); { int i; printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize); for (i = 0; i < 20; i++) printf(" %2x", (unsigned)(Byte)buf[i]); } } */ /* Print_sysctlbyname("hw.pagesize"); Print_sysctlbyname("machdep.cpu.brand_string"); */ static BoolInt z7_sysctlbyname_Get_BoolInt(const char *name) { UInt32 val = 0; if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1) return 1; return 0; } BoolInt CPU_IsSupported_CRC32(void) { return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32"); } BoolInt CPU_IsSupported_NEON(void) { return z7_sysctlbyname_Get_BoolInt("hw.optional.neon"); } #ifdef MY_CPU_ARM64 #define APPLE_CRYPTO_SUPPORT_VAL 1 #else #define APPLE_CRYPTO_SUPPORT_VAL 0 #endif BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; } BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; } BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } #else // __APPLE__ #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) #define Z7_GETAUXV_AVAILABLE #else // #pragma message("=== is not NEW GLIBC === ") #if defined __has_include #if __has_include () // #pragma message("=== sys/auxv.h is avail=== ") #define Z7_GETAUXV_AVAILABLE #endif #endif #endif #ifdef Z7_GETAUXV_AVAILABLE // #pragma message("=== Z7_GETAUXV_AVAILABLE === ") #include #define USE_HWCAP #endif #ifdef USE_HWCAP #if defined(__FreeBSD__) static unsigned long MY_getauxval(int aux) { unsigned long val; if (elf_aux_info(aux, &val, sizeof(val))) return 0; return val; } #else #define MY_getauxval getauxval #if defined __has_include #if __has_include () #include #endif #endif #endif #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); } #ifdef MY_CPU_ARM64 #define MY_HWCAP_CHECK_FUNC(name) \ MY_HWCAP_CHECK_FUNC_2(name, name) #if 1 || defined(__ARM_NEON) BoolInt CPU_IsSupported_NEON(void) { return True; } #else MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) #endif // MY_HWCAP_CHECK_FUNC (ASIMD) #elif defined(MY_CPU_ARM) #define MY_HWCAP_CHECK_FUNC(name) \ BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); } MY_HWCAP_CHECK_FUNC_2(NEON, NEON) #endif #else // USE_HWCAP #define MY_HWCAP_CHECK_FUNC(name) \ BoolInt CPU_IsSupported_ ## name(void) { return 0; } #if defined(__ARM_NEON) BoolInt CPU_IsSupported_NEON(void) { return True; } #else MY_HWCAP_CHECK_FUNC(NEON) #endif #endif // USE_HWCAP MY_HWCAP_CHECK_FUNC (CRC32) MY_HWCAP_CHECK_FUNC (SHA1) MY_HWCAP_CHECK_FUNC (SHA2) MY_HWCAP_CHECK_FUNC (AES) #endif // __APPLE__ #endif // _WIN32 #endif // MY_CPU_ARM_OR_ARM64 #ifdef __APPLE__ #include int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize) { return sysctlbyname(name, buf, bufSize, NULL, 0); } int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val) { size_t bufSize = sizeof(*val); const int res = z7_sysctlbyname_Get(name, val, &bufSize); if (res == 0 && bufSize != sizeof(*val)) return EFAULT; return res; } #endif tmp41wklro_/C/CpuArch.h0000444000175000001440000004363014634004440016026 0ustar nabijaczleweliusers/* CpuArch.h -- CPU specific code 2024-06-17 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_CPU_ARCH_H #define ZIP7_INC_CPU_ARCH_H #include "7zTypes.h" EXTERN_C_BEGIN /* MY_CPU_LE means that CPU is LITTLE ENDIAN. MY_CPU_BE means that CPU is BIG ENDIAN. If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. MY_CPU_64BIT means that processor can work with 64-bit registers. MY_CPU_64BIT can be used to select fast code branch MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) */ #if !defined(_M_ARM64EC) #if defined(_M_X64) \ || defined(_M_AMD64) \ || defined(__x86_64__) \ || defined(__AMD64__) \ || defined(__amd64__) #define MY_CPU_AMD64 #ifdef __ILP32__ #define MY_CPU_NAME "x32" #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "x64" #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #endif #endif #if defined(_M_IX86) \ || defined(__i386__) #define MY_CPU_X86 #define MY_CPU_NAME "x86" /* #define MY_CPU_32BIT */ #define MY_CPU_SIZEOF_POINTER 4 #endif #if defined(_M_ARM64) \ || defined(_M_ARM64EC) \ || defined(__AARCH64EL__) \ || defined(__AARCH64EB__) \ || defined(__aarch64__) #define MY_CPU_ARM64 #if defined(__ILP32__) \ || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4) #define MY_CPU_NAME "arm64-32" #define MY_CPU_SIZEOF_POINTER 4 #elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16) #define MY_CPU_NAME "arm64-128" #define MY_CPU_SIZEOF_POINTER 16 #else #if defined(_M_ARM64EC) #define MY_CPU_NAME "arm64ec" #else #define MY_CPU_NAME "arm64" #endif #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #endif #if defined(_M_ARM) \ || defined(_M_ARM_NT) \ || defined(_M_ARMT) \ || defined(__arm__) \ || defined(__thumb__) \ || defined(__ARMEL__) \ || defined(__ARMEB__) \ || defined(__THUMBEL__) \ || defined(__THUMBEB__) #define MY_CPU_ARM #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) #define MY_CPU_ARMT #define MY_CPU_NAME "armt" #else #define MY_CPU_ARM32 #define MY_CPU_NAME "arm" #endif /* #define MY_CPU_32BIT */ #define MY_CPU_SIZEOF_POINTER 4 #endif #if defined(_M_IA64) \ || defined(__ia64__) #define MY_CPU_IA64 #define MY_CPU_NAME "ia64" #define MY_CPU_64BIT #endif #if defined(__mips64) \ || defined(__mips64__) \ || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) #define MY_CPU_NAME "mips64" #define MY_CPU_64BIT #elif defined(__mips__) #define MY_CPU_NAME "mips" /* #define MY_CPU_32BIT */ #endif #if defined(__ppc64__) \ || defined(__powerpc64__) \ || defined(__ppc__) \ || defined(__powerpc__) \ || defined(__PPC__) \ || defined(_POWER) #define MY_CPU_PPC_OR_PPC64 #if defined(__ppc64__) \ || defined(__powerpc64__) \ || defined(_LP64) \ || defined(__64BIT__) #ifdef __ILP32__ #define MY_CPU_NAME "ppc64-32" #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "ppc64" #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #else #define MY_CPU_NAME "ppc" #define MY_CPU_SIZEOF_POINTER 4 /* #define MY_CPU_32BIT */ #endif #endif #if defined(__sparc__) \ || defined(__sparc) #define MY_CPU_SPARC #if defined(__LP64__) \ || defined(_LP64) \ || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8) #define MY_CPU_NAME "sparcv9" #define MY_CPU_SIZEOF_POINTER 8 #define MY_CPU_64BIT #elif defined(__sparc_v9__) \ || defined(__sparcv9) #define MY_CPU_64BIT #if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4) #define MY_CPU_NAME "sparcv9-32" #else #define MY_CPU_NAME "sparcv9m" #endif #elif defined(__sparc_v8__) \ || defined(__sparcv8) #define MY_CPU_NAME "sparcv8" #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "sparc" #endif #endif #if defined(__riscv) \ || defined(__riscv__) #define MY_CPU_RISCV #if __riscv_xlen == 32 #define MY_CPU_NAME "riscv32" #elif __riscv_xlen == 64 #define MY_CPU_NAME "riscv64" #else #define MY_CPU_NAME "riscv" #endif #endif #if defined(__loongarch__) #define MY_CPU_LOONGARCH #if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64) #define MY_CPU_64BIT #endif #if defined(__loongarch64) #define MY_CPU_NAME "loongarch64" #define MY_CPU_LOONGARCH64 #else #define MY_CPU_NAME "loongarch" #endif #endif // #undef MY_CPU_NAME // #undef MY_CPU_SIZEOF_POINTER // #define __e2k__ // #define __SIZEOF_POINTER__ 4 #if defined(__e2k__) #define MY_CPU_E2K #if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4) #define MY_CPU_NAME "e2k-32" #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "e2k" #if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8) #define MY_CPU_SIZEOF_POINTER 8 #endif #endif #define MY_CPU_64BIT #endif #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) #define MY_CPU_X86_OR_AMD64 #endif #if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64) #define MY_CPU_ARM_OR_ARM64 #endif #ifdef _WIN32 #ifdef MY_CPU_ARM #define MY_CPU_ARM_LE #endif #ifdef MY_CPU_ARM64 #define MY_CPU_ARM64_LE #endif #ifdef _M_IA64 #define MY_CPU_IA64_LE #endif #endif #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM64_LE) \ || defined(MY_CPU_IA64_LE) \ || defined(_LITTLE_ENDIAN) \ || defined(__LITTLE_ENDIAN__) \ || defined(__ARMEL__) \ || defined(__THUMBEL__) \ || defined(__AARCH64EL__) \ || defined(__MIPSEL__) \ || defined(__MIPSEL) \ || defined(_MIPSEL) \ || defined(__BFIN__) \ || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) #define MY_CPU_LE #endif #if defined(__BIG_ENDIAN__) \ || defined(__ARMEB__) \ || defined(__THUMBEB__) \ || defined(__AARCH64EB__) \ || defined(__MIPSEB__) \ || defined(__MIPSEB) \ || defined(_MIPSEB) \ || defined(__m68k__) \ || defined(__s390__) \ || defined(__s390x__) \ || defined(__zarch__) \ || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) #define MY_CPU_BE #endif #if defined(MY_CPU_LE) && defined(MY_CPU_BE) #error Stop_Compiling_Bad_Endian #endif #if !defined(MY_CPU_LE) && !defined(MY_CPU_BE) #error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time #endif #if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) #error Stop_Compiling_Bad_32_64_BIT #endif #ifdef __SIZEOF_POINTER__ #ifdef MY_CPU_SIZEOF_POINTER #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__ #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE #endif #else #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__ #endif #endif #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) #if defined (_LP64) #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE #endif #endif #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1)) #define MY_CPU_pragma_pop __pragma(pack(pop)) #else #define MY_CPU_pragma_pack_push_1 #define MY_CPU_pragma_pop #endif #else #ifdef __xlC__ #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)") #define MY_CPU_pragma_pop _Pragma("pack()") #else #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)") #define MY_CPU_pragma_pop _Pragma("pack(pop)") #endif #endif #ifndef MY_CPU_NAME // #define MY_CPU_IS_UNKNOWN #ifdef MY_CPU_LE #define MY_CPU_NAME "LE" #elif defined(MY_CPU_BE) #define MY_CPU_NAME "BE" #else /* #define MY_CPU_NAME "" */ #endif #endif #ifdef __has_builtin #define Z7_has_builtin(x) __has_builtin(x) #else #define Z7_has_builtin(x) 0 #endif #define Z7_BSWAP32_CONST(v) \ ( (((UInt32)(v) << 24) ) \ | (((UInt32)(v) << 8) & (UInt32)0xff0000) \ | (((UInt32)(v) >> 8) & (UInt32)0xff00 ) \ | (((UInt32)(v) >> 24) )) #if defined(_MSC_VER) && (_MSC_VER >= 1300) #include /* Note: these macros will use bswap instruction (486), that is unsupported in 386 cpu */ #pragma intrinsic(_byteswap_ushort) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define Z7_BSWAP16(v) _byteswap_ushort(v) #define Z7_BSWAP32(v) _byteswap_ulong (v) #define Z7_BSWAP64(v) _byteswap_uint64(v) #define Z7_CPU_FAST_BSWAP_SUPPORTED /* GCC can generate slow code that calls function for __builtin_bswap32() for: - GCC for RISCV, if Zbb/XTHeadBb extension is not used. - GCC for SPARC. The code from CLANG for SPARC also is not fastest. So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases. */ #elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb) || defined(__riscv_xtheadbb)) \ && !defined(MY_CPU_SPARC) \ && ( \ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \ ) #define Z7_BSWAP16(v) __builtin_bswap16(v) #define Z7_BSWAP32(v) __builtin_bswap32(v) #define Z7_BSWAP64(v) __builtin_bswap64(v) #define Z7_CPU_FAST_BSWAP_SUPPORTED #else #define Z7_BSWAP16(v) ((UInt16) \ ( ((UInt32)(v) << 8) \ | ((UInt32)(v) >> 8) \ )) #define Z7_BSWAP32(v) Z7_BSWAP32_CONST(v) #define Z7_BSWAP64(v) \ ( ( ( (UInt64)(v) ) << 8 * 7 ) \ | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 1) ) << 8 * 5 ) \ | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 2) ) << 8 * 3 ) \ | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 3) ) << 8 * 1 ) \ | ( ( (UInt64)(v) >> 8 * 1 ) & ((UInt32)0xff << 8 * 3) ) \ | ( ( (UInt64)(v) >> 8 * 3 ) & ((UInt32)0xff << 8 * 2) ) \ | ( ( (UInt64)(v) >> 8 * 5 ) & ((UInt32)0xff << 8 * 1) ) \ | ( ( (UInt64)(v) >> 8 * 7 ) ) \ ) #endif #ifdef MY_CPU_LE #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM64) \ || defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \ || defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6) #define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN_64 #elif defined(__ARM_FEATURE_UNALIGNED) /* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions. Description of problems: problem-1 : 32-bit ARM architecture: multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM) require 32-bit (WORD) alignment (by 32-bit ARM architecture). So there is "Alignment fault exception", if data is not aligned for 32-bit. problem-2 : 32-bit kernels and arm64 kernels: 32-bit linux kernels provide fixup for these "paired" instruction "Alignment fault exception". So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux. But some arm64 kernels do not handle these faults in 32-bit programs. So we have unhandled exception for such instructions. Probably some new arm64 kernels have fixed it, and unaligned paired-access instructions work in new kernels? problem-3 : compiler for 32-bit arm: Compilers use LDRD/STRD/LDM/STM for UInt64 accesses and for another cases where two 32-bit accesses are fused to one multi-access instruction. So UInt64 variables must be aligned for 32-bit, and each 32-bit access must be aligned for 32-bit, if we want to avoid "Alignment fault" exception (handled or unhandled). problem-4 : performace: Even if unaligned access is handled by kernel, it will be slow. So if we allow unaligned access, we can get fast unaligned single-access, and slow unaligned paired-access. We don't allow unaligned access on 32-bit arm, because compiler genarates paired-access instructions that require 32-bit alignment, and some arm64 kernels have no handler for these instructions. Also unaligned paired-access instructions will be slow, if kernel handles them. */ // it must be disabled: // #define MY_CPU_LE_UNALIGN #endif #endif #ifdef MY_CPU_LE_UNALIGN #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) #ifdef MY_CPU_LE_UNALIGN_64 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) #define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } #endif #define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); } #define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); } #else #define GetUi16(p) ( (UInt16) ( \ ((const Byte *)(p))[0] | \ ((UInt16)((const Byte *)(p))[1] << 8) )) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)_vvv_; \ _ppp_[1] = (Byte)(_vvv_ >> 8); } #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)_vvv_; \ _ppp_[1] = (Byte)(_vvv_ >> 8); \ _ppp_[2] = (Byte)(_vvv_ >> 16); \ _ppp_[3] = (Byte)(_vvv_ >> 24); } #endif #ifndef GetUi64 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #endif #ifndef SetUi64 #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ SetUi32(_ppp2_ , (UInt32)_vvv2_) \ SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)) } #endif #if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) #define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) #define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } #if defined(MY_CPU_LE_UNALIGN_64) #define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) #endif #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)(_vvv_ >> 24); \ _ppp_[1] = (Byte)(_vvv_ >> 16); \ _ppp_[2] = (Byte)(_vvv_ >> 8); \ _ppp_[3] = (Byte)_vvv_; } #endif #ifndef GetBe64 #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #ifndef GetBe16 #define GetBe16(p) ( (UInt16) ( \ ((UInt16)((const Byte *)(p))[0] << 8) | \ ((const Byte *)(p))[1] )) #endif #if defined(MY_CPU_BE) #define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) #define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) #define Z7_CONV_NATIVE_TO_BE_32(v) (v) #elif defined(MY_CPU_LE) #define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) #define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) #define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v) #else #error Stop_Compiling_Unknown_Endian_CONV #endif #if defined(MY_CPU_BE) #define GetBe64a(p) (*(const UInt64 *)(const void *)(p)) #define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) #define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } #define GetUi64a(p) GetUi64(p) #define GetUi32a(p) GetUi32(p) #define GetUi16a(p) GetUi16(p) #define SetUi32a(p, v) SetUi32(p, v) #define SetUi16a(p, v) SetUi16(p, v) #elif defined(MY_CPU_LE) #define GetUi64a(p) (*(const UInt64 *)(const void *)(p)) #define GetUi32a(p) (*(const UInt32 *)(const void *)(p)) #define GetUi16a(p) (*(const UInt16 *)(const void *)(p)) #define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } #define GetBe64a(p) GetBe64(p) #define GetBe32a(p) GetBe32(p) #define GetBe16a(p) GetBe16(p) #define SetBe32a(p, v) SetBe32(p, v) #define SetBe16a(p, v) SetBe16(p, v) #else #error Stop_Compiling_Unknown_Endian_CPU_a #endif #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM_OR_ARM64) \ || defined(MY_CPU_PPC_OR_PPC64) #define Z7_CPU_FAST_ROTATE_SUPPORTED #endif #ifdef MY_CPU_X86_OR_AMD64 void Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function); UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void); #if defined(MY_CPU_AMD64) #define Z7_IF_X86_CPUID_SUPPORTED #else #define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc()) #endif BoolInt CPU_IsSupported_AES(void); BoolInt CPU_IsSupported_AVX(void); BoolInt CPU_IsSupported_AVX2(void); BoolInt CPU_IsSupported_AVX512F_AVX512VL(void); BoolInt CPU_IsSupported_VAES_AVX2(void); BoolInt CPU_IsSupported_CMOV(void); BoolInt CPU_IsSupported_SSE(void); BoolInt CPU_IsSupported_SSE2(void); BoolInt CPU_IsSupported_SSSE3(void); BoolInt CPU_IsSupported_SSE41(void); BoolInt CPU_IsSupported_SHA(void); BoolInt CPU_IsSupported_PageGB(void); #elif defined(MY_CPU_ARM_OR_ARM64) BoolInt CPU_IsSupported_CRC32(void); BoolInt CPU_IsSupported_NEON(void); #if defined(_WIN32) BoolInt CPU_IsSupported_CRYPTO(void); #define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO #define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO #define CPU_IsSupported_AES CPU_IsSupported_CRYPTO #else BoolInt CPU_IsSupported_SHA1(void); BoolInt CPU_IsSupported_SHA2(void); BoolInt CPU_IsSupported_AES(void); #endif #endif #if defined(__APPLE__) int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); #endif EXTERN_C_END #endif tmp41wklro_/C/Delta.c0000444000175000001440000000575514010537620015532 0ustar nabijaczleweliusers/* Delta.c -- Delta converter 2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Delta.h" void Delta_Init(Byte *state) { unsigned i; for (i = 0; i < DELTA_STATE_SIZE; i++) state[i] = 0; } void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) { Byte temp[DELTA_STATE_SIZE]; if (size == 0) return; { unsigned i = 0; do temp[i] = state[i]; while (++i != delta); } if (size <= delta) { unsigned i = 0, k; do { Byte b = *data; *data++ = (Byte)(b - temp[i]); temp[i] = b; } while (++i != size); k = 0; do { if (i == delta) i = 0; state[k] = temp[i++]; } while (++k != delta); return; } { Byte *p = data + size - delta; { unsigned i = 0; do state[i] = *p++; while (++i != delta); } { const Byte *lim = data + delta; ptrdiff_t dif = -(ptrdiff_t)delta; if (((ptrdiff_t)size + dif) & 1) { --p; *p = (Byte)(*p - p[dif]); } while (p != lim) { --p; *p = (Byte)(*p - p[dif]); --p; *p = (Byte)(*p - p[dif]); } dif = -dif; do { --p; *p = (Byte)(*p - temp[--dif]); } while (dif != 0); } } } void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) { unsigned i; const Byte *lim; if (size == 0) return; i = 0; lim = data + size; if (size <= delta) { do *data = (Byte)(*data + state[i++]); while (++data != lim); for (; delta != i; state++, delta--) *state = state[i]; data -= i; } else { /* #define B(n) b ## n #define I(n) Byte B(n) = state[n]; #define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); } #define F(n) if (data != lim) { U(n) } if (delta == 1) { I(0) if ((lim - data) & 1) { U(0) } while (data != lim) { U(0) U(0) } data -= 1; } else if (delta == 2) { I(0) I(1) lim -= 1; while (data < lim) { U(0) U(1) } lim += 1; F(0) data -= 2; } else if (delta == 3) { I(0) I(1) I(2) lim -= 2; while (data < lim) { U(0) U(1) U(2) } lim += 2; F(0) F(1) data -= 3; } else if (delta == 4) { I(0) I(1) I(2) I(3) lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) } lim += 3; F(0) F(1) F(2) data -= 4; } else */ { do { *data = (Byte)(*data + state[i++]); data++; } while (i != delta); { ptrdiff_t dif = -(ptrdiff_t)delta; do *data = (Byte)(*data + data[dif]); while (++data != lim); data += dif; } } } do *state++ = *data; while (++data != lim); } tmp41wklro_/C/Delta.h0000444000175000001440000000063114400342440015520 0ustar nabijaczleweliusers/* Delta.h -- Delta converter 2023-03-03 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_DELTA_H #define ZIP7_INC_DELTA_H #include "7zTypes.h" EXTERN_C_BEGIN #define DELTA_STATE_SIZE 256 void Delta_Init(Byte *state); void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); EXTERN_C_END #endif tmp41wklro_/C/DllSecur.c0000444000175000001440000000456214533141040016206 0ustar nabijaczleweliusers/* DllSecur.c -- DLL loading security 2023-12-03 : Igor Pavlov : Public domain */ #include "Precomp.h" #ifdef _WIN32 #include "7zWindows.h" #include "DllSecur.h" #ifndef UNDER_CE Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); #define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 #define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800 #define DELIM "\0" static const char * const g_Dlls = "userenv" DELIM "setupapi" DELIM "apphelp" DELIM "propsys" DELIM "dwmapi" DELIM "cryptbase" DELIM "oleacc" DELIM "clbcatq" DELIM "version" #ifndef _CONSOLE DELIM "uxtheme" #endif DELIM; #endif #ifdef __clang__ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif #if defined (_MSC_VER) && _MSC_VER >= 1900 // sysinfoapi.h: kit10: GetVersion was declared deprecated #pragma warning(disable : 4996) #endif #define IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN \ if ((UInt16)GetVersion() != 6) { \ const \ Func_SetDefaultDllDirectories setDllDirs = \ (Func_SetDefaultDllDirectories) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \ "SetDefaultDllDirectories"); \ if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; } void My_SetDefaultDllDirectories(void) { #ifndef UNDER_CE IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN #endif } void LoadSecurityDlls(void) { #ifndef UNDER_CE // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ??? IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN { wchar_t buf[MAX_PATH + 100]; const char *dll; unsigned pos = GetSystemDirectoryW(buf, MAX_PATH + 2); if (pos == 0 || pos > MAX_PATH) return; if (buf[pos - 1] != '\\') buf[pos++] = '\\'; for (dll = g_Dlls; *dll != 0;) { wchar_t *dest = &buf[pos]; for (;;) { const char c = *dll++; if (c == 0) break; *dest++ = (Byte)c; } dest[0] = '.'; dest[1] = 'd'; dest[2] = 'l'; dest[3] = 'l'; dest[4] = 0; // lstrcatW(buf, L".dll"); LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } } #endif } #endif // _WIN32 tmp41wklro_/C/DllSecur.h0000444000175000001440000000047614400342440016213 0ustar nabijaczleweliusers/* DllSecur.h -- DLL loading for security 2023-03-03 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_DLL_SECUR_H #define ZIP7_INC_DLL_SECUR_H #include "7zTypes.h" EXTERN_C_BEGIN #ifdef _WIN32 void My_SetDefaultDllDirectories(void); void LoadSecurityDlls(void); #endif EXTERN_C_END #endif tmp41wklro_/C/LzFind.c0000444000175000001440000012715014570276360015675 0ustar nabijaczleweliusers/* LzFind.c -- Match finder for LZ algorithms 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include // #include #include "CpuArch.h" #include "LzFind.h" #include "LzHash.h" #define kBlockMoveAlign (1 << 7) // alignment for memmove() #define kBlockSizeAlign (1 << 16) // alignment for block allocation #define kBlockSizeReserveMin (1 << 24) // it's 1/256 from 4 GB dictinary #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0) // #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xfff) // for debug // #define kNormalizeAlign (1 << 7) // alignment for speculated accesses #define GET_AVAIL_BYTES(p) \ Inline_MatchFinder_GetNumAvailableBytes(p) // #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define kFix5HashSize kFix4HashSize /* HASH2_CALC: if (hv) match, then cur[0] and cur[1] also match */ #define HASH2_CALC hv = GetUi16(cur); // (crc[0 ... 255] & 0xFF) provides one-to-one correspondence to [0 ... 255] /* HASH3_CALC: if (cur[0]) and (h2) match, then cur[1] also match if (cur[0]) and (hv) match, then cur[1] and cur[2] also match */ #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \ h3 = temp & (kHash3Size - 1); \ hv = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \ h3 = temp & (kHash3Size - 1); \ temp ^= (p->crc[cur[3]] << kLzHash_CrcShift_1); \ /* h4 = temp & p->hash4Mask; */ /* (kHash4Size - 1); */ \ hv = (temp ^ (p->crc[cur[4]] << kLzHash_CrcShift_2)) & p->hashMask; } #define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) { // if (!p->directInput) { ISzAlloc_Free(alloc, p->bufBase); p->bufBase = NULL; } } static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr alloc) { if (blockSize == 0) return 0; if (!p->bufBase || p->blockSize != blockSize) { // size_t blockSizeT; LzInWindow_Free(p, alloc); p->blockSize = blockSize; // blockSizeT = blockSize; // printf("\nblockSize = 0x%x\n", blockSize); /* #if defined _WIN64 // we can allocate 4GiB, but still use UInt32 for (p->blockSize) // we use UInt32 type for (p->blockSize), because // we don't want to wrap over 4 GiB, // when we use (p->streamPos - p->pos) that is UInt32. if (blockSize >= (UInt32)0 - (UInt32)kBlockSizeAlign) { blockSizeT = ((size_t)1 << 32); printf("\nchanged to blockSizeT = 4GiB\n"); } #endif */ p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); // printf("\nbufferBase = %p\n", p->bufBase); // return 0; // for debug } return (p->bufBase != NULL); } static const Byte *MatchFinder_GetPointerToCurrentPos(void *p) { return ((CMatchFinder *)p)->buffer; } static UInt32 MatchFinder_GetNumAvailableBytes(void *p) { return GET_AVAIL_BYTES((CMatchFinder *)p); } Z7_NO_INLINE static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */ if (p->directInput) { UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p); if (curSize > p->directInputRem) curSize = (UInt32)p->directInputRem; p->streamPos += curSize; p->directInputRem -= curSize; if (p->directInputRem == 0) p->streamEndWasReached = 1; return; } for (;;) { const Byte *dest = p->buffer + GET_AVAIL_BYTES(p); size_t size = (size_t)(p->bufBase + p->blockSize - dest); if (size == 0) { /* we call ReadBlock() after NeedMove() and MoveBlock(). NeedMove() and MoveBlock() povide more than (keepSizeAfter) to the end of (blockSize). So we don't execute this branch in normal code flow. We can go here, if we will call ReadBlock() before NeedMove(), MoveBlock(). */ // p->result = SZ_ERROR_FAIL; // we can show error here return; } // #define kRead 3 // if (size > kRead) size = kRead; // for debug /* // we need cast (Byte *)dest. #ifdef __clang__ #pragma GCC diagnostic ignored "-Wcast-qual" #endif */ p->result = ISeqInStream_Read(p->stream, p->bufBase + (dest - p->bufBase), &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (GET_AVAIL_BYTES(p) > p->keepSizeAfter) return; /* here and in another (p->keepSizeAfter) checks we keep on 1 byte more than was requested by Create() function (GET_AVAIL_BYTES(p) >= p->keepSizeAfter) - minimal required size */ } // on exit: (p->result != SZ_OK || p->streamEndWasReached || GET_AVAIL_BYTES(p) > p->keepSizeAfter) } Z7_NO_INLINE void MatchFinder_MoveBlock(CMatchFinder *p) { const size_t offset = (size_t)(p->buffer - p->bufBase) - p->keepSizeBefore; const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore; p->buffer = p->bufBase + keepBefore; memmove(p->bufBase, p->bufBase + (offset & ~((size_t)kBlockMoveAlign - 1)), keepBefore + (size_t)GET_AVAIL_BYTES(p)); } /* We call MoveBlock() before ReadBlock(). So MoveBlock() can be wasteful operation, if the whole input data can fit in current block even without calling MoveBlock(). in important case where (dataSize <= historySize) condition (p->blockSize > dataSize + p->keepSizeAfter) is met So there is no MoveBlock() in that case case. */ int MatchFinder_NeedMove(CMatchFinder *p) { if (p->directInput) return 0; if (p->streamEndWasReached || p->result != SZ_OK) return 0; return ((size_t)(p->bufBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->keepSizeAfter >= GET_AVAIL_BYTES(p)) MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; p->numHashBytes_Min = 2; p->numHashOutBits = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { unsigned i; p->buffer = NULL; p->bufBase = NULL; p->directInput = 0; p->stream = NULL; p->hash = NULL; p->expectedDataSize = (UInt64)(Int64)-1; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = (UInt32)i; unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); p->crc[i] = r; } } #undef kCrcPoly static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->hash); p->hash = NULL; } void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) { const size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return NULL; return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); } #if (kBlockSizeReserveMin < kBlockSizeAlign * 2) #error Stop_Compiling_Bad_Reserve #endif static UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize) { UInt32 blockSize = (p->keepSizeBefore + p->keepSizeAfter); /* if (historySize > kMaxHistorySize) return 0; */ // printf("\nhistorySize == 0x%x\n", historySize); if (p->keepSizeBefore < historySize || blockSize < p->keepSizeBefore) // if 32-bit overflow return 0; { const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)kBlockSizeAlign; const UInt32 rem = kBlockSizeMax - blockSize; const UInt32 reserve = (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)) + (1 << 12) + kBlockMoveAlign + kBlockSizeAlign; // do not overflow 32-bit here if (blockSize >= kBlockSizeMax || rem < kBlockSizeReserveMin) // we reject settings that will be slow return 0; if (reserve >= rem) blockSize = kBlockSizeMax; else { blockSize += reserve; blockSize &= ~(UInt32)(kBlockSizeAlign - 1); } } // printf("\n LzFind_blockSize = %x\n", blockSize); // printf("\n LzFind_blockSize = %d\n", blockSize >> 20); return blockSize; } // input is historySize static UInt32 MatchFinder_GetHashMask2(CMatchFinder *p, UInt32 hs) { if (p->numHashBytes == 2) return (1 << 16) - 1; if (hs != 0) hs--; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); // we propagated 16 bits in (hs). Low 16 bits must be set later if (hs >= (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ } // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) hs |= (1 << 16) - 1; /* don't change it! */ // bt5: we adjust the size with recommended minimum size if (p->numHashBytes >= 5) hs |= (256 << kLzHash_CrcShift_2) - 1; return hs; } // input is historySize static UInt32 MatchFinder_GetHashMask(CMatchFinder *p, UInt32 hs) { if (p->numHashBytes == 2) return (1 << 16) - 1; if (hs != 0) hs--; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); // we propagated 16 bits in (hs). Low 16 bits must be set later hs >>= 1; if (hs >= (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ } // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) hs |= (1 << 16) - 1; /* don't change it! */ // bt5: we adjust the size with recommended minimum size if (p->numHashBytes >= 5) hs |= (256 << kLzHash_CrcShift_2) - 1; return hs; } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { /* we need one additional byte in (p->keepSizeBefore), since we use MoveBlock() after (p->pos++) and before dictionary using */ // keepAddBufferBefore = (UInt32)0xFFFFFFFF - (1 << 22); // for debug p->keepSizeBefore = historySize + keepAddBufferBefore + 1; keepAddBufferAfter += matchMaxLen; /* we need (p->keepSizeAfter >= p->numHashBytes) */ if (keepAddBufferAfter < p->numHashBytes) keepAddBufferAfter = p->numHashBytes; // keepAddBufferAfter -= 2; // for debug p->keepSizeAfter = keepAddBufferAfter; if (p->directInput) p->blockSize = 0; if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc)) { size_t hashSizeSum; { UInt32 hs; UInt32 hsCur; if (p->numHashOutBits != 0) { unsigned numBits = p->numHashOutBits; const unsigned nbMax = (p->numHashBytes == 2 ? 16 : (p->numHashBytes == 3 ? 24 : 32)); if (numBits > nbMax) numBits = nbMax; if (numBits >= 32) hs = (UInt32)0 - 1; else hs = ((UInt32)1 << numBits) - 1; // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) hs |= (1 << 16) - 1; /* don't change it! */ if (p->numHashBytes >= 5) hs |= (256 << kLzHash_CrcShift_2) - 1; { const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize); if (hs > hs2) hs = hs2; } hsCur = hs; if (p->expectedDataSize < historySize) { const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize); if (hsCur > hs2) hsCur = hs2; } } else { hs = MatchFinder_GetHashMask(p, historySize); hsCur = hs; if (p->expectedDataSize < historySize) { hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize); if (hsCur > hs) // is it possible? hsCur = hs; } } p->hashMask = hsCur; hashSizeSum = hs; hashSizeSum++; if (hashSizeSum < hs) return 0; { UInt32 fixedHashSize = 0; if (p->numHashBytes > 2 && p->numHashBytes_Min <= 2) fixedHashSize += kHash2Size; if (p->numHashBytes > 3 && p->numHashBytes_Min <= 3) fixedHashSize += kHash3Size; // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; hashSizeSum += fixedHashSize; p->fixedHashSize = fixedHashSize; } } p->matchMaxLen = matchMaxLen; { size_t newSize; size_t numSons; const UInt32 newCyclicBufferSize = historySize + 1; // do not change it p->historySize = historySize; p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1) numSons = newCyclicBufferSize; if (p->btMode) numSons <<= 1; newSize = hashSizeSum + numSons; if (numSons < newCyclicBufferSize || newSize < numSons) return 0; // aligned size is not required here, but it can be better for some loops #define NUM_REFS_ALIGN_MASK 0xF newSize = (newSize + NUM_REFS_ALIGN_MASK) & ~(size_t)NUM_REFS_ALIGN_MASK; // 22.02: we don't reallocate buffer, if old size is enough if (p->hash && p->numRefs >= newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->numRefs = newSize; p->hash = AllocRefs(newSize, alloc); if (p->hash) { p->son = p->hash + hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 k; UInt32 n = kMaxValForNormalize - p->pos; if (n == 0) n = (UInt32)(Int32)-1; // we allow (pos == 0) at start even with (kMaxValForNormalize == 0) k = p->cyclicBufferSize - p->cyclicBufferPos; if (k < n) n = k; k = GET_AVAIL_BYTES(p); { const UInt32 ksa = p->keepSizeAfter; UInt32 mm = p->matchMaxLen; if (k > ksa) k -= ksa; // we must limit exactly to keepSizeAfter for ReadBlock else if (k >= mm) { // the limitation for (p->lenLimit) update k -= mm; // optimization : to reduce the number of checks k++; // k = 1; // non-optimized version : for debug } else { mm = k; if (k != 0) k = 1; } p->lenLimit = mm; } if (k < n) n = k; p->posLimit = p->pos + n; } void MatchFinder_Init_LowHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash; const size_t numItems = p->fixedHashSize; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } void MatchFinder_Init_HighHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash + p->fixedHashSize; const size_t numItems = (size_t)p->hashMask + 1; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } void MatchFinder_Init_4(CMatchFinder *p) { if (!p->directInput) p->buffer = p->bufBase; { /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker. the code in CMatchFinderMt expects (pos = 1) */ p->pos = p->streamPos = 1; // it's smallest optimal value. do not change it // 0; // for debug } p->result = SZ_OK; p->streamEndWasReached = 0; } // (CYC_TO_POS_OFFSET == 0) is expected by some optimized code #define CYC_TO_POS_OFFSET 0 // #define CYC_TO_POS_OFFSET 1 // for debug void MatchFinder_Init(void *_p) { CMatchFinder *p = (CMatchFinder *)_p; MatchFinder_Init_HighHash(p); MatchFinder_Init_LowHash(p); MatchFinder_Init_4(p); // if (readData) MatchFinder_ReadBlock(p); /* if we init (cyclicBufferPos = pos), then we can use one variable instead of both (cyclicBufferPos) and (pos) : only before (cyclicBufferPos) wrapping */ p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); // init with relation to (pos) // p->cyclicBufferPos = 0; // smallest value // p->son[0] = p->son[1] = 0; // unused: we can init skipped record for speculated accesses. MatchFinder_SetLimits(p); } #ifdef MY_CPU_X86_OR_AMD64 #if defined(__clang__) && (__clang_major__ >= 4) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) #define USE_LZFIND_SATUR_SUB_128 #define USE_LZFIND_SATUR_SUB_256 #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("sse4.1"))) #define LZFIND_ATTRIB_AVX2 __attribute__((__target__("avx2"))) #elif defined(_MSC_VER) #if (_MSC_VER >= 1600) #define USE_LZFIND_SATUR_SUB_128 #endif #if (_MSC_VER >= 1900) #define USE_LZFIND_SATUR_SUB_256 #endif #endif #elif defined(MY_CPU_ARM64) \ /* || (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) */ #if defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) #define USE_LZFIND_SATUR_SUB_128 #ifdef MY_CPU_ARM64 // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(""))) #else #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=neon"))) #endif #elif defined(_MSC_VER) #if (_MSC_VER >= 1910) #define USE_LZFIND_SATUR_SUB_128 #endif #endif #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) #include #else #include #endif #endif #ifdef USE_LZFIND_SATUR_SUB_128 // #define Z7_SHOW_HW_STATUS #ifdef Z7_SHOW_HW_STATUS #include #define PRF(x) x PRF(;) #else #define PRF(x) #endif #ifdef MY_CPU_ARM_OR_ARM64 #ifdef MY_CPU_ARM64 // #define FORCE_LZFIND_SATUR_SUB_128 #endif typedef uint32x4_t LzFind_v128; #define SASUB_128_V(v, s) \ vsubq_u32(vmaxq_u32(v, s), s) #else // MY_CPU_ARM_OR_ARM64 #include // sse4.1 typedef __m128i LzFind_v128; // SSE 4.1 #define SASUB_128_V(v, s) \ _mm_sub_epi32(_mm_max_epu32(v, s), s) #endif // MY_CPU_ARM_OR_ARM64 #define SASUB_128(i) \ *( LzFind_v128 *)( void *)(items + (i) * 4) = SASUB_128_V( \ *(const LzFind_v128 *)(const void *)(items + (i) * 4), sub2); Z7_NO_INLINE static #ifdef LZFIND_ATTRIB_SSE41 LZFIND_ATTRIB_SSE41 #endif void Z7_FASTCALL LzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim) { const LzFind_v128 sub2 = #ifdef MY_CPU_ARM_OR_ARM64 vdupq_n_u32(subValue); #else _mm_set_epi32((Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); #endif Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SASUB_128(0) SASUB_128(1) items += 2 * 4; SASUB_128(0) SASUB_128(1) items += 2 * 4; } while (items != lim); } #ifdef USE_LZFIND_SATUR_SUB_256 #include // avx /* clang :immintrin.h uses #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ defined(__AVX2__) #include #endif so we need for clang-cl */ #if defined(__clang__) #include #include #endif // AVX2: #define SASUB_256(i) \ *( __m256i *)( void *)(items + (i) * 8) = \ _mm256_sub_epi32(_mm256_max_epu32( \ *(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2); Z7_NO_INLINE static #ifdef LZFIND_ATTRIB_AVX2 LZFIND_ATTRIB_AVX2 #endif void Z7_FASTCALL LzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim) { const __m256i sub2 = _mm256_set_epi32( (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SASUB_256(0) SASUB_256(1) items += 2 * 8; SASUB_256(0) SASUB_256(1) items += 2 * 8; } while (items != lim); } #endif // USE_LZFIND_SATUR_SUB_256 #ifndef FORCE_LZFIND_SATUR_SUB_128 typedef void (Z7_FASTCALL *LZFIND_SATUR_SUB_CODE_FUNC)( UInt32 subValue, CLzRef *items, const CLzRef *lim); static LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub; #endif // FORCE_LZFIND_SATUR_SUB_128 #endif // USE_LZFIND_SATUR_SUB_128 // kEmptyHashValue must be zero // #define SASUB_32(i) { UInt32 v = items[i]; UInt32 m = v - subValue; if (v < subValue) m = kEmptyHashValue; items[i] = m; } #define SASUB_32(i) { UInt32 v = items[i]; if (v < subValue) v = subValue; items[i] = v - subValue; } #ifdef FORCE_LZFIND_SATUR_SUB_128 #define DEFAULT_SaturSub LzFind_SaturSub_128 #else #define DEFAULT_SaturSub LzFind_SaturSub_32 Z7_NO_INLINE static void Z7_FASTCALL LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SASUB_32(0) SASUB_32(1) items += 2; SASUB_32(0) SASUB_32(1) items += 2; SASUB_32(0) SASUB_32(1) items += 2; SASUB_32(0) SASUB_32(1) items += 2; } while (items != lim); } #endif Z7_NO_INLINE void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) { #define LZFIND_NORM_ALIGN_BLOCK_SIZE (1 << 7) Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (LZFIND_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--) { SASUB_32(0) items++; } { const size_t k_Align_Mask = (LZFIND_NORM_ALIGN_BLOCK_SIZE / 4 - 1); CLzRef *lim = items + (numItems & ~(size_t)k_Align_Mask); numItems &= k_Align_Mask; if (items != lim) { #if defined(USE_LZFIND_SATUR_SUB_128) && !defined(FORCE_LZFIND_SATUR_SUB_128) if (g_LzFind_SaturSub) g_LzFind_SaturSub(subValue, items, lim); else #endif DEFAULT_SaturSub(subValue, items, lim); } items = lim; } Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0; numItems--) { SASUB_32(0) items++; } } // call MatchFinder_CheckLimits() only after (p->pos++) update Z7_NO_INLINE static void MatchFinder_CheckLimits(CMatchFinder *p) { if (// !p->streamEndWasReached && p->result == SZ_OK && p->keepSizeAfter == GET_AVAIL_BYTES(p)) { // we try to read only in exact state (p->keepSizeAfter == GET_AVAIL_BYTES(p)) if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } if (p->pos == kMaxValForNormalize) if (GET_AVAIL_BYTES(p) >= p->numHashBytes) // optional optimization for last bytes of data. /* if we disable normalization for last bytes of data, and if (data_size == 4 GiB), we don't call wastfull normalization, but (pos) will be wrapped over Zero (0) in that case. And we cannot resume later to normal operation */ { // MatchFinder_Normalize(p); /* after normalization we need (p->pos >= p->historySize + 1); */ /* we can reduce subValue to aligned value, if want to keep alignment of (p->pos) and (p->buffer) for speculated accesses. */ const UInt32 subValue = (p->pos - p->historySize - 1) /* & ~(UInt32)(kNormalizeAlign - 1) */; // const UInt32 subValue = (1 << 15); // for debug // printf("\nMatchFinder_Normalize() subValue == 0x%x\n", subValue); MatchFinder_REDUCE_OFFSETS(p, subValue) MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashMask + 1 + p->fixedHashSize); { size_t numSonRefs = p->cyclicBufferSize; if (p->btMode) numSonRefs <<= 1; MatchFinder_Normalize3(subValue, p->son, numSonRefs); } } if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } /* (lenLimit > maxLen) */ Z7_FORCE_INLINE static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *d, unsigned maxLen) { /* son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return d; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { maxLen = len; *d++ = len; *d++ = delta - 1; if (len == lenLimit) return d; } } } } */ const Byte *lim = cur + lenLimit; son[_cyclicBufferPos] = curMatch; do { UInt32 delta; if (curMatch == 0) break; // if (curMatch2 >= curMatch) return NULL; delta = pos - curMatch; if (delta >= _cyclicBufferSize) break; { ptrdiff_t diff; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; diff = (ptrdiff_t)0 - (ptrdiff_t)delta; if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) { const Byte *c = cur; while (*c == c[diff]) { if (++c == lim) { d[0] = (UInt32)(lim - cur); d[1] = delta - 1; return d + 2; } } { const unsigned len = (unsigned)(c - cur); if (maxLen < len) { maxLen = len; d[0] = (UInt32)len; d[1] = delta - 1; d += 2; } } } } } while (--cutValue); return d; } Z7_FORCE_INLINE UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *d, UInt32 maxLen) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; UInt32 cmCheck; // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } cmCheck = (UInt32)(pos - _cyclicBufferSize); if ((UInt32)pos <= _cyclicBufferSize) cmCheck = 0; if (cmCheck < curMatch) do { const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; unsigned len = (len0 < len1 ? len0 : len1); const UInt32 pair0 = pair[0]; if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { maxLen = (UInt32)len; *d++ = (UInt32)len; *d++ = delta - 1; if (len == lenLimit) { *ptr1 = pair0; *ptr0 = pair[1]; return d; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; // const UInt32 curMatch2 = pair[1]; // if (curMatch2 >= curMatch) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } // curMatch = curMatch2; curMatch = pair[1]; ptr1 = pair + 1; len1 = len; } else { *ptr0 = curMatch; curMatch = pair[0]; ptr0 = pair; len0 = len; } } } while(--cutValue && cmCheck < curMatch); *ptr0 = *ptr1 = kEmptyHashValue; return d; } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; UInt32 cmCheck; cmCheck = (UInt32)(pos - _cyclicBufferSize); if ((UInt32)pos <= _cyclicBufferSize) cmCheck = 0; if (// curMatch >= pos || // failure cmCheck < curMatch) do { const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; unsigned len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; curMatch = pair[1]; ptr1 = pair + 1; len1 = len; } else { *ptr0 = curMatch; curMatch = pair[0]; ptr0 = pair; len0 = len; } } } while(--cutValue && cmCheck < curMatch); *ptr0 = *ptr1 = kEmptyHashValue; return; } #define MOVE_POS \ p->cyclicBufferPos++; \ p->buffer++; \ { const UInt32 pos1 = p->pos + 1; \ p->pos = pos1; \ if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } #define MOVE_POS_RET MOVE_POS return distances; Z7_NO_INLINE static void MatchFinder_MovePos(CMatchFinder *p) { /* we go here at the end of stream data, when (avail < num_hash_bytes) We don't update sons[cyclicBufferPos << btMode]. So (sons) record will contain junk. And we cannot resume match searching to normal operation, even if we will provide more input data in buffer. p->sons[p->cyclicBufferPos << p->btMode] = 0; // kEmptyHashValue if (p->btMode) p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0; // kEmptyHashValue */ MOVE_POS } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 hv; const Byte *cur; UInt32 curMatch; \ UInt32 lenLimit = p->lenLimit; \ if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; } \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) #define SKIP_HEADER(minLen) \ do { GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, \ p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define SKIP_FOOTER \ SkipMatchesSpec(MF_PARAMS(p)); \ MOVE_POS \ } while (--num); #define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ distances = func(MF_PARAMS(p), distances, (UInt32)_maxLen_); \ MOVE_POS_RET #define GET_MATCHES_FOOTER_BT(_maxLen_) \ GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) #define GET_MATCHES_FOOTER_HC(_maxLen_) \ GET_MATCHES_FOOTER_BASE(_maxLen_, Hc_GetMatchesSpec) #define UPDATE_maxLen { \ const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)d2; \ const Byte *c = cur + maxLen; \ const Byte *lim = cur + lenLimit; \ for (; c != lim; c++) if (*(c + diff) != *c) break; \ maxLen = (unsigned)(c - cur); } static UInt32* Bt2_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; GET_MATCHES_HEADER(2) HASH2_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_BT(1) } UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { GET_MATCHES_HEADER(3) HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_BT(2) } #define SET_mmm \ mmm = p->cyclicBufferSize; \ if (pos < mmm) \ mmm = pos; static UInt32* Bt3_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; UInt32 mmm; UInt32 h2, d2, pos; unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(3) HASH3_CALC hash = p->hash; pos = p->pos; d2 = pos - hash[h2]; curMatch = (hash + kFix3HashSize)[hv]; hash[h2] = pos; (hash + kFix3HashSize)[hv] = pos; SET_mmm maxLen = 2; if (d2 < mmm && *(cur - d2) == *cur) { UPDATE_maxLen distances[0] = (UInt32)maxLen; distances[1] = d2 - 1; distances += 2; if (maxLen == lenLimit) { SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET } } GET_MATCHES_FOOTER_BT(maxLen) } static UInt32* Bt4_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; UInt32 mmm; UInt32 h2, h3, d2, d3, pos; unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) HASH4_CALC hash = p->hash; pos = p->pos; d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; (hash + kFix4HashSize)[hv] = pos; SET_mmm maxLen = 3; for (;;) { if (d2 < mmm && *(cur - d2) == *cur) { distances[0] = 2; distances[1] = d2 - 1; distances += 2; if (*(cur - d2 + 2) == cur[2]) { // distances[-2] = 3; } else if (d3 < mmm && *(cur - d3) == *cur) { d2 = d3; distances[1] = d3 - 1; distances += 2; } else break; } else if (d3 < mmm && *(cur - d3) == *cur) { d2 = d3; distances[1] = d3 - 1; distances += 2; } else break; UPDATE_maxLen distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET } break; } GET_MATCHES_FOOTER_BT(maxLen) } static UInt32* Bt5_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; UInt32 mmm; UInt32 h2, h3, d2, d3, pos; unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(5) HASH5_CALC hash = p->hash; pos = p->pos; d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; SET_mmm maxLen = 4; for (;;) { if (d2 < mmm && *(cur - d2) == *cur) { distances[0] = 2; distances[1] = d2 - 1; distances += 2; if (*(cur - d2 + 2) == cur[2]) { } else if (d3 < mmm && *(cur - d3) == *cur) { distances[1] = d3 - 1; distances += 2; d2 = d3; } else break; } else if (d3 < mmm && *(cur - d3) == *cur) { distances[1] = d3 - 1; distances += 2; d2 = d3; } else break; distances[-2] = 3; if (*(cur - d2 + 3) != cur[3]) break; UPDATE_maxLen distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET } break; } GET_MATCHES_FOOTER_BT(maxLen) } static UInt32* Hc4_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; UInt32 mmm; UInt32 h2, h3, d2, d3, pos; unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) HASH4_CALC hash = p->hash; pos = p->pos; d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; (hash + kFix4HashSize)[hv] = pos; SET_mmm maxLen = 3; for (;;) { if (d2 < mmm && *(cur - d2) == *cur) { distances[0] = 2; distances[1] = d2 - 1; distances += 2; if (*(cur - d2 + 2) == cur[2]) { // distances[-2] = 3; } else if (d3 < mmm && *(cur - d3) == *cur) { d2 = d3; distances[1] = d3 - 1; distances += 2; } else break; } else if (d3 < mmm && *(cur - d3) == *cur) { d2 = d3; distances[1] = d3 - 1; distances += 2; } else break; UPDATE_maxLen distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET } break; } GET_MATCHES_FOOTER_HC(maxLen) } static UInt32 * Hc5_MatchFinder_GetMatches(void *_p, UInt32 *distances) { CMatchFinder *p = (CMatchFinder *)_p; UInt32 mmm; UInt32 h2, h3, d2, d3, pos; unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(5) HASH5_CALC hash = p->hash; pos = p->pos; d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; SET_mmm maxLen = 4; for (;;) { if (d2 < mmm && *(cur - d2) == *cur) { distances[0] = 2; distances[1] = d2 - 1; distances += 2; if (*(cur - d2 + 2) == cur[2]) { } else if (d3 < mmm && *(cur - d3) == *cur) { distances[1] = d3 - 1; distances += 2; d2 = d3; } else break; } else if (d3 < mmm && *(cur - d3) == *cur) { distances[1] = d3 - 1; distances += 2; d2 = d3; } else break; distances[-2] = 3; if (*(cur - d2 + 3) != cur[3]) break; UPDATE_maxLen distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET } break; } GET_MATCHES_FOOTER_HC(maxLen) } UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { GET_MATCHES_HEADER(3) HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; GET_MATCHES_FOOTER_HC(2) } static void Bt2_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; SKIP_HEADER(2) { HASH2_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; } SKIP_FOOTER } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { SKIP_HEADER(3) { HASH_ZIP_CALC curMatch = p->hash[hv]; p->hash[hv] = p->pos; } SKIP_FOOTER } static void Bt3_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; SKIP_HEADER(3) { UInt32 h2; UInt32 *hash; HASH3_CALC hash = p->hash; curMatch = (hash + kFix3HashSize)[hv]; hash[h2] = (hash + kFix3HashSize)[hv] = p->pos; } SKIP_FOOTER } static void Bt4_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; SKIP_HEADER(4) { UInt32 h2, h3; UInt32 *hash; HASH4_CALC hash = p->hash; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = (hash + kFix4HashSize)[hv] = p->pos; } SKIP_FOOTER } static void Bt5_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; SKIP_HEADER(5) { UInt32 h2, h3; UInt32 *hash; HASH5_CALC hash = p->hash; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = // (hash + kFix4HashSize)[h4] = (hash + kFix5HashSize)[hv] = p->pos; } SKIP_FOOTER } #define HC_SKIP_HEADER(minLen) \ do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \ const Byte *cur; \ UInt32 *hash; \ UInt32 *son; \ UInt32 pos = p->pos; \ UInt32 num2 = num; \ /* (p->pos == p->posLimit) is not allowed here !!! */ \ { const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \ num -= num2; \ { const UInt32 cycPos = p->cyclicBufferPos; \ son = p->son + cycPos; \ p->cyclicBufferPos = cycPos + num2; } \ cur = p->buffer; \ hash = p->hash; \ do { \ UInt32 curMatch; \ UInt32 hv; #define HC_SKIP_FOOTER \ cur++; pos++; *son++ = curMatch; \ } while (--num2); \ p->buffer = cur; \ p->pos = pos; \ if (pos == p->posLimit) MatchFinder_CheckLimits(p); \ }} while(num); \ static void Hc4_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; HC_SKIP_HEADER(4) UInt32 h2, h3; HASH4_CALC curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = (hash + kFix4HashSize)[hv] = pos; HC_SKIP_FOOTER } static void Hc5_MatchFinder_Skip(void *_p, UInt32 num) { CMatchFinder *p = (CMatchFinder *)_p; HC_SKIP_HEADER(5) UInt32 h2, h3; HASH5_CALC curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = // (hash + kFix4HashSize)[h4] = (hash + kFix5HashSize)[hv] = pos; HC_SKIP_FOOTER } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { HC_SKIP_HEADER(3) HASH_ZIP_CALC curMatch = hash[hv]; hash[hv] = pos; HC_SKIP_FOOTER } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) { vTable->Init = MatchFinder_Init; vTable->GetNumAvailableBytes = MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { if (p->numHashBytes <= 4) { vTable->GetMatches = Hc4_MatchFinder_GetMatches; vTable->Skip = Hc4_MatchFinder_Skip; } else { vTable->GetMatches = Hc5_MatchFinder_GetMatches; vTable->Skip = Hc5_MatchFinder_Skip; } } else if (p->numHashBytes == 2) { vTable->GetMatches = Bt2_MatchFinder_GetMatches; vTable->Skip = Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = Bt3_MatchFinder_GetMatches; vTable->Skip = Bt3_MatchFinder_Skip; } else if (p->numHashBytes == 4) { vTable->GetMatches = Bt4_MatchFinder_GetMatches; vTable->Skip = Bt4_MatchFinder_Skip; } else { vTable->GetMatches = Bt5_MatchFinder_GetMatches; vTable->Skip = Bt5_MatchFinder_Skip; } } void LzFindPrepare(void) { #ifndef FORCE_LZFIND_SATUR_SUB_128 #ifdef USE_LZFIND_SATUR_SUB_128 LZFIND_SATUR_SUB_CODE_FUNC f = NULL; #ifdef MY_CPU_ARM_OR_ARM64 { if (CPU_IsSupported_NEON()) { // #pragma message ("=== LzFind NEON") PRF(printf("\n=== LzFind NEON\n")); f = LzFind_SaturSub_128; } // f = 0; // for debug } #else // MY_CPU_ARM_OR_ARM64 if (CPU_IsSupported_SSE41()) { // #pragma message ("=== LzFind SSE41") PRF(printf("\n=== LzFind SSE41\n")); f = LzFind_SaturSub_128; #ifdef USE_LZFIND_SATUR_SUB_256 if (CPU_IsSupported_AVX2()) { // #pragma message ("=== LzFind AVX2") PRF(printf("\n=== LzFind AVX2\n")); f = LzFind_SaturSub_256; } #endif } #endif // MY_CPU_ARM_OR_ARM64 g_LzFind_SaturSub = f; #endif // USE_LZFIND_SATUR_SUB_128 #endif // FORCE_LZFIND_SATUR_SUB_128 } #undef MOVE_POS #undef MOVE_POS_RET #undef PRF tmp41wklro_/C/LzFind.h0000444000175000001440000001076314553463320015676 0ustar nabijaczleweliusers/* LzFind.h -- Match finder for LZ algorithms 2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZ_FIND_H #define ZIP7_INC_LZ_FIND_H #include "7zTypes.h" EXTERN_C_BEGIN typedef UInt32 CLzRef; typedef struct { const Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */ UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ Byte streamEndWasReached; Byte btMode; Byte bigHash; Byte directInput; UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufBase; ISeqInStreamPtr stream; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; size_t directInputRem; UInt32 historySize; UInt32 fixedHashSize; Byte numHashBytes_Min; Byte numHashOutBits; Byte _pad2_[2]; SRes result; UInt32 crc[256]; size_t numRefs; UInt64 expectedDataSize; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((p)->streamPos - (p)->pos)) /* #define Inline_MatchFinder_IsFinishedOK(p) \ ((p)->streamEndWasReached \ && (p)->streamPos == (p)->pos \ && (!(p)->directInput || (p)->directInputRem == 0)) */ int MatchFinder_NeedMove(CMatchFinder *p); /* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */ void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* (directInput = 0) is default value. It's required to provide correct (directInput) value before calling MatchFinder_Create(). You can set (directInput) by any of the following calls: - MatchFinder_SET_DIRECT_INPUT_BUF() - MatchFinder_SET_STREAM() - MatchFinder_SET_STREAM_MODE() */ #define MatchFinder_SET_DIRECT_INPUT_BUF(p, _src_, _srcLen_) { \ (p)->stream = NULL; \ (p)->directInput = 1; \ (p)->buffer = (_src_); \ (p)->directInputRem = (_srcLen_); } /* #define MatchFinder_SET_STREAM_MODE(p) { \ (p)->directInput = 0; } */ #define MatchFinder_SET_STREAM(p, _stream_) { \ (p)->stream = _stream_; \ (p)->directInput = 0; } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); /* #define MatchFinder_INIT_POS(p, val) \ (p)->pos = (val); \ (p)->streamPos = (val); */ // void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); #define MatchFinder_REDUCE_OFFSETS(p, subValue) \ (p)->pos -= (subValue); \ (p)->streamPos -= (subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct { Mf_Init_Func Init; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder2; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable); void MatchFinder_Init_LowHash(CMatchFinder *p); void MatchFinder_Init_HighHash(CMatchFinder *p); void MatchFinder_Init_4(CMatchFinder *p); // void MatchFinder_Init(CMatchFinder *p); void MatchFinder_Init(void *p); UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void LzFindPrepare(void); EXTERN_C_END #endif tmp41wklro_/C/LzFindMt.c0000444000175000001440000011154414553472340016173 0ustar nabijaczleweliusers/* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2024-01-22 : Igor Pavlov : Public domain */ #include "Precomp.h" // #include #include "CpuArch.h" #include "LzHash.h" #include "LzFindMt.h" // #define LOG_ITERS // #define LOG_THREAD #ifdef LOG_THREAD #include #define PRF(x) x #else #define PRF(x) #endif #ifdef LOG_ITERS #include extern UInt64 g_NumIters_Tree; extern UInt64 g_NumIters_Loop; extern UInt64 g_NumIters_Bytes; #define LOG_ITER(x) x #else #define LOG_ITER(x) #endif #define kMtHashBlockSize ((UInt32)1 << 17) #define kMtHashNumBlocks (1 << 1) #define GET_HASH_BLOCK_OFFSET(i) (((i) & (kMtHashNumBlocks - 1)) * kMtHashBlockSize) #define kMtBtBlockSize ((UInt32)1 << 16) #define kMtBtNumBlocks (1 << 4) #define GET_BT_BLOCK_OFFSET(i) (((i) & (kMtBtNumBlocks - 1)) * (size_t)kMtBtBlockSize) /* HASH functions: We use raw 8/16 bits from a[1] and a[2], xored with crc(a[0]) and crc(a[3]). We check a[0], a[3] only. We don't need to compare a[1] and a[2] in matches. our crc() function provides one-to-one correspondence for low 8-bit values: (crc[0...0xFF] & 0xFF) <-> [0...0xFF] */ #define MF(mt) ((mt)->MatchFinder) #define MF_CRC (p->crc) // #define MF(mt) (&(mt)->MatchFinder) // #define MF_CRC (p->MatchFinder.crc) #define MT_HASH2_CALC \ h2 = (MF_CRC[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = MF_CRC[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } /* #define MT_HASH3_CALC__NO_2 { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ h2 = temp & (kHash2Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \ h3 = temp & (kHash3Size - 1); \ h4 = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hash4Mask; } // (kHash4Size - 1); */ Z7_NO_INLINE static void MtSync_Construct(CMtSync *p) { p->affinity = 0; p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_CONSTRUCT(&p->thread) Event_Construct(&p->canStart); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } // #define DEBUG_BUFFER_LOCK // define it to debug lock state #ifdef DEBUG_BUFFER_LOCK #include #define BUFFER_MUST_BE_LOCKED(p) if (!(p)->csWasEntered) exit(1); #define BUFFER_MUST_BE_UNLOCKED(p) if ( (p)->csWasEntered) exit(1); #else #define BUFFER_MUST_BE_LOCKED(p) #define BUFFER_MUST_BE_UNLOCKED(p) #endif #define LOCK_BUFFER(p) { \ BUFFER_MUST_BE_UNLOCKED(p); \ CriticalSection_Enter(&(p)->cs); \ (p)->csWasEntered = True; } #define UNLOCK_BUFFER(p) { \ BUFFER_MUST_BE_LOCKED(p); \ CriticalSection_Leave(&(p)->cs); \ (p)->csWasEntered = False; } Z7_NO_INLINE static UInt32 MtSync_GetNextBlock(CMtSync *p) { UInt32 numBlocks = 0; if (p->needStart) { BUFFER_MUST_BE_UNLOCKED(p) p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStopped); Event_Set(&p->canStart); } else { UNLOCK_BUFFER(p) // we free current block numBlocks = p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } // buffer is UNLOCKED here Semaphore_Wait(&p->filledSemaphore); LOCK_BUFFER(p) return numBlocks; } /* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */ Z7_NO_INLINE static void MtSync_StopWriting(CMtSync *p) { if (!Thread_WasCreated(&p->thread) || p->needStart) return; PRF(printf("\nMtSync_StopWriting %p\n", p)); if (p->csWasEntered) { /* we don't use buffer in this thread after StopWriting(). So we UNLOCK buffer. And we restore default UNLOCKED state for stopped thread */ UNLOCK_BUFFER(p) } /* We send (p->stopWriting) message and release freeSemaphore to free current block. So the thread will see (p->stopWriting) at some iteration after Wait(freeSemaphore). The thread doesn't need to fill all avail free blocks, so we can get fast thread stop. */ p->stopWriting = True; Semaphore_Release1(&p->freeSemaphore); // check semaphore count !!! PRF(printf("\nMtSync_StopWriting %p : Event_Wait(&p->wasStopped)\n", p)); Event_Wait(&p->wasStopped); PRF(printf("\nMtSync_StopWriting %p : Event_Wait() finsihed\n", p)); /* 21.03 : we don't restore samaphore counters here. We will recreate and reinit samaphores in next start */ p->needStart = True; } Z7_NO_INLINE static void MtSync_Destruct(CMtSync *p) { PRF(printf("\nMtSync_Destruct %p\n", p)); if (Thread_WasCreated(&p->thread)) { /* we want thread to be in Stopped state before sending EXIT command. note: stop(btSync) will stop (htSync) also */ MtSync_StopWriting(p); /* thread in Stopped state here : (p->needStart == true) */ p->exit = True; // if (p->needStart) // it's (true) Event_Set(&p->canStart); // we send EXIT command to thread Thread_Wait_Close(&p->thread); // we wait thread finishing } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } p->csWasEntered = False; Event_Close(&p->canStart); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } // #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } // we want to get real system error codes here instead of SZ_ERROR_THREAD #define RINOK_THREAD(x) RINOK_WRes(x) // call it before each new file (when new starting is required): Z7_NO_INLINE static SRes MtSync_Init(CMtSync *p, UInt32 numBlocks) { WRes wres; // BUFFER_MUST_BE_UNLOCKED(p) if (!p->needStart || p->csWasEntered) return SZ_ERROR_FAIL; wres = Semaphore_OptCreateInit(&p->freeSemaphore, numBlocks, numBlocks); if (wres == 0) wres = Semaphore_OptCreateInit(&p->filledSemaphore, 0, numBlocks); return MY_SRes_HRESULT_FROM_WRes(wres); } static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) { WRes wres; if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)) p->csWasInitialized = True; p->csWasEntered = False; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)) RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)) p->needStart = True; p->exit = True; /* p->exit is unused before (canStart) Event. But in case of some unexpected code failure we will get fast exit from thread */ // return ERROR_TOO_MANY_POSTS; // for debug // return EINVAL; // for debug if (p->affinity != 0) wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); else wres = Thread_Create(&p->thread, startAddress, obj); RINOK_THREAD(wres) p->wasCreated = True; return SZ_OK; } Z7_NO_INLINE static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) { const WRes wres = MtSync_Create_WRes(p, startAddress, obj); if (wres == 0) return 0; MtSync_Destruct(p); return MY_SRes_HRESULT_FROM_WRes(wres); } // ---------- HASH THREAD ---------- #define kMtMaxValForNormalize 0xFFFFFFFF // #define kMtMaxValForNormalize ((1 << 21)) // for debug // #define kNormalizeAlign (1 << 7) // alignment for speculated accesses #ifdef MY_CPU_LE_UNALIGN #define GetUi24hi_from32(p) ((UInt32)GetUi32(p) >> 8) #else #define GetUi24hi_from32(p) ((p)[1] ^ ((UInt32)(p)[2] << 8) ^ ((UInt32)(p)[3] << 16)) #endif #define GetHeads_DECL(name) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) #define GetHeads_LOOP(v) \ for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); \ p++; \ *heads++ = pos - hash[value]; \ hash[value] = pos++; } #define DEF_GetHeads2(name, v, action) \ GetHeads_DECL(name) { action \ GetHeads_LOOP(v) } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, GetUi16(p), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) DEF_GetHeads(3, (crc[p[0]] ^ GetUi16(p + 1)) & hashMask) DEF_GetHeads2(3b, GetUi16(p) ^ ((UInt32)(p)[2] << 16), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) // BT3 is not good for crc collisions for big hashMask values. /* GetHeads_DECL(3b) { UNUSED_VAR(hashMask); UNUSED_VAR(crc); { const Byte *pLim = p + numHeads; if (numHeads == 0) return; pLim--; while (p < pLim) { UInt32 v1 = GetUi32(p); UInt32 v0 = v1 & 0xFFFFFF; UInt32 h0, h1; p += 2; v1 >>= 8; h0 = hash[v0]; hash[v0] = pos; heads[0] = pos - h0; pos++; h1 = hash[v1]; hash[v1] = pos; heads[1] = pos - h1; pos++; heads += 2; } if (p == pLim) { UInt32 v0 = GetUi16(p) ^ ((UInt32)(p)[2] << 16); *heads = pos - hash[v0]; hash[v0] = pos; } } } */ /* GetHeads_DECL(4) { unsigned sh = 0; UNUSED_VAR(crc) while ((hashMask & 0x80000000) == 0) { hashMask <<= 1; sh++; } GetHeads_LOOP((GetUi32(p) * 0xa54a1) >> sh) } #define GetHeads4b GetHeads4 */ #define USE_GetHeads_LOCAL_CRC #ifdef USE_GetHeads_LOCAL_CRC GetHeads_DECL(4) { UInt32 crc0[256]; UInt32 crc1[256]; { unsigned i; for (i = 0; i < 256; i++) { UInt32 v = crc[i]; crc0[i] = v & hashMask; crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; // crc1[i] = rotlFixed(v, 8) & hashMask; } } GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ (UInt32)GetUi16(p+1)) } GetHeads_DECL(4b) { UInt32 crc0[256]; { unsigned i; for (i = 0; i < 256; i++) crc0[i] = crc[i] & hashMask; } GetHeads_LOOP(crc0[p[0]] ^ GetUi24hi_from32(p)) } GetHeads_DECL(5) { UInt32 crc0[256]; UInt32 crc1[256]; UInt32 crc2[256]; { unsigned i; for (i = 0; i < 256; i++) { UInt32 v = crc[i]; crc0[i] = v & hashMask; crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; crc2[i] = (v << kLzHash_CrcShift_2) & hashMask; } } GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ crc2[p[4]] ^ (UInt32)GetUi16(p+1)) } GetHeads_DECL(5b) { UInt32 crc0[256]; UInt32 crc1[256]; { unsigned i; for (i = 0; i < 256; i++) { UInt32 v = crc[i]; crc0[i] = v & hashMask; crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; } } GetHeads_LOOP(crc0[p[0]] ^ crc1[p[4]] ^ GetUi24hi_from32(p)) } #else DEF_GetHeads(4, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (UInt32)GetUi16(p+1)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ GetUi24hi_from32(p)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (crc[p[4]] << kLzHash_CrcShift_2) ^ (UInt32)GetUi16(p + 1)) & hashMask) DEF_GetHeads(5b, (crc[p[0]] ^ (crc[p[4]] << kLzHash_CrcShift_1) ^ GetUi24hi_from32(p)) & hashMask) #endif static void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; PRF(printf("\nHashThreadFunc\n")); for (;;) { UInt32 blockIndex = 0; PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart)\n")); Event_Wait(&p->canStart); PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart) : after \n")); if (p->exit) { PRF(printf("\nHashThreadFunc : exit \n")); return; } MatchFinder_Init_HighHash(MF(mt)); for (;;) { PRF(printf("Hash thread block = %d pos = %d\n", (unsigned)blockIndex, mt->MatchFinder->pos)); { CMatchFinder *mf = MF(mt); if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf); ptrdiff_t offset; MatchFinder_MoveBlock(mf); offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= offset; mt->buffer -= offset; } CriticalSection_Leave(&mt->hashSync.cs); CriticalSection_Leave(&mt->btSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); if (p->exit) // exit is unexpected here. But we check it here for some failure case return; // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) if (p->stopWriting) break; MatchFinder_ReadIfRequired(mf); { UInt32 *heads = mt->hashBuf + GET_HASH_BLOCK_OFFSET(blockIndex++); UInt32 num = Inline_MatchFinder_GetNumAvailableBytes(mf); heads[0] = 2; heads[1] = num; /* heads[1] contains the number of avail bytes: if (avail < mf->numHashBytes) : { it means that stream was finished HASH_THREAD and BT_TREAD must move position for heads[1] (avail) bytes. HASH_THREAD doesn't stop, HASH_THREAD fills only the header (2 numbers) for all next blocks: {2, NumHashBytes - 1}, {2,0}, {2,0}, ... , {2,0} } else { HASH_THREAD and BT_TREAD must move position for (heads[0] - 2) bytes; } */ if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; if (mf->pos > (UInt32)kMtMaxValForNormalize - num) { const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); MatchFinder_REDUCE_OFFSETS(mf, subValue) MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); } heads[0] = 2 + num; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); } mf->pos += num; // wrap over zero is allowed at the end of stream mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } // for() processing end // p->numBlocks_Sent = blockIndex; Event_Set(&p->wasStopped); } // for() thread end } // ---------- BT THREAD ---------- /* we use one variable instead of two (cyclicBufferPos == pos) before CyclicBuf wrap. here we define fixed offset of (p->pos) from (p->cyclicBufferPos) */ #define CYC_TO_POS_OFFSET 0 // #define CYC_TO_POS_OFFSET 1 // for debug #define MFMT_GM_INLINE #ifdef MFMT_GM_INLINE /* we use size_t for (pos) instead of UInt32 to eliminate "movsx" BUG in old MSVC x64 compiler. */ UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes); #endif static void BtGetMatches(CMatchFinderMt *p, UInt32 *d) { UInt32 numProcessed = 0; UInt32 curPos = 2; /* GetMatchesSpec() functions don't create (len = 1) in [len, dist] match pairs, if (p->numHashBytes >= 2) Also we suppose here that (matchMaxLen >= 2). So the following code for (reserve) is not required UInt32 reserve = (p->matchMaxLen * 2); const UInt32 kNumHashBytes_Max = 5; // BT_HASH_BYTES_MAX if (reserve < kNumHashBytes_Max - 1) reserve = kNumHashBytes_Max - 1; const UInt32 limit = kMtBtBlockSize - (reserve); */ const UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); d[1] = p->hashNumAvail; if (p->failure_BT) { // printf("\n == 1 BtGetMatches() p->failure_BT\n"); d[0] = 0; // d[1] = 0; return; } while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { // MatchFinderMt_GetNextBlock_Hash(p); UInt32 avail; { const UInt32 bi = MtSync_GetNextBlock(&p->hashSync); const UInt32 k = GET_HASH_BLOCK_OFFSET(bi); const UInt32 *h = p->hashBuf + k; avail = h[1]; p->hashBufPosLimit = k + h[0]; p->hashNumAvail = avail; p->hashBufPos = k + 2; } { /* we must prevent UInt32 overflow for avail total value, if avail was increased with new hash block */ UInt32 availSum = numProcessed + avail; if (availSum < numProcessed) availSum = (UInt32)(Int32)-1; d[1] = availSum; } if (avail >= p->numHashBytes) continue; // if (p->hashBufPos != p->hashBufPosLimit) exit(1); /* (avail < p->numHashBytes) It means that stream was finished. And (avail) - is a number of remaining bytes, we fill (d) for (avail) bytes for LZ_THREAD (receiver). but we don't update (p->pos) and (p->cyclicBufferPos) here in BT_THREAD */ /* here we suppose that we have space enough: (kMtBtBlockSize - curPos >= p->hashNumAvail) */ p->hashNumAvail = 0; d[0] = curPos + avail; d += curPos; for (; avail != 0; avail--) *d++ = 0; return; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; UInt32 lenLimit = p->matchMaxLen; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } if (pos > (UInt32)kMtMaxValForNormalize - size) { const UInt32 subValue = (pos - p->cyclicBufferSize); // & ~(UInt32)(kNormalizeAlign - 1); pos -= subValue; p->pos = pos; MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = d + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes = pos; const UInt32 *d_end; { d_end = GetMatchesSpecN_2( p->buffer + lenLimit - 1, pos, p->buffer, p->son, p->cutValue, d + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, d + limit, p->hashBuf + p->hashBufPos + size, cyclicBufferPos, p->cyclicBufferSize, &posRes); } { if (!d_end) { // printf("\n == 2 BtGetMatches() p->failure_BT\n"); // internal data failure p->failure_BT = True; d[0] = 0; // d[1] = 0; return; } } curPos = (UInt32)(d_end - d); { const UInt32 processed = posRes - pos; pos = posRes; p->hashBufPos += processed; cyclicBufferPos += processed; p->buffer += processed; } } #endif { const UInt32 processed = pos - p->pos; numProcessed += processed; p->hashNumAvail -= processed; p->pos = pos; } if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } d[0] = curPos; } static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; BUFFER_MUST_BE_UNLOCKED(sync) if (!sync->needStart) { LOCK_BUFFER(sync) } BtGetMatches(p, p->btBuf + GET_BT_BLOCK_OFFSET(globalBlockIndex)); /* We suppose that we have called GetNextBlock() from start. So buffer is LOCKED */ UNLOCK_BUFFER(sync) } Z7_NO_INLINE static void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); for (;;) { PRF(printf(" BT thread block = %d pos = %d\n", (unsigned)blockIndex, mt->pos)); /* (p->exit == true) is possible after (p->canStart) at first loop iteration and is unexpected after more Wait(freeSemaphore) iterations */ if (p->exit) return; Semaphore_Wait(&p->freeSemaphore); // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) if (p->stopWriting) break; BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } // we stop HASH_THREAD here MtSync_StopWriting(&mt->hashSync); // p->numBlocks_Sent = blockIndex; Event_Set(&p->wasStopped); } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = NULL; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->hashBuf); p->hashBuf = NULL; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) { /* HASH_THREAD can use CriticalSection(s) btSync.cs and hashSync.cs. So we must be sure that HASH_THREAD will not use CriticalSection(s) after deleting CriticalSection here. we call ReleaseStream(p) that calls StopWriting(btSync) that calls StopWriting(hashSync), if it's required to stop HASH_THREAD. after StopWriting() it's safe to destruct MtSync(s) in any order */ MatchFinderMt_ReleaseStream(p); MtSync_Destruct(&p->btSync); MtSync_Destruct(&p->hashSync); LOG_ITER( printf("\nTree %9d * %7d iter = %9d = sum : bytes = %9d\n", (UInt32)(g_NumIters_Tree / 1000), (UInt32)(((UInt64)g_NumIters_Loop * 1000) / (g_NumIters_Tree + 1)), (UInt32)(g_NumIters_Loop / 1000), (UInt32)(g_NumIters_Bytes / 1000) )); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static THREAD_FUNC_DECL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static THREAD_FUNC_DECL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; unsigned i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)0; if (allocaDummy[0] == 0) BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { CMatchFinder *mf = MF(p); p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (!p->hashBuf) { p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, ((size_t)kHashBufferSize + (size_t)kBtBufferSize) * sizeof(UInt32)); if (!p->hashBuf) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)) RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)) return SZ_OK; } SRes MatchFinderMt_InitMt(CMatchFinderMt *p) { RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)) return MtSync_Init(&p->btSync, kMtBtNumBlocks); } static void MatchFinderMt_Init(void *_p) { CMatchFinderMt *p = (CMatchFinderMt *)_p; CMatchFinder *mf = MF(p); p->btBufPos = p->btBufPosLimit = NULL; p->hashBufPos = p->hashBufPosLimit = 0; p->hashNumAvail = 0; // 21.03 p->failure_BT = False; /* Init without data reading. We don't want to read data in this thread */ MatchFinder_Init_4(mf); MatchFinder_Init_LowHash(mf); p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->failure_LZ_BT = False; // p->failure_LZ_LZ = False; p->lzPos = 1; // optimal smallest value // 0; // for debug: ignores match to start // kNormalizeAlign; // for debug p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; // p->hash4Mask = mf->hash4Mask; p->crc = mf->crc; // memcpy(p->crc, mf->crc, sizeof(mf->crc)); p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; /* (mf->pos) and (mf->streamPos) were already initialized to 1 in MatchFinder_Init_4() */ // mf->streamPos = mf->pos = 1; // optimal smallest value // 0; // for debug: ignores match to start // kNormalizeAlign; // for debug /* we must init (p->pos = mf->pos) for BT, because BT code needs (p->pos == delta_value_for_empty_hash_record == mf->pos) */ p->pos = mf->pos; // do not change it p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); p->cyclicBufferSize = mf->cyclicBufferSize; p->buffer = mf->buffer; p->cutValue = mf->cutValue; // p->son[0] = p->son[1] = 0; // unused: to init skipped record for speculated accesses. } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { // Sleep(1); // for debug MtSync_StopWriting(&p->btSync); // Sleep(200); // for debug /* p->MatchFinder->ReleaseStream(); */ } Z7_NO_INLINE static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { if (p->failure_LZ_BT) p->btBufPos = p->failureBuf; else { const UInt32 bi = MtSync_GetNextBlock(&p->btSync); const UInt32 *bt = p->btBuf + GET_BT_BLOCK_OFFSET(bi); { const UInt32 numItems = bt[0]; p->btBufPosLimit = bt + numItems; p->btNumAvailBytes = bt[1]; p->btBufPos = bt + 2; if (numItems < 2 || numItems > kMtBtBlockSize) { p->failureBuf[0] = 0; p->btBufPos = p->failureBuf; p->btBufPosLimit = p->failureBuf + 1; p->failure_LZ_BT = True; // p->btNumAvailBytes = 0; /* we don't want to decrease AvailBytes, that was load before. that can be unxepected for the code that have loaded anopther value before */ } } if (p->lzPos >= (UInt32)kMtMaxValForNormalize - (UInt32)kMtBtBlockSize) { /* we don't check (lzPos) over exact avail bytes in (btBuf). (fixedHashSize) is small, so normalization is fast */ const UInt32 subValue = (p->lzPos - p->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); p->lzPos -= subValue; MatchFinder_Normalize3(subValue, p->hash, p->fixedHashSize); } } return p->btNumAvailBytes; } static const Byte * MatchFinderMt_GetPointerToCurrentPos(void *_p) { CMatchFinderMt *p = (CMatchFinderMt *)_p; return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); static UInt32 MatchFinderMt_GetNumAvailableBytes(void *_p) { CMatchFinderMt *p = (CMatchFinderMt *)_p; if (p->btBufPos != p->btBufPosLimit) return p->btNumAvailBytes; return MatchFinderMt_GetNextBlock_Bt(p); } // #define CHECK_FAILURE_LZ(_match_, _pos_) if (_match_ >= _pos_) { p->failure_LZ_LZ = True; return d; } #define CHECK_FAILURE_LZ(_match_, _pos_) static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { UInt32 h2, c2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; const UInt32 m = p->lzPos; MT_HASH2_CALC c2 = hash[h2]; hash[h2] = m; if (c2 >= matchMinPos) { CHECK_FAILURE_LZ(c2, m) if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { *d++ = 2; *d++ = m - c2 - 1; } } return d; } static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { UInt32 h2, h3, c2, c3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; const UInt32 m = p->lzPos; MT_HASH3_CALC c2 = hash[h2]; c3 = (hash + kFix3HashSize)[h3]; hash[h2] = m; (hash + kFix3HashSize)[h3] = m; if (c2 >= matchMinPos) { CHECK_FAILURE_LZ(c2, m) if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { d[1] = m - c2 - 1; if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) { d[0] = 3; return d + 2; } d[0] = 2; d += 2; } } if (c3 >= matchMinPos) { CHECK_FAILURE_LZ(c3, m) if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) { *d++ = 3; *d++ = m - c3 - 1; } } return d; } #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; /* static UInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d) { const UInt32 *bt = p->btBufPos; const UInt32 len = *bt++; const UInt32 *btLim = bt + len; UInt32 matchMinPos; UInt32 avail = p->btNumAvailBytes - 1; p->btBufPos = btLim; { p->btNumAvailBytes = avail; #define BT_HASH_BYTES_MAX 5 matchMinPos = p->lzPos; if (len != 0) matchMinPos -= bt[1]; else if (avail < (BT_HASH_BYTES_MAX - 1) - 1) { INCREASE_LZ_POS return d; } else { const UInt32 hs = p->historySize; if (matchMinPos > hs) matchMinPos -= hs; else matchMinPos = 1; } } for (;;) { UInt32 h2, h3, c2, c3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 m = p->lzPos; MT_HASH3_CALC c2 = hash[h2]; c3 = (hash + kFix3HashSize)[h3]; hash[h2] = m; (hash + kFix3HashSize)[h3] = m; if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { d[1] = m - c2 - 1; if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) { d[0] = 3; d += 2; break; } // else { d[0] = 2; d += 2; } } if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) { *d++ = 3; *d++ = m - c3 - 1; } break; } if (len != 0) { do { const UInt32 v0 = bt[0]; const UInt32 v1 = bt[1]; bt += 2; d[0] = v0; d[1] = v1; d += 2; } while (bt != btLim); } INCREASE_LZ_POS return d; } */ static UInt32 * MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; const UInt32 m = p->lzPos; MT_HASH3_CALC // MT_HASH4_CALC c2 = hash[h2]; c3 = (hash + kFix3HashSize)[h3]; // c4 = (hash + kFix4HashSize)[h4]; hash[h2] = m; (hash + kFix3HashSize)[h3] = m; // (hash + kFix4HashSize)[h4] = m; // #define BT5_USE_H2 // #ifdef BT5_USE_H2 if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { d[1] = m - c2 - 1; if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) { // d[0] = (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) ? 4 : 3; // return d + 2; if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) { d[0] = 4; return d + 2; } d[0] = 3; d += 2; #ifdef BT5_USE_H4 if (c4 >= matchMinPos) if ( cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] ) { *d++ = 4; *d++ = m - c4 - 1; } #endif return d; } d[0] = 2; d += 2; } // #endif if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) { d[1] = m - c3 - 1; if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m + 3] == cur[3]) { d[0] = 4; return d + 2; } d[0] = 3; d += 2; } #ifdef BT5_USE_H4 if (c4 >= matchMinPos) if ( cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] ) { *d++ = 4; *d++ = m - c4 - 1; } #endif return d; } static UInt32 * MatchFinderMt2_GetMatches(void *_p, UInt32 *d) { CMatchFinderMt *p = (CMatchFinderMt *)_p; const UInt32 *bt = p->btBufPos; const UInt32 len = *bt++; const UInt32 *btLim = bt + len; p->btBufPos = btLim; p->btNumAvailBytes--; INCREASE_LZ_POS { while (bt != btLim) { const UInt32 v0 = bt[0]; const UInt32 v1 = bt[1]; bt += 2; d[0] = v0; d[1] = v1; d += 2; } } return d; } static UInt32 * MatchFinderMt_GetMatches(void *_p, UInt32 *d) { CMatchFinderMt *p = (CMatchFinderMt *)_p; const UInt32 *bt = p->btBufPos; UInt32 len = *bt++; const UInt32 avail = p->btNumAvailBytes - 1; p->btNumAvailBytes = avail; p->btBufPos = bt + len; if (len == 0) { #define BT_HASH_BYTES_MAX 5 if (avail >= (BT_HASH_BYTES_MAX - 1) - 1) { UInt32 m = p->lzPos; if (m > p->historySize) m -= p->historySize; else m = 1; d = p->MixMatchesFunc(p, m, d); } } else { /* first match pair from BinTree: (match_len, match_dist), (match_len >= numHashBytes). MixMatchesFunc() inserts only hash matches that are nearer than (match_dist) */ d = p->MixMatchesFunc(p, p->lzPos - bt[1], d); // if (d) // check for failure do { const UInt32 v0 = bt[0]; const UInt32 v1 = bt[1]; bt += 2; d[0] = v0; d[1] = v1; d += 2; } while (len -= 2); } INCREASE_LZ_POS return d; } #define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); static void MatchFinderMt0_Skip(void *_p, UInt32 num) { CMatchFinderMt *p = (CMatchFinderMt *)_p; SKIP_HEADER2_MT { p->btNumAvailBytes--; SKIP_FOOTER_MT } static void MatchFinderMt2_Skip(void *_p, UInt32 num) { CMatchFinderMt *p = (CMatchFinderMt *)_p; SKIP_HEADER_MT(2) UInt32 h2; MT_HASH2_CALC hash[h2] = p->lzPos; SKIP_FOOTER_MT } static void MatchFinderMt3_Skip(void *_p, UInt32 num) { CMatchFinderMt *p = (CMatchFinderMt *)_p; SKIP_HEADER_MT(3) UInt32 h2, h3; MT_HASH3_CALC (hash + kFix3HashSize)[h3] = hash[ h2] = p->lzPos; SKIP_FOOTER_MT } /* // MatchFinderMt4_Skip() is similar to MatchFinderMt3_Skip(). // The difference is that MatchFinderMt3_Skip() updates hash for last 3 bytes of stream. static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER_MT(4) UInt32 h2, h3; // h4 MT_HASH3_CALC // MT_HASH4_CALC // (hash + kFix4HashSize)[h4] = (hash + kFix3HashSize)[h3] = hash[ h2] = p->lzPos; SKIP_FOOTER_MT } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) { vTable->Init = MatchFinderMt_Init; vTable->GetNumAvailableBytes = MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = MatchFinderMt_GetMatches; switch (MF(p)->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = NULL; vTable->Skip = MatchFinderMt0_Skip; vTable->GetMatches = MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; p->MixMatchesFunc = MixMatches2; vTable->Skip = MatchFinderMt2_Skip; break; case 4: p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; // it's fast inline version of GetMatches() // vTable->GetMatches = MatchFinderMt_GetMatches_Bt4; p->MixMatchesFunc = MixMatches3; vTable->Skip = MatchFinderMt3_Skip; break; default: p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; p->MixMatchesFunc = MixMatches4; vTable->Skip = MatchFinderMt3_Skip; // MatchFinderMt4_Skip; break; } } #undef RINOK_THREAD #undef PRF #undef MF #undef GetUi24hi_from32 #undef LOCK_BUFFER #undef UNLOCK_BUFFER tmp41wklro_/C/LzFindMt.h0000444000175000001440000000530014553472340016170 0ustar nabijaczleweliusers/* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2024-01-22 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZ_FIND_MT_H #define ZIP7_INC_LZ_FIND_MT_H #include "LzFind.h" #include "Threads.h" EXTERN_C_BEGIN typedef struct { UInt32 numProcessedBlocks; CThread thread; UInt64 affinity; BoolInt wasCreated; BoolInt needStart; BoolInt csWasInitialized; BoolInt csWasEntered; BoolInt exit; BoolInt stopWriting; CAutoResetEvent canStart; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; CCriticalSection cs; // UInt32 numBlocks_Sent; } CMtSync; struct CMatchFinderMt_; typedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct CMatchFinderMt_ { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; const UInt32 *btBufPos; const UInt32 *btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; // UInt32 hash4Mask; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; UInt32 failure_LZ_BT; // failure in BT transfered to LZ // UInt32 failure_LZ_LZ; // failure in LZ tables UInt32 failureBuf[1]; // UInt32 crc[256]; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; UInt32 failure_BT; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; const Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; // CMatchFinder MatchFinder; } CMatchFinderMt; // only for Mt part void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable); /* call MatchFinderMt_InitMt() before IMatchFinder::Init() */ SRes MatchFinderMt_InitMt(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); EXTERN_C_END #endif tmp41wklro_/C/LzFindOpt.c0000444000175000001440000003557014412267100016347 0ustar nabijaczleweliusers/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "CpuArch.h" #include "LzFind.h" // #include "LzFindMt.h" // #define LOG_ITERS // #define LOG_THREAD #ifdef LOG_THREAD #include #define PRF(x) x #else // #define PRF(x) #endif #ifdef LOG_ITERS #include UInt64 g_NumIters_Tree; UInt64 g_NumIters_Loop; UInt64 g_NumIters_Bytes; #define LOG_ITER(x) x #else #define LOG_ITER(x) #endif // ---------- BT THREAD ---------- #define USE_SON_PREFETCH #define USE_LONG_MATCH_OPT #define kEmptyHashValue 0 // #define CYC_TO_POS_OFFSET 0 // #define CYC_TO_POS_OFFSET 1 // for debug /* Z7_NO_INLINE UInt32 * Z7_FASTCALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes) { do { UInt32 delta; if (hash == size) break; delta = *hash++; if (delta == 0 || delta > (UInt32)pos) return NULL; lenLimit++; if (delta == (UInt32)pos) { CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2; *d++ = 0; ptr1[0] = kEmptyHashValue; ptr1[1] = kEmptyHashValue; } else { UInt32 *_distances = ++d; CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1; CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; const Byte *len0 = cur, *len1 = cur; UInt32 cutValue = _cutValue; const Byte *maxLen = cur + _maxLen; for (LOG_ITER(g_NumIters_Tree++);;) { LOG_ITER(g_NumIters_Loop++); { const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1); const Byte *len = (len0 < len1 ? len0 : len1); #ifdef USE_SON_PREFETCH const UInt32 pair0 = *pair; #endif if (len[diff] == len[0]) { if (++len != lenLimit && len[diff] == len[0]) while (++len != lenLimit) { LOG_ITER(g_NumIters_Bytes++); if (len[diff] != len[0]) break; } if (maxLen < len) { maxLen = len; *d++ = (UInt32)(len - cur); *d++ = delta - 1; if (len == lenLimit) { const UInt32 pair1 = pair[1]; *ptr1 = #ifdef USE_SON_PREFETCH pair0; #else pair[0]; #endif *ptr0 = pair1; _distances[-1] = (UInt32)(d - _distances); #ifdef USE_LONG_MATCH_OPT if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) break; { for (;;) { hash++; pos++; cur++; lenLimit++; { CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; #if 0 *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff]; #else const UInt32 p0 = ptr[0 + (diff * 2)]; const UInt32 p1 = ptr[1 + (diff * 2)]; ptr[0] = p0; ptr[1] = p1; // ptr[0] = ptr[0 + (diff * 2)]; // ptr[1] = ptr[1 + (diff * 2)]; #endif } // PrintSon(son + 2, pos - 1); // printf("\npos = %x delta = %x\n", pos, delta); len++; *d++ = 2; *d++ = (UInt32)(len - cur); *d++ = delta - 1; if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) break; } } #endif break; } } } { const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); if (len[diff] < len[0]) { delta = pair[1]; if (delta >= curMatch) return NULL; *ptr1 = curMatch; ptr1 = pair + 1; len1 = len; } else { delta = *pair; if (delta >= curMatch) return NULL; *ptr0 = curMatch; ptr0 = pair; len0 = len; } delta = (UInt32)pos - delta; if (--cutValue == 0 || delta >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; _distances[-1] = (UInt32)(d - _distances); break; } } } } // for (tree iterations) } pos++; cur++; } while (d < limit); *posRes = (UInt32)pos; return d; } */ /* define cbs if you use 2 functions. GetMatchesSpecN_1() : (pos < _cyclicBufferSize) GetMatchesSpecN_2() : (pos >= _cyclicBufferSize) do not define cbs if you use 1 function: GetMatchesSpecN_2() */ // #define cbs _cyclicBufferSize /* we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32 to eliminate "movsx" BUG in old MSVC x64 compiler. */ UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes); Z7_NO_INLINE UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes) { do // while (hash != size) { UInt32 delta; #ifndef cbs UInt32 cbs; #endif if (hash == size) break; delta = *hash++; if (delta == 0) return NULL; lenLimit++; #ifndef cbs cbs = _cyclicBufferSize; if ((UInt32)pos < cbs) { if (delta > (UInt32)pos) return NULL; cbs = (UInt32)pos; } #endif if (delta >= cbs) { CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); *d++ = 0; ptr1[0] = kEmptyHashValue; ptr1[1] = kEmptyHashValue; } else { UInt32 *_distances = ++d; CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); UInt32 cutValue = _cutValue; const Byte *len0 = cur, *len1 = cur; const Byte *maxLen = cur + _maxLen; // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else for (LOG_ITER(g_NumIters_Tree++);;) { LOG_ITER(g_NumIters_Loop++); { // SPEC code CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) ) << 1); const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; const Byte *len = (len0 < len1 ? len0 : len1); #ifdef USE_SON_PREFETCH const UInt32 pair0 = *pair; #endif if (len[diff] == len[0]) { if (++len != lenLimit && len[diff] == len[0]) while (++len != lenLimit) { LOG_ITER(g_NumIters_Bytes++); if (len[diff] != len[0]) break; } if (maxLen < len) { maxLen = len; *d++ = (UInt32)(len - cur); *d++ = delta - 1; if (len == lenLimit) { const UInt32 pair1 = pair[1]; *ptr1 = #ifdef USE_SON_PREFETCH pair0; #else pair[0]; #endif *ptr0 = pair1; _distances[-1] = (UInt32)(d - _distances); #ifdef USE_LONG_MATCH_OPT if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) break; { for (;;) { *d++ = 2; *d++ = (UInt32)(lenLimit - cur); *d++ = delta - 1; cur++; lenLimit++; // SPEC _cyclicBufferPos++; { // SPEC code CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1); const CLzRef *src = dest + ((diff + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1); // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; #if 0 *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); #else const UInt32 p0 = src[0]; const UInt32 p1 = src[1]; dest[0] = p0; dest[1] = p1; #endif } pos++; hash++; if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) break; } // for() end for long matches } #endif break; // break from TREE iterations } } } { const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); if (len[diff] < len[0]) { delta = pair[1]; *ptr1 = curMatch; ptr1 = pair + 1; len1 = len; if (delta >= curMatch) return NULL; } else { delta = *pair; *ptr0 = curMatch; ptr0 = pair; len0 = len; if (delta >= curMatch) return NULL; } delta = (UInt32)pos - delta; if (--cutValue == 0 || delta >= cbs) { *ptr0 = *ptr1 = kEmptyHashValue; _distances[-1] = (UInt32)(d - _distances); break; } } } } // for (tree iterations) } pos++; _cyclicBufferPos++; cur++; } while (d < limit); *posRes = (UInt32)pos; return d; } /* typedef UInt32 uint32plus; // size_t UInt32 * Z7_FASTCALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son, UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 *posRes) { do // while (hash != size) { UInt32 delta; #ifndef cbs UInt32 cbs; #endif if (hash == size) break; delta = *hash++; if (delta == 0) return NULL; #ifndef cbs cbs = _cyclicBufferSize; if ((UInt32)pos < cbs) { if (delta > (UInt32)pos) return NULL; cbs = (UInt32)pos; } #endif if (delta >= cbs) { CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); *d++ = 0; ptr1[0] = kEmptyHashValue; ptr1[1] = kEmptyHashValue; } else { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); UInt32 *_distances = ++d; uint32plus len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; uint32plus maxLen = _maxLen; // lenLimit++; // const Byte *lenLimit = cur + _lenLimit; for (LOG_ITER(g_NumIters_Tree++);;) { LOG_ITER(g_NumIters_Loop++); { // const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) ) << 1); const Byte *pb = cur - delta; uint32plus len = (len0 < len1 ? len0 : len1); #ifdef USE_SON_PREFETCH const UInt32 pair0 = *pair; #endif if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { maxLen = len; *d++ = (UInt32)len; *d++ = delta - 1; if (len == lenLimit) { { const UInt32 pair1 = pair[1]; *ptr0 = pair1; *ptr1 = #ifdef USE_SON_PREFETCH pair0; #else pair[0]; #endif } _distances[-1] = (UInt32)(d - _distances); #ifdef USE_LONG_MATCH_OPT if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) break; { const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; for (;;) { *d++ = 2; *d++ = (UInt32)lenLimit; *d++ = delta - 1; _cyclicBufferPos++; { CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1); const CLzRef *src = dest + ((diff + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1); #if 0 *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); #else const UInt32 p0 = src[0]; const UInt32 p1 = src[1]; dest[0] = p0; dest[1] = p1; #endif } hash++; pos++; cur++; pb++; if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) break; } } #endif break; } } } { const UInt32 curMatch = (UInt32)pos - delta; if (pb[len] < cur[len]) { delta = pair[1]; *ptr1 = curMatch; ptr1 = pair + 1; len1 = len; } else { delta = *pair; *ptr0 = curMatch; ptr0 = pair; len0 = len; } { if (delta >= curMatch) return NULL; delta = (UInt32)pos - delta; if (delta >= cbs // delta >= _cyclicBufferSize || delta >= pos || --cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; _distances[-1] = (UInt32)(d - _distances); break; } } } } } // for (tree iterations) } pos++; _cyclicBufferPos++; cur++; } while (d < limit); *posRes = (UInt32)pos; return d; } */ tmp41wklro_/C/LzHash.h0000444000175000001440000000156114401145220015661 0ustar nabijaczleweliusers/* LzHash.h -- HASH constants for LZ algorithms 2023-03-05 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZ_HASH_H #define ZIP7_INC_LZ_HASH_H /* (kHash2Size >= (1 << 8)) : Required (kHash3Size >= (1 << 16)) : Required */ #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) // #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) // #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) /* We use up to 3 crc values for hash: crc0 crc1 << Shift_1 crc2 << Shift_2 (Shift_1 = 5) and (Shift_2 = 10) is good tradeoff. Small values for Shift are not good for collision rate. Big value for Shift_2 increases the minimum size of hash table, that will be slow for small files. */ #define kLzHash_CrcShift_1 5 #define kLzHash_CrcShift_2 10 #endif tmp41wklro_/C/Lzma2Dec.c0000444000175000001440000003207414570276360016110 0ustar nabijaczleweliusers/* Lzma2Dec.c -- LZMA2 Decoder 2024-03-01 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ #include "Precomp.h" #ifdef SHOW_DEBUG_INFO #include #endif #include #include "Lzma2Dec.h" /* 00000000 - End of data 00000001 U U - Uncompressed, reset dic, need reset state and set new prop 00000010 U U - Uncompressed, no reset 100uuuuu U U P P - LZMA, no reset 101uuuuu U U P P - LZMA, reset state 110uuuuu U U P P S - LZMA, reset state + set new prop 111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic u, U - Unpack Size P - Pack Size S - Props */ #define LZMA2_CONTROL_COPY_RESET_DIC 1 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0) #define LZMA2_LCLP_MAX 4 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif typedef enum { LZMA2_STATE_CONTROL, LZMA2_STATE_UNPACK0, LZMA2_STATE_UNPACK1, LZMA2_STATE_PACK0, LZMA2_STATE_PACK1, LZMA2_STATE_PROP, LZMA2_STATE_DATA, LZMA2_STATE_DATA_CONT, LZMA2_STATE_FINISHED, LZMA2_STATE_ERROR } ELzma2State; static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) { UInt32 dicSize; if (prop > 40) return SZ_ERROR_UNSUPPORTED; dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); props[0] = (Byte)LZMA2_LCLP_MAX; props[1] = (Byte)(dicSize); props[2] = (Byte)(dicSize >> 8); props[3] = (Byte)(dicSize >> 16); props[4] = (Byte)(dicSize >> 24); return SZ_OK; } SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) { Byte props[LZMA_PROPS_SIZE]; RINOK(Lzma2Dec_GetOldProps(prop, props)) return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); } SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) { Byte props[LZMA_PROPS_SIZE]; RINOK(Lzma2Dec_GetOldProps(prop, props)) return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); } void Lzma2Dec_Init(CLzma2Dec *p) { p->state = LZMA2_STATE_CONTROL; p->needInitLevel = 0xE0; p->isExtraMode = False; p->unpackSize = 0; // p->decoder.dicPos = 0; // we can use it instead of full init LzmaDec_Init(&p->decoder); } // ELzma2State static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) { switch (p->state) { case LZMA2_STATE_CONTROL: p->isExtraMode = False; p->control = b; PRF(printf("\n %8X", (unsigned)p->decoder.dicPos)); PRF(printf(" %02X", (unsigned)b)); if (b == 0) return LZMA2_STATE_FINISHED; if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (b == LZMA2_CONTROL_COPY_RESET_DIC) p->needInitLevel = 0xC0; else if (b > 2 || p->needInitLevel == 0xE0) return LZMA2_STATE_ERROR; } else { if (b < p->needInitLevel) return LZMA2_STATE_ERROR; p->needInitLevel = 0; p->unpackSize = (UInt32)(b & 0x1F) << 16; } return LZMA2_STATE_UNPACK0; case LZMA2_STATE_UNPACK0: p->unpackSize |= (UInt32)b << 8; return LZMA2_STATE_UNPACK1; case LZMA2_STATE_UNPACK1: p->unpackSize |= (UInt32)b; p->unpackSize++; PRF(printf(" %7u", (unsigned)p->unpackSize)); return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; case LZMA2_STATE_PACK0: p->packSize = (UInt32)b << 8; return LZMA2_STATE_PACK1; case LZMA2_STATE_PACK1: p->packSize |= (UInt32)b; p->packSize++; // if (p->packSize < 5) return LZMA2_STATE_ERROR; PRF(printf(" %5u", (unsigned)p->packSize)); return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA; case LZMA2_STATE_PROP: { unsigned lc, lp; if (b >= (9 * 5 * 5)) return LZMA2_STATE_ERROR; lc = b % 9; b /= 9; p->decoder.prop.pb = (Byte)(b / 5); lp = b % 5; if (lc + lp > LZMA2_LCLP_MAX) return LZMA2_STATE_ERROR; p->decoder.prop.lc = (Byte)lc; p->decoder.prop.lp = (Byte)lp; return LZMA2_STATE_DATA; } default: return LZMA2_STATE_ERROR; } } static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) { memcpy(p->dic + p->dicPos, src, size); p->dicPos += size; if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) p->checkDicSize = p->prop.dicSize; p->processedPos += (UInt32)size; } void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; while (p->state != LZMA2_STATE_ERROR) { SizeT dicPos; if (p->state == LZMA2_STATE_FINISHED) { *status = LZMA_STATUS_FINISHED_WITH_MARK; return SZ_OK; } dicPos = p->decoder.dicPos; if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } (*srcLen)++; p->state = Lzma2Dec_UpdateState(p, *src++); if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) break; continue; } { SizeT inCur = inSize - *srcLen; SizeT outCur = dicLimit - dicPos; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; if (outCur >= p->unpackSize) { outCur = (SizeT)p->unpackSize; curFinishMode = LZMA_FINISH_END; } if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (inCur == 0) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->state == LZMA2_STATE_DATA) { BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); LzmaDec_InitDicAndState(&p->decoder, initDic, False); } if (inCur > outCur) inCur = outCur; if (inCur == 0) break; LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); src += inCur; *srcLen += inCur; p->unpackSize -= (UInt32)inCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; } else { SRes res; if (p->state == LZMA2_STATE_DATA) { BoolInt initDic = (p->control >= 0xE0); BoolInt initState = (p->control >= 0xA0); LzmaDec_InitDicAndState(&p->decoder, initDic, initState); p->state = LZMA2_STATE_DATA_CONT; } if (inCur > p->packSize) inCur = (SizeT)p->packSize; res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); src += inCur; *srcLen += inCur; p->packSize -= (UInt32)inCur; outCur = p->decoder.dicPos - dicPos; p->unpackSize -= (UInt32)outCur; if (res != 0) break; if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) { if (p->packSize == 0) break; return SZ_OK; } if (inCur == 0 && outCur == 0) { if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || p->unpackSize != 0 || p->packSize != 0) break; p->state = LZMA2_STATE_CONTROL; } *status = LZMA_STATUS_NOT_SPECIFIED; } } } *status = LZMA_STATUS_NOT_SPECIFIED; p->state = LZMA2_STATE_ERROR; return SZ_ERROR_DATA; } ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, SizeT outSize, const Byte *src, SizeT *srcLen, int checkFinishBlock) { SizeT inSize = *srcLen; *srcLen = 0; while (p->state != LZMA2_STATE_ERROR) { if (p->state == LZMA2_STATE_FINISHED) return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK; if (outSize == 0 && !checkFinishBlock) return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) { if (*srcLen == inSize) return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; (*srcLen)++; p->state = Lzma2Dec_UpdateState(p, *src++); if (p->state == LZMA2_STATE_UNPACK0) { // if (p->decoder.dicPos != 0) if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0) return LZMA2_PARSE_STATUS_NEW_BLOCK; // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; } // The following code can be commented. // It's not big problem, if we read additional input bytes. // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. if (outSize == 0 && p->state != LZMA2_STATE_FINISHED) { // checkFinishBlock is true. So we expect that block must be finished, // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here // break; return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; } if (p->state == LZMA2_STATE_DATA) return LZMA2_PARSE_STATUS_NEW_CHUNK; continue; } if (outSize == 0) return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; { SizeT inCur = inSize - *srcLen; if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (inCur == 0) return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; if (inCur > p->unpackSize) inCur = p->unpackSize; if (inCur > outSize) inCur = outSize; p->decoder.dicPos += inCur; src += inCur; *srcLen += inCur; outSize -= inCur; p->unpackSize -= (UInt32)inCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; } else { p->isExtraMode = True; if (inCur == 0) { if (p->packSize != 0) return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; } else if (p->state == LZMA2_STATE_DATA) { p->state = LZMA2_STATE_DATA_CONT; if (*src != 0) { // first byte of lzma chunk must be Zero *srcLen += 1; p->packSize--; break; } } if (inCur > p->packSize) inCur = (SizeT)p->packSize; src += inCur; *srcLen += inCur; p->packSize -= (UInt32)inCur; if (p->packSize == 0) { SizeT rem = outSize; if (rem > p->unpackSize) rem = p->unpackSize; p->decoder.dicPos += rem; p->unpackSize -= (UInt32)rem; outSize -= rem; if (p->unpackSize == 0) p->state = LZMA2_STATE_CONTROL; } } } } p->state = LZMA2_STATE_ERROR; return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; } SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen, inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inCur = inSize, outCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->decoder.dicPos == p->decoder.dicBufSize) p->decoder.dicPos = 0; dicPos = p->decoder.dicPos; curFinishMode = LZMA_FINISH_ANY; outCur = p->decoder.dicBufSize - dicPos; if (outCur >= outSize) { outCur = outSize; curFinishMode = finishMode; } res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); src += inCur; inSize -= inCur; *srcLen += inCur; outCur = p->decoder.dicPos - dicPos; memcpy(dest, p->decoder.dic + dicPos, outCur); dest += outCur; outSize -= outCur; *destLen += outCur; if (res != 0) return res; if (outCur == 0 || outSize == 0) return SZ_OK; } } SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) { CLzma2Dec p; SRes res; SizeT outSize = *destLen, inSize = *srcLen; *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; Lzma2Dec_CONSTRUCT(&p) RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)) p.decoder.dic = dest; p.decoder.dicBufSize = outSize; Lzma2Dec_Init(&p); *srcLen = inSize; res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); *destLen = p.decoder.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; Lzma2Dec_FreeProbs(&p, alloc); return res; } #undef PRF tmp41wklro_/C/Lzma2Dec.h0000444000175000001440000000747614400360500016103 0ustar nabijaczleweliusers/* Lzma2Dec.h -- LZMA2 Decoder 2023-03-03 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA2_DEC_H #define ZIP7_INC_LZMA2_DEC_H #include "LzmaDec.h" EXTERN_C_BEGIN /* ---------- State Interface ---------- */ typedef struct { unsigned state; Byte control; Byte needInitLevel; Byte isExtraMode; Byte _pad_; UInt32 packSize; UInt32 unpackSize; CLzmaDec decoder; } CLzma2Dec; #define Lzma2Dec_CONSTRUCT(p) LzmaDec_CONSTRUCT(&(p)->decoder) #define Lzma2Dec_Construct(p) Lzma2Dec_CONSTRUCT(p) #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); void Lzma2Dec_Init(CLzma2Dec *p); /* finishMode: It has meaning only if the decoding reaches output limit (*destLen or dicLimit). LZMA_FINISH_ANY - use smallest number of input bytes LZMA_FINISH_END - read EndOfStream marker after decoding Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT SZ_ERROR_DATA - Data error */ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- LZMA2 block and chunk parsing ---------- */ /* Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data. It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code: - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input. - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read. CLzma2Dec::unpackSize contains unpack size of that chunk */ typedef enum { /* LZMA_STATUS_NOT_SPECIFIED // data error LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED // LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused */ LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1, LZMA2_PARSE_STATUS_NEW_CHUNK } ELzma2ParseStatus; ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, SizeT outSize, // output size const Byte *src, SizeT *srcLen, int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. ); /* LZMA2 parser doesn't decode LZMA chunks, so we must read full input LZMA chunk to decode some part of LZMA chunk. Lzma2Dec_GetUnpackExtra() returns the value that shows max possible number of output bytes that can be output by decoder at current input positon. */ #define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0) /* ---------- One Call Interface ---------- */ /* finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - use smallest number of input bytes LZMA_FINISH_END - read EndOfStream marker after decoding Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); EXTERN_C_END #endif tmp41wklro_/C/Lzma2DecMt.c0000444000175000001440000006020314415733200016371 0ustar nabijaczleweliusers/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread 2023-04-13 : Igor Pavlov : Public domain */ #include "Precomp.h" // #define SHOW_DEBUG_INFO // #define Z7_ST #ifdef SHOW_DEBUG_INFO #include #endif #include "Alloc.h" #include "Lzma2Dec.h" #include "Lzma2DecMt.h" #ifndef Z7_ST #include "MtDec.h" #define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28) #endif #ifndef Z7_ST #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif #define PRF_STR(s) PRF(printf("\n" s "\n");) #define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2);) #endif void Lzma2DecMtProps_Init(CLzma2DecMtProps *p) { p->inBufSize_ST = 1 << 20; p->outStep_ST = 1 << 20; #ifndef Z7_ST p->numThreads = 1; p->inBufSize_MT = 1 << 18; p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT; p->inBlockMax = p->outBlockMax + p->outBlockMax / 16; #endif } #ifndef Z7_ST /* ---------- CLzma2DecMtThread ---------- */ typedef struct { CLzma2Dec dec; Byte dec_created; Byte needInit; Byte *outBuf; size_t outBufSize; EMtDecParseState state; ELzma2ParseStatus parseStatus; size_t inPreSize; size_t outPreSize; size_t inCodeSize; size_t outCodeSize; SRes codeRes; CAlignOffsetAlloc alloc; Byte mtPad[1 << 7]; } CLzma2DecMtThread; #endif /* ---------- CLzma2DecMt ---------- */ struct CLzma2DecMt { // ISzAllocPtr alloc; ISzAllocPtr allocMid; CAlignOffsetAlloc alignOffsetAlloc; CLzma2DecMtProps props; Byte prop; ISeqInStreamPtr inStream; ISeqOutStreamPtr outStream; ICompressProgressPtr progress; BoolInt finishMode; BoolInt outSize_Defined; UInt64 outSize; UInt64 outProcessed; UInt64 inProcessed; BoolInt readWasFinished; SRes readRes; Byte *inBuf; size_t inBufSize; Byte dec_created; CLzma2Dec dec; size_t inPos; size_t inLim; #ifndef Z7_ST UInt64 outProcessed_Parse; BoolInt mtc_WasConstructed; CMtDec mtc; CLzma2DecMtThread coders[MTDEC_THREADS_MAX]; #endif }; CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) { CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt)); if (!p) return NULL; // p->alloc = alloc; p->allocMid = allocMid; AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); p->alignOffsetAlloc.numAlignBits = 7; p->alignOffsetAlloc.offset = 0; p->alignOffsetAlloc.baseAlloc = alloc; p->inBuf = NULL; p->inBufSize = 0; p->dec_created = False; // Lzma2DecMtProps_Init(&p->props); #ifndef Z7_ST p->mtc_WasConstructed = False; { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CLzma2DecMtThread *t = &p->coders[i]; t->dec_created = False; t->outBuf = NULL; t->outBufSize = 0; } } #endif return (CLzma2DecMtHandle)(void *)p; } #ifndef Z7_ST static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p) { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CLzma2DecMtThread *t = &p->coders[i]; if (t->outBuf) { ISzAlloc_Free(p->allocMid, t->outBuf); t->outBuf = NULL; t->outBufSize = 0; } } } #endif static void Lzma2DecMt_FreeSt(CLzma2DecMt *p) { if (p->dec_created) { Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt); p->dec_created = False; } if (p->inBuf) { ISzAlloc_Free(p->allocMid, p->inBuf); p->inBuf = NULL; } p->inBufSize = 0; } // #define GET_CLzma2DecMt_p CLzma2DecMt *p = (CLzma2DecMt *)(void *)pp; void Lzma2DecMt_Destroy(CLzma2DecMtHandle p) { // GET_CLzma2DecMt_p Lzma2DecMt_FreeSt(p); #ifndef Z7_ST if (p->mtc_WasConstructed) { MtDec_Destruct(&p->mtc); p->mtc_WasConstructed = False; } { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CLzma2DecMtThread *t = &p->coders[i]; if (t->dec_created) { // we don't need to free dict here Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!! t->dec_created = False; } } } Lzma2DecMt_FreeOutBufs(p); #endif ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p); } #ifndef Z7_ST static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) { CLzma2DecMt *me = (CLzma2DecMt *)obj; CLzma2DecMtThread *t = &me->coders[coderIndex]; PRF_STR_INT_2("Parse", coderIndex, cc->srcSize) cc->state = MTDEC_PARSE_CONTINUE; if (cc->startCall) { if (!t->dec_created) { Lzma2Dec_CONSTRUCT(&t->dec) t->dec_created = True; AlignOffsetAlloc_CreateVTable(&t->alloc); { /* (1 << 12) is expected size of one way in data cache. We optimize alignment for cache line size of 128 bytes and smaller */ const unsigned kNumAlignBits = 12; const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */ t->alloc.numAlignBits = kNumAlignBits; t->alloc.offset = ((UInt32)coderIndex * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits)); t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc; } } Lzma2Dec_Init(&t->dec); t->inPreSize = 0; t->outPreSize = 0; // t->blockWasFinished = False; // t->finishedWithMark = False; t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; t->state = MTDEC_PARSE_CONTINUE; t->inCodeSize = 0; t->outCodeSize = 0; t->codeRes = SZ_OK; // (cc->srcSize == 0) is allowed } { ELzma2ParseStatus status; BoolInt overflow; UInt32 unpackRem = 0; int checkFinishBlock = True; size_t limit = me->props.outBlockMax; if (me->outSize_Defined) { UInt64 rem = me->outSize - me->outProcessed_Parse; if (limit >= rem) { limit = (size_t)rem; if (!me->finishMode) checkFinishBlock = False; } } // checkFinishBlock = False, if we want to decode partial data // that must be finished at position <= outBlockMax. { const size_t srcOrig = cc->srcSize; SizeT srcSize_Point = 0; SizeT dicPos_Point = 0; cc->srcSize = 0; overflow = False; for (;;) { SizeT srcCur = (SizeT)(srcOrig - cc->srcSize); status = Lzma2Dec_Parse(&t->dec, (SizeT)limit - t->dec.decoder.dicPos, cc->src + cc->srcSize, &srcCur, checkFinishBlock); cc->srcSize += srcCur; if (status == LZMA2_PARSE_STATUS_NEW_CHUNK) { if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos) { overflow = True; break; } continue; } if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) { if (t->dec.decoder.dicPos == 0) continue; // we decode small blocks in one thread if (t->dec.decoder.dicPos >= (1 << 14)) break; dicPos_Point = t->dec.decoder.dicPos; srcSize_Point = (SizeT)cc->srcSize; continue; } if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock // && limit == t->dec.decoder.dicPos // && limit == me->props.outBlockMax ) { overflow = True; break; } unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec); break; } if (dicPos_Point != 0 && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK && (int)status != LZMA_STATUS_FINISHED_WITH_MARK && (int)status != LZMA_STATUS_NOT_SPECIFIED) { // we revert to latest newBlock state status = LZMA2_PARSE_STATUS_NEW_BLOCK; unpackRem = 0; t->dec.decoder.dicPos = dicPos_Point; cc->srcSize = srcSize_Point; overflow = False; } } t->inPreSize += cc->srcSize; t->parseStatus = status; if (overflow) cc->state = MTDEC_PARSE_OVERFLOW; else { size_t dicPos = t->dec.decoder.dicPos; if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT) { if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) { cc->state = MTDEC_PARSE_NEW; cc->srcSize--; // we don't need control byte of next block t->inPreSize--; } else { cc->state = MTDEC_PARSE_END; if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK) { // (status == LZMA_STATUS_NOT_SPECIFIED) // (status == LZMA_STATUS_NOT_FINISHED) if (unpackRem != 0) { /* we also reserve space for max possible number of output bytes of current LZMA chunk */ size_t rem = limit - dicPos; if (rem > unpackRem) rem = unpackRem; dicPos += rem; } } } me->outProcessed_Parse += dicPos; } cc->outPos = dicPos; t->outPreSize = (size_t)dicPos; } t->state = cc->state; return; } } static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex) { CLzma2DecMt *me = (CLzma2DecMt *)pp; CLzma2DecMtThread *t = &me->coders[coderIndex]; Byte *dest = t->outBuf; if (t->inPreSize == 0) { t->codeRes = SZ_ERROR_DATA; return t->codeRes; } if (!dest || t->outBufSize < t->outPreSize) { if (dest) { ISzAlloc_Free(me->allocMid, dest); t->outBuf = NULL; t->outBufSize = 0; } dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize // + (1 << 28) ); // Sleep(200); if (!dest) return SZ_ERROR_MEM; t->outBuf = dest; t->outBufSize = t->outPreSize; } t->dec.decoder.dic = dest; t->dec.decoder.dicBufSize = (SizeT)t->outPreSize; t->needInit = True; return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt } static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex, const Byte *src, size_t srcSize, int srcFinished, // int finished, int blockFinished, UInt64 *inCodePos, UInt64 *outCodePos, int *stop) { CLzma2DecMt *me = (CLzma2DecMt *)pp; CLzma2DecMtThread *t = &me->coders[coderIndex]; UNUSED_VAR(srcFinished) PRF_STR_INT_2("Code", coderIndex, srcSize) *inCodePos = t->inCodeSize; *outCodePos = 0; *stop = True; if (t->needInit) { Lzma2Dec_Init(&t->dec); t->needInit = False; } { ELzmaStatus status; SizeT srcProcessed = (SizeT)srcSize; BoolInt blockWasFinished = ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK); SRes res = Lzma2Dec_DecodeToDic(&t->dec, (SizeT)t->outPreSize, src, &srcProcessed, blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY, &status); t->codeRes = res; t->inCodeSize += srcProcessed; *inCodePos = t->inCodeSize; t->outCodeSize = t->dec.decoder.dicPos; *outCodePos = t->dec.decoder.dicPos; if (res != SZ_OK) return res; if (srcProcessed == srcSize) *stop = False; if (blockWasFinished) { if (srcSize != srcProcessed) return SZ_ERROR_FAIL; if (t->inPreSize == t->inCodeSize) { if (t->outPreSize != t->outCodeSize) return SZ_ERROR_FAIL; *stop = True; } } else { if (t->outPreSize == t->outCodeSize) *stop = True; } return SZ_OK; } } #define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24) static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex, BoolInt needWriteToStream, const Byte *src, size_t srcSize, BoolInt isCross, BoolInt *needContinue, BoolInt *canRecode) { CLzma2DecMt *me = (CLzma2DecMt *)pp; const CLzma2DecMtThread *t = &me->coders[coderIndex]; size_t size = t->outCodeSize; const Byte *data = t->outBuf; BoolInt needContinue2 = True; UNUSED_VAR(src) UNUSED_VAR(srcSize) UNUSED_VAR(isCross) PRF_STR_INT_2("Write", coderIndex, srcSize) *needContinue = False; *canRecode = True; if ( // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK t->state == MTDEC_PARSE_OVERFLOW || t->state == MTDEC_PARSE_END) needContinue2 = False; if (!needWriteToStream) return SZ_OK; me->mtc.inProcessed += t->inCodeSize; if (t->codeRes == SZ_OK) if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK) if (t->outPreSize != t->outCodeSize || t->inPreSize != t->inCodeSize) return SZ_ERROR_FAIL; *canRecode = False; if (me->outStream) { for (;;) { size_t cur = size; size_t written; if (cur > LZMA2DECMT_STREAM_WRITE_STEP) cur = LZMA2DECMT_STREAM_WRITE_STEP; written = ISeqOutStream_Write(me->outStream, data, cur); me->outProcessed += written; // me->mtc.writtenTotal += written; if (written != cur) return SZ_ERROR_WRITE; data += cur; size -= cur; if (size == 0) { *needContinue = needContinue2; return SZ_OK; } RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0)) } } return SZ_ERROR_FAIL; /* if (size > me->outBufSize) return SZ_ERROR_OUTPUT_EOF; memcpy(me->outBuf, data, size); me->outBufSize -= size; me->outBuf += size; *needContinue = needContinue2; return SZ_OK; */ } #endif static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p) { if (!p->dec_created) { Lzma2Dec_CONSTRUCT(&p->dec) p->dec_created = True; } RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt)) if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) { ISzAlloc_Free(p->allocMid, p->inBuf); p->inBufSize = 0; p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); if (!p->inBuf) return SZ_ERROR_MEM; p->inBufSize = p->props.inBufSize_ST; } Lzma2Dec_Init(&p->dec); return SZ_OK; } static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p #ifndef Z7_ST , BoolInt tMode #endif ) { SizeT wrPos; size_t inPos, inLim; const Byte *inData; UInt64 inPrev, outPrev; CLzma2Dec *dec; #ifndef Z7_ST if (tMode) { Lzma2DecMt_FreeOutBufs(p); tMode = MtDec_PrepareRead(&p->mtc); } #endif RINOK(Lzma2Dec_Prepare_ST(p)) dec = &p->dec; inPrev = p->inProcessed; outPrev = p->outProcessed; inPos = 0; inLim = 0; inData = NULL; wrPos = dec->decoder.dicPos; for (;;) { SizeT dicPos; SizeT size; ELzmaFinishMode finishMode; SizeT inProcessed; ELzmaStatus status; SRes res; SizeT outProcessed; BoolInt outFinished; BoolInt needStop; if (inPos == inLim) { #ifndef Z7_ST if (tMode) { inData = MtDec_Read(&p->mtc, &inLim); inPos = 0; if (inData) continue; tMode = False; inLim = 0; } #endif if (!p->readWasFinished) { inPos = 0; inLim = p->inBufSize; inData = p->inBuf; p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim); // p->readProcessed += inLim; // inLim -= 5; p->readWasFinished = True; // for test if (inLim == 0 || p->readRes != SZ_OK) p->readWasFinished = True; } } dicPos = dec->decoder.dicPos; { SizeT next = dec->decoder.dicBufSize; if (next - wrPos > p->props.outStep_ST) next = wrPos + (SizeT)p->props.outStep_ST; size = next - dicPos; } finishMode = LZMA_FINISH_ANY; if (p->outSize_Defined) { const UInt64 rem = p->outSize - p->outProcessed; if (size >= rem) { size = (SizeT)rem; if (p->finishMode) finishMode = LZMA_FINISH_END; } } inProcessed = (SizeT)(inLim - inPos); res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; p->inProcessed += inProcessed; outProcessed = dec->decoder.dicPos - dicPos; p->outProcessed += outProcessed; outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed); needStop = (res != SZ_OK || (inProcessed == 0 && outProcessed == 0) || status == LZMA_STATUS_FINISHED_WITH_MARK || (!p->finishMode && outFinished)); if (needStop || outProcessed >= size) { SRes res2; { size_t writeSize = dec->decoder.dicPos - wrPos; size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize); res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE; } if (dec->decoder.dicPos == dec->decoder.dicBufSize) dec->decoder.dicPos = 0; wrPos = dec->decoder.dicPos; RINOK(res2) if (needStop) { if (res != SZ_OK) return res; if (status == LZMA_STATUS_FINISHED_WITH_MARK) { if (p->finishMode) { if (p->outSize_Defined && p->outSize != p->outProcessed) return SZ_ERROR_DATA; } return SZ_OK; } if (!p->finishMode && outFinished) return SZ_OK; if (status == LZMA_STATUS_NEEDS_MORE_INPUT) return SZ_ERROR_INPUT_EOF; return SZ_ERROR_DATA; } } if (p->progress) { UInt64 inDelta = p->inProcessed - inPrev; UInt64 outDelta = p->outProcessed - outPrev; if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) { RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed)) inPrev = p->inProcessed; outPrev = p->outProcessed; } } } } SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, Byte prop, const CLzma2DecMtProps *props, ISeqOutStreamPtr outStream, const UInt64 *outDataSize, int finishMode, // Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, // const Byte *inData, size_t inDataSize, UInt64 *inProcessed, // UInt64 *outProcessed, int *isMT, ICompressProgressPtr progress) { // GET_CLzma2DecMt_p #ifndef Z7_ST BoolInt tMode; #endif *inProcessed = 0; if (prop > 40) return SZ_ERROR_UNSUPPORTED; p->prop = prop; p->props = *props; p->inStream = inStream; p->outStream = outStream; p->progress = progress; p->outSize = 0; p->outSize_Defined = False; if (outDataSize) { p->outSize_Defined = True; p->outSize = *outDataSize; } p->finishMode = finishMode; p->outProcessed = 0; p->inProcessed = 0; p->readWasFinished = False; p->readRes = SZ_OK; *isMT = False; #ifndef Z7_ST tMode = False; // p->mtc.parseRes = SZ_OK; // p->mtc.numFilledThreads = 0; // p->mtc.crossStart = 0; // p->mtc.crossEnd = 0; // p->mtc.allocError_for_Read_BlockIndex = 0; // p->mtc.isAllocError = False; if (p->props.numThreads > 1) { IMtDecCallback2 vt; Lzma2DecMt_FreeSt(p); p->outProcessed_Parse = 0; if (!p->mtc_WasConstructed) { p->mtc_WasConstructed = True; MtDec_Construct(&p->mtc); } p->mtc.progress = progress; p->mtc.inStream = inStream; // p->outBuf = NULL; // p->outBufSize = 0; /* if (!outStream) { // p->outBuf = outBuf; // p->outBufSize = *outBufSize; // *outBufSize = 0; return SZ_ERROR_PARAM; } */ // p->mtc.inBlockMax = p->props.inBlockMax; p->mtc.alloc = &p->alignOffsetAlloc.vt; // p->alignOffsetAlloc.baseAlloc; // p->mtc.inData = inData; // p->mtc.inDataSize = inDataSize; p->mtc.mtCallback = &vt; p->mtc.mtCallbackObject = p; p->mtc.inBufSize = p->props.inBufSize_MT; p->mtc.numThreadsMax = p->props.numThreads; *isMT = True; vt.Parse = Lzma2DecMt_MtCallback_Parse; vt.PreCode = Lzma2DecMt_MtCallback_PreCode; vt.Code = Lzma2DecMt_MtCallback_Code; vt.Write = Lzma2DecMt_MtCallback_Write; { BoolInt needContinue = False; SRes res = MtDec_Code(&p->mtc); /* if (!outStream) *outBufSize = p->outBuf - outBuf; */ *inProcessed = p->mtc.inProcessed; needContinue = False; if (res == SZ_OK) { if (p->mtc.mtProgress.res != SZ_OK) res = p->mtc.mtProgress.res; else needContinue = p->mtc.needContinue; } if (!needContinue) { if (res == SZ_OK) return p->mtc.readRes; return res; } tMode = True; p->readRes = p->mtc.readRes; p->readWasFinished = p->mtc.readWasFinished; p->inProcessed = p->mtc.inProcessed; PRF_STR("----- decoding ST -----") } } #endif *isMT = False; { SRes res = Lzma2Dec_Decode_ST(p #ifndef Z7_ST , tMode #endif ); *inProcessed = p->inProcessed; // res = SZ_OK; // for test if (res == SZ_ERROR_INPUT_EOF) { if (p->readRes != SZ_OK) res = p->readRes; } else if (res == SZ_OK && p->readRes != SZ_OK) res = p->readRes; /* #ifndef Z7_ST if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK) res = p->mtc.parseRes; #endif */ return res; } } /* ---------- Read from CLzma2DecMtHandle Interface ---------- */ SRes Lzma2DecMt_Init(CLzma2DecMtHandle p, Byte prop, const CLzma2DecMtProps *props, const UInt64 *outDataSize, int finishMode, ISeqInStreamPtr inStream) { // GET_CLzma2DecMt_p if (prop > 40) return SZ_ERROR_UNSUPPORTED; p->prop = prop; p->props = *props; p->inStream = inStream; p->outSize = 0; p->outSize_Defined = False; if (outDataSize) { p->outSize_Defined = True; p->outSize = *outDataSize; } p->finishMode = finishMode; p->outProcessed = 0; p->inProcessed = 0; p->inPos = 0; p->inLim = 0; return Lzma2Dec_Prepare_ST(p); } SRes Lzma2DecMt_Read(CLzma2DecMtHandle p, Byte *data, size_t *outSize, UInt64 *inStreamProcessed) { // GET_CLzma2DecMt_p ELzmaFinishMode finishMode; SRes readRes; size_t size = *outSize; *outSize = 0; *inStreamProcessed = 0; finishMode = LZMA_FINISH_ANY; if (p->outSize_Defined) { const UInt64 rem = p->outSize - p->outProcessed; if (size >= rem) { size = (size_t)rem; if (p->finishMode) finishMode = LZMA_FINISH_END; } } readRes = SZ_OK; for (;;) { SizeT inCur; SizeT outCur; ELzmaStatus status; SRes res; if (p->inPos == p->inLim && readRes == SZ_OK) { p->inPos = 0; p->inLim = p->props.inBufSize_ST; readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim); } inCur = (SizeT)(p->inLim - p->inPos); outCur = (SizeT)size; res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur, p->inBuf + p->inPos, &inCur, finishMode, &status); p->inPos += inCur; p->inProcessed += inCur; *inStreamProcessed += inCur; p->outProcessed += outCur; *outSize += outCur; size -= outCur; data += outCur; if (res != 0) return res; /* if (status == LZMA_STATUS_FINISHED_WITH_MARK) return readRes; if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) { if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize) return SZ_ERROR_DATA; return readRes; } */ if (inCur == 0 && outCur == 0) return readRes; } } #undef PRF #undef PRF_STR #undef PRF_STR_INT_2 tmp41wklro_/C/Lzma2DecMt.h0000444000175000001440000000436014415733200016400 0ustar nabijaczleweliusers/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread 2023-04-13 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA2_DEC_MT_H #define ZIP7_INC_LZMA2_DEC_MT_H #include "7zTypes.h" EXTERN_C_BEGIN typedef struct { size_t inBufSize_ST; size_t outStep_ST; #ifndef Z7_ST unsigned numThreads; size_t inBufSize_MT; size_t outBlockMax; size_t inBlockMax; #endif } CLzma2DecMtProps; /* init to single-thread mode */ void Lzma2DecMtProps_Init(CLzma2DecMtProps *p); /* ---------- CLzma2DecMtHandle Interface ---------- */ /* Lzma2DecMt_ * functions can return the following exit codes: SRes: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - ISeqOutStream write callback error // SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) */ typedef struct CLzma2DecMt CLzma2DecMt; typedef CLzma2DecMt * CLzma2DecMtHandle; // Z7_DECLARE_HANDLE(CLzma2DecMtHandle) CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); void Lzma2DecMt_Destroy(CLzma2DecMtHandle p); SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, Byte prop, const CLzma2DecMtProps *props, ISeqOutStreamPtr outStream, const UInt64 *outDataSize, // NULL means undefined int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished // Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, // const Byte *inData, size_t inDataSize, // out variables: UInt64 *inProcessed, int *isMT, /* out: (*isMT == 0), if single thread decoding was used */ // UInt64 *outProcessed, ICompressProgressPtr progress); /* ---------- Read from CLzma2DecMtHandle Interface ---------- */ SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, Byte prop, const CLzma2DecMtProps *props, const UInt64 *outDataSize, int finishMode, ISeqInStreamPtr inStream); SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, Byte *data, size_t *outSize, UInt64 *inStreamProcessed); EXTERN_C_END #endif tmp41wklro_/C/Lzma2Enc.c0000444000175000001440000004645114415733200016113 0ustar nabijaczleweliusers/* Lzma2Enc.c -- LZMA2 Encoder 2023-04-13 : Igor Pavlov : Public domain */ #include "Precomp.h" #include /* #define Z7_ST */ #include "Lzma2Enc.h" #ifndef Z7_ST #include "MtCoder.h" #else #define MTCODER_THREADS_MAX 1 #endif #define LZMA2_CONTROL_LZMA (1 << 7) #define LZMA2_CONTROL_COPY_NO_RESET 2 #define LZMA2_CONTROL_COPY_RESET_DIC 1 #define LZMA2_CONTROL_EOF 0 #define LZMA2_LCLP_MAX 4 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) #define LZMA2_PACK_SIZE_MAX (1 << 16) #define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX #define LZMA2_UNPACK_SIZE_MAX (1 << 21) #define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX #define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) #define PRF(x) /* x */ /* ---------- CLimitedSeqInStream ---------- */ typedef struct { ISeqInStream vt; ISeqInStreamPtr realStream; UInt64 limit; UInt64 processed; int finished; } CLimitedSeqInStream; static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) { p->limit = (UInt64)(Int64)-1; p->processed = 0; p->finished = 0; } static SRes LimitedSeqInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream) size_t size2 = *size; SRes res = SZ_OK; if (p->limit != (UInt64)(Int64)-1) { const UInt64 rem = p->limit - p->processed; if (size2 > rem) size2 = (size_t)rem; } if (size2 != 0) { res = ISeqInStream_Read(p->realStream, data, &size2); p->finished = (size2 == 0 ? 1 : 0); p->processed += size2; } *size = size2; return res; } /* ---------- CLzma2EncInt ---------- */ typedef struct { CLzmaEncHandle enc; Byte propsAreSet; Byte propsByte; Byte needInitState; Byte needInitProp; UInt64 srcPos; } CLzma2EncInt; static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) { if (!p->propsAreSet) { SizeT propsSize = LZMA_PROPS_SIZE; Byte propsEncoded[LZMA_PROPS_SIZE]; RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)) RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)) p->propsByte = propsEncoded[0]; p->propsAreSet = True; } return SZ_OK; } static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) { p->srcPos = 0; p->needInitState = True; p->needInitProp = True; } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p); void LzmaEnc_Finish(CLzmaEncHandle p); void LzmaEnc_SaveState(CLzmaEncHandle p); void LzmaEnc_RestoreState(CLzmaEncHandle p); /* UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p); */ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, size_t *packSizeRes, ISeqOutStreamPtr outStream) { size_t packSizeLimit = *packSizeRes; size_t packSize = packSizeLimit; UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); BoolInt useCopyBlock; SRes res; *packSizeRes = 0; if (packSize < lzHeaderSize) return SZ_ERROR_OUTPUT_EOF; packSize -= lzHeaderSize; LzmaEnc_SaveState(p->enc); res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); if (unpackSize == 0) return res; if (res == SZ_OK) useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); else { if (res != SZ_ERROR_OUTPUT_EOF) return res; res = SZ_OK; useCopyBlock = True; } if (useCopyBlock) { size_t destPos = 0; PRF(printf("################# COPY ")); while (unpackSize > 0) { const UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; if (packSizeLimit - destPos < u + 3) return SZ_ERROR_OUTPUT_EOF; outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); outBuf[destPos++] = (Byte)((u - 1) >> 8); outBuf[destPos++] = (Byte)(u - 1); memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); unpackSize -= u; destPos += u; p->srcPos += u; if (outStream) { *packSizeRes += destPos; if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) return SZ_ERROR_WRITE; destPos = 0; } else *packSizeRes = destPos; /* needInitState = True; */ } LzmaEnc_RestoreState(p->enc); return SZ_OK; } { size_t destPos = 0; const UInt32 u = unpackSize - 1; const UInt32 pm = (UInt32)(packSize - 1); const unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); PRF(printf(" ")); outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); outBuf[destPos++] = (Byte)(u >> 8); outBuf[destPos++] = (Byte)u; outBuf[destPos++] = (Byte)(pm >> 8); outBuf[destPos++] = (Byte)pm; if (p->needInitProp) outBuf[destPos++] = p->propsByte; p->needInitProp = False; p->needInitState = False; destPos += packSize; p->srcPos += unpackSize; if (outStream) if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) return SZ_ERROR_WRITE; *packSizeRes = destPos; return SZ_OK; } } /* ---------- Lzma2 Props ---------- */ void Lzma2EncProps_Init(CLzma2EncProps *p) { LzmaEncProps_Init(&p->lzmaProps); p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO; p->numBlockThreads_Reduced = -1; p->numBlockThreads_Max = -1; p->numTotalThreads = -1; } void Lzma2EncProps_Normalize(CLzma2EncProps *p) { UInt64 fileSize; int t1, t1n, t2, t2r, t3; { CLzmaEncProps lzmaProps = p->lzmaProps; LzmaEncProps_Normalize(&lzmaProps); t1n = lzmaProps.numThreads; } t1 = p->lzmaProps.numThreads; t2 = p->numBlockThreads_Max; t3 = p->numTotalThreads; if (t2 > MTCODER_THREADS_MAX) t2 = MTCODER_THREADS_MAX; if (t3 <= 0) { if (t2 <= 0) t2 = 1; t3 = t1n * t2; } else if (t2 <= 0) { t2 = t3 / t1n; if (t2 == 0) { t1 = 1; t2 = t3; } if (t2 > MTCODER_THREADS_MAX) t2 = MTCODER_THREADS_MAX; } else if (t1 <= 0) { t1 = t3 / t2; if (t1 == 0) t1 = 1; } else t3 = t1n * t2; p->lzmaProps.numThreads = t1; t2r = t2; fileSize = p->lzmaProps.reduceSize; if ( p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID && p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) p->lzmaProps.reduceSize = p->blockSize; LzmaEncProps_Normalize(&p->lzmaProps); p->lzmaProps.reduceSize = fileSize; t1 = p->lzmaProps.numThreads; if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) { t2r = t2 = 1; t3 = t1; } else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1) { /* if there is no block multi-threading, we use SOLID block */ p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; } else { if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) { const UInt32 kMinSize = (UInt32)1 << 20; const UInt32 kMaxSize = (UInt32)1 << 28; const UInt32 dictSize = p->lzmaProps.dictSize; UInt64 blockSize = (UInt64)dictSize << 2; if (blockSize < kMinSize) blockSize = kMinSize; if (blockSize > kMaxSize) blockSize = kMaxSize; if (blockSize < dictSize) blockSize = dictSize; blockSize += (kMinSize - 1); blockSize &= ~(UInt64)(kMinSize - 1); p->blockSize = blockSize; } if (t2 > 1 && fileSize != (UInt64)(Int64)-1) { UInt64 numBlocks = fileSize / p->blockSize; if (numBlocks * p->blockSize != fileSize) numBlocks++; if (numBlocks < (unsigned)t2) { t2r = (int)numBlocks; if (t2r == 0) t2r = 1; t3 = t1 * t2r; } } } p->numBlockThreads_Max = t2; p->numBlockThreads_Reduced = t2r; p->numTotalThreads = t3; } static SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize) { return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; } /* ---------- Lzma2 ---------- */ struct CLzma2Enc { Byte propEncoded; CLzma2EncProps props; UInt64 expectedDataSize; Byte *tempBufLzma; ISzAllocPtr alloc; ISzAllocPtr allocBig; CLzma2EncInt coders[MTCODER_THREADS_MAX]; #ifndef Z7_ST ISeqOutStreamPtr outStream; Byte *outBuf; size_t outBuf_Rem; /* remainder in outBuf */ size_t outBufSize; /* size of allocated outBufs[i] */ size_t outBufsDataSizes[MTCODER_BLOCKS_MAX]; BoolInt mtCoder_WasConstructed; CMtCoder mtCoder; Byte *outBufs[MTCODER_BLOCKS_MAX]; #endif }; CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); if (!p) return NULL; Lzma2EncProps_Init(&p->props); Lzma2EncProps_Normalize(&p->props); p->expectedDataSize = (UInt64)(Int64)-1; p->tempBufLzma = NULL; p->alloc = alloc; p->allocBig = allocBig; { unsigned i; for (i = 0; i < MTCODER_THREADS_MAX; i++) p->coders[i].enc = NULL; } #ifndef Z7_ST p->mtCoder_WasConstructed = False; { unsigned i; for (i = 0; i < MTCODER_BLOCKS_MAX; i++) p->outBufs[i] = NULL; p->outBufSize = 0; } #endif return (CLzma2EncHandle)p; } #ifndef Z7_ST static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) { unsigned i; for (i = 0; i < MTCODER_BLOCKS_MAX; i++) if (p->outBufs[i]) { ISzAlloc_Free(p->alloc, p->outBufs[i]); p->outBufs[i] = NULL; } p->outBufSize = 0; } #endif // #define GET_CLzma2Enc_p CLzma2Enc *p = (CLzma2Enc *)(void *)p; void Lzma2Enc_Destroy(CLzma2EncHandle p) { // GET_CLzma2Enc_p unsigned i; for (i = 0; i < MTCODER_THREADS_MAX; i++) { CLzma2EncInt *t = &p->coders[i]; if (t->enc) { LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); t->enc = NULL; } } #ifndef Z7_ST if (p->mtCoder_WasConstructed) { MtCoder_Destruct(&p->mtCoder); p->mtCoder_WasConstructed = False; } Lzma2Enc_FreeOutBufs(p); #endif ISzAlloc_Free(p->alloc, p->tempBufLzma); p->tempBufLzma = NULL; ISzAlloc_Free(p->alloc, p); } SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props) { // GET_CLzma2Enc_p CLzmaEncProps lzmaProps = props->lzmaProps; LzmaEncProps_Normalize(&lzmaProps); if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) return SZ_ERROR_PARAM; p->props = *props; Lzma2EncProps_Normalize(&p->props); return SZ_OK; } void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize) { // GET_CLzma2Enc_p p->expectedDataSize = expectedDataSiize; } Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p) { // GET_CLzma2Enc_p unsigned i; UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); for (i = 0; i < 40; i++) if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) break; return (Byte)i; } static SRes Lzma2Enc_EncodeMt1( CLzma2Enc *me, CLzma2EncInt *p, ISeqOutStreamPtr outStream, Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, const Byte *inData, size_t inDataSize, int finished, ICompressProgressPtr progress) { UInt64 unpackTotal = 0; UInt64 packTotal = 0; size_t outLim = 0; CLimitedSeqInStream limitedInStream; if (outBuf) { outLim = *outBufSize; *outBufSize = 0; } if (!p->enc) { p->propsAreSet = False; p->enc = LzmaEnc_Create(me->alloc); if (!p->enc) return SZ_ERROR_MEM; } limitedInStream.realStream = inStream; if (inStream) { limitedInStream.vt.Read = LimitedSeqInStream_Read; } if (!outBuf) { // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma if (!me->tempBufLzma) { me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); if (!me->tempBufLzma) return SZ_ERROR_MEM; } } RINOK(Lzma2EncInt_InitStream(p, &me->props)) for (;;) { SRes res = SZ_OK; SizeT inSizeCur = 0; Lzma2EncInt_InitBlock(p); LimitedSeqInStream_Init(&limitedInStream); limitedInStream.limit = me->props.blockSize; if (inStream) { UInt64 expected = (UInt64)(Int64)-1; // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize if (me->expectedDataSize != (UInt64)(Int64)-1 && me->expectedDataSize >= unpackTotal) expected = me->expectedDataSize - unpackTotal; if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID && expected > me->props.blockSize) expected = (size_t)me->props.blockSize; LzmaEnc_SetDataSize(p->enc, expected); RINOK(LzmaEnc_PrepareForLzma2(p->enc, &limitedInStream.vt, LZMA2_KEEP_WINDOW_SIZE, me->alloc, me->allocBig)) } else { inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal); if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID && inSizeCur > me->props.blockSize) inSizeCur = (SizeT)(size_t)me->props.blockSize; // LzmaEnc_SetDataSize(p->enc, inSizeCur); RINOK(LzmaEnc_MemPrepare(p->enc, inData + (size_t)unpackTotal, inSizeCur, LZMA2_KEEP_WINDOW_SIZE, me->alloc, me->allocBig)) } for (;;) { size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; if (outBuf) packSize = outLim - (size_t)packTotal; res = Lzma2EncInt_EncodeSubblock(p, outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, outBuf ? NULL : outStream); if (res != SZ_OK) break; packTotal += packSize; if (outBuf) *outBufSize = (size_t)packTotal; res = Progress(progress, unpackTotal + p->srcPos, packTotal); if (res != SZ_OK) break; /* if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) break; */ if (packSize == 0) break; } LzmaEnc_Finish(p->enc); unpackTotal += p->srcPos; RINOK(res) if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) return SZ_ERROR_FAIL; if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) { if (finished) { if (outBuf) { const size_t destPos = *outBufSize; if (destPos >= outLim) return SZ_ERROR_OUTPUT_EOF; outBuf[destPos] = LZMA2_CONTROL_EOF; // 0 *outBufSize = destPos + 1; } else { const Byte b = LZMA2_CONTROL_EOF; // 0; if (ISeqOutStream_Write(outStream, &b, 1) != 1) return SZ_ERROR_WRITE; } } return SZ_OK; } } } #ifndef Z7_ST static SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex, const Byte *src, size_t srcSize, int finished) { CLzma2Enc *me = (CLzma2Enc *)p; size_t destSize = me->outBufSize; SRes res; CMtProgressThunk progressThunk; Byte *dest = me->outBufs[outBufIndex]; me->outBufsDataSizes[outBufIndex] = 0; if (!dest) { dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); if (!dest) return SZ_ERROR_MEM; me->outBufs[outBufIndex] = dest; } MtProgressThunk_CreateVTable(&progressThunk); progressThunk.mtProgress = &me->mtCoder.mtProgress; progressThunk.inSize = 0; progressThunk.outSize = 0; res = Lzma2Enc_EncodeMt1(me, &me->coders[coderIndex], NULL, dest, &destSize, NULL, src, srcSize, finished, &progressThunk.vt); me->outBufsDataSizes[outBufIndex] = destSize; return res; } static SRes Lzma2Enc_MtCallback_Write(void *p, unsigned outBufIndex) { CLzma2Enc *me = (CLzma2Enc *)p; size_t size = me->outBufsDataSizes[outBufIndex]; const Byte *data = me->outBufs[outBufIndex]; if (me->outStream) return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; if (size > me->outBuf_Rem) return SZ_ERROR_OUTPUT_EOF; memcpy(me->outBuf, data, size); me->outBuf_Rem -= size; me->outBuf += size; return SZ_OK; } #endif SRes Lzma2Enc_Encode2(CLzma2EncHandle p, ISeqOutStreamPtr outStream, Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, const Byte *inData, size_t inDataSize, ICompressProgressPtr progress) { // GET_CLzma2Enc_p if (inStream && inData) return SZ_ERROR_PARAM; if (outStream && outBuf) return SZ_ERROR_PARAM; { unsigned i; for (i = 0; i < MTCODER_THREADS_MAX; i++) p->coders[i].propsAreSet = False; } #ifndef Z7_ST if (p->props.numBlockThreads_Reduced > 1) { IMtCoderCallback2 vt; if (!p->mtCoder_WasConstructed) { p->mtCoder_WasConstructed = True; MtCoder_Construct(&p->mtCoder); } vt.Code = Lzma2Enc_MtCallback_Code; vt.Write = Lzma2Enc_MtCallback_Write; p->outStream = outStream; p->outBuf = NULL; p->outBuf_Rem = 0; if (!outStream) { p->outBuf = outBuf; p->outBuf_Rem = *outBufSize; *outBufSize = 0; } p->mtCoder.allocBig = p->allocBig; p->mtCoder.progress = progress; p->mtCoder.inStream = inStream; p->mtCoder.inData = inData; p->mtCoder.inDataSize = inDataSize; p->mtCoder.mtCallback = &vt; p->mtCoder.mtCallbackObject = p; p->mtCoder.blockSize = (size_t)p->props.blockSize; if (p->mtCoder.blockSize != p->props.blockSize) return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ { const size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; if (destBlockSize < p->mtCoder.blockSize) return SZ_ERROR_PARAM; if (p->outBufSize != destBlockSize) Lzma2Enc_FreeOutBufs(p); p->outBufSize = destBlockSize; } p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max; p->mtCoder.expectedDataSize = p->expectedDataSize; { const SRes res = MtCoder_Code(&p->mtCoder); if (!outStream) *outBufSize = (size_t)(p->outBuf - outBuf); return res; } } #endif return Lzma2Enc_EncodeMt1(p, &p->coders[0], outStream, outBuf, outBufSize, inStream, inData, inDataSize, True, /* finished */ progress); } #undef PRF tmp41wklro_/C/Lzma2Enc.h0000444000175000001440000000334614415733200016114 0ustar nabijaczleweliusers/* Lzma2Enc.h -- LZMA2 Encoder 2023-04-13 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA2_ENC_H #define ZIP7_INC_LZMA2_ENC_H #include "LzmaEnc.h" EXTERN_C_BEGIN #define LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO 0 #define LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID ((UInt64)(Int64)-1) typedef struct { CLzmaEncProps lzmaProps; UInt64 blockSize; int numBlockThreads_Reduced; int numBlockThreads_Max; int numTotalThreads; } CLzma2EncProps; void Lzma2EncProps_Init(CLzma2EncProps *p); void Lzma2EncProps_Normalize(CLzma2EncProps *p); /* ---------- CLzmaEnc2Handle Interface ---------- */ /* Lzma2Enc_* functions can return the following exit codes: SRes: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - ISeqOutStream write callback error SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) */ typedef struct CLzma2Enc CLzma2Enc; typedef CLzma2Enc * CLzma2EncHandle; // Z7_DECLARE_HANDLE(CLzma2EncHandle) CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); void Lzma2Enc_Destroy(CLzma2EncHandle p); SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize); Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); SRes Lzma2Enc_Encode2(CLzma2EncHandle p, ISeqOutStreamPtr outStream, Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, const Byte *inData, size_t inDataSize, ICompressProgressPtr progress); EXTERN_C_END #endif tmp41wklro_/C/Lzma86.h0000444000175000001440000000632014400367520015557 0ustar nabijaczleweliusers/* Lzma86.h -- LZMA + x86 (BCJ) Filter 2023-03-03 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA86_H #define ZIP7_INC_LZMA86_H #include "7zTypes.h" EXTERN_C_BEGIN #define LZMA86_SIZE_OFFSET (1 + 5) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, pure LZMA = 1 - x86 filter + LZMA 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); EXTERN_C_END #endif tmp41wklro_/C/Lzma86Dec.c0000444000175000001440000000244214400367520016167 0ustar nabijaczleweliusers/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2023-03-03 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Lzma86.h" #include "Alloc.h" #include "Bra.h" #include "LzmaDec.h" SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; z7_BranchConvSt_X86_Dec(dest, *destLen, 0, &x86State); } return SZ_OK; } tmp41wklro_/C/Lzma86Enc.c0000444000175000001440000000520314400367520016177 0ustar nabijaczleweliusers/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2023-03-03 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "Lzma86.h" #include "Alloc.h" #include "Bra.h" #include "LzmaEnc.h" int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; BoolInt useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; z7_BranchConvSt_X86_Enc(filteredStream, srcLen, 0, &x86State); } } { size_t minSize = 0; BoolInt bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (Byte)(bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } tmp41wklro_/C/LzmaDec.c0000444000175000001440000011504714414055040016013 0ustar nabijaczleweliusers/* LzmaDec.c -- LZMA Decoder 2023-04-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include /* #include "CpuArch.h" */ #include "LzmaDec.h" // #define kNumTopBits 24 #define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define RC_INIT_SIZE 5 #ifndef Z7_LZMA_DEC_OPT #define kNumMoveBits 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p) i = (i + i); A0; } else \ { UPDATE_1(p) i = (i + i) + 1; A1; } #define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); } #define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \ { UPDATE_0(p + i) A0; } else \ { UPDATE_1(p + i) A1; } #define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; ) #define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; ) #define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; ) #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define Z7_LZMA_SIZE_OPT */ #ifdef Z7_LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i) \ TREE_GET_BIT(probs, i) \ TREE_GET_BIT(probs, i) \ TREE_GET_BIT(probs, i) \ TREE_GET_BIT(probs, i) \ TREE_GET_BIT(probs, i) \ i -= 0x40; } #endif #define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol) #define MATCHED_LITER_DEC \ matchByte += matchByte; \ bit = offs; \ offs &= matchByte; \ probLit = prob + (offs + bit + symbol); \ GET_BIT2(probLit, symbol, offs ^= bit; , ;) #endif // Z7_LZMA_DEC_OPT #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK i = (i + i); A0; } else \ { UPDATE_1_CHECK i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \ { UPDATE_0_CHECK i += m; m += m; } else \ { UPDATE_1_CHECK m += m; i += m; } #define kNumPosBitsMax 4 #define kNumPosStatesMax (1 << kNumPosBitsMax) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define LenLow 0 #define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits)) #define kNumLenProbs (LenHigh + kLenNumHighSymbols) #define LenChoice LenLow #define LenChoice2 (LenLow + (1 << kLenNumLowBits)) #define kNumStates 12 #define kNumStates2 16 #define kNumLitStates 7 #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #define kNumPosSlotBits 6 #define kNumLenToPosStates 4 #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kMatchMinLen 2 #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) #define kMatchSpecLen_Error_Data (1 << 9) #define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1) /* External ASM code needs same CLzmaProb array layout. So don't change it. */ /* (probs_1664) is faster and better for code size at some platforms */ /* #ifdef MY_CPU_X86_OR_AMD64 */ #define kStartOffset 1664 #define GET_PROBS p->probs_1664 /* #define GET_PROBS p->probs + kStartOffset #else #define kStartOffset 0 #define GET_PROBS p->probs #endif */ #define SpecPos (-kStartOffset) #define IsRep0Long (SpecPos + kNumFullDistances) #define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) #define LenCoder (RepLenCoder + kNumLenProbs) #define IsMatch (LenCoder + kNumLenProbs) #define Align (IsMatch + (kNumStates2 << kNumPosBitsMax)) #define IsRep (Align + kAlignTableSize) #define IsRepG0 (IsRep + kNumStates) #define IsRepG1 (IsRepG0 + kNumStates) #define IsRepG2 (IsRepG1 + kNumStates) #define PosSlot (IsRepG2 + kNumStates) #define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) #define NUM_BASE_PROBS (Literal + kStartOffset) #if Align != 0 && kStartOffset != 0 #error Stop_Compiling_Bad_LZMA_kAlign #endif #if NUM_BASE_PROBS != 1984 #error Stop_Compiling_Bad_LZMA_PROBS #endif #define LZMA_LIT_SIZE 0x300 #define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4) #define COMBINED_PS_STATE (posState + state) #define GET_LEN_STATE (posState) #define LZMA_DIC_MIN (1 << 12) /* p->remainLen : shows status of LZMA decoder: < kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset = kMatchSpecLenStart : the LZMA stream was finished with end mark = kMatchSpecLenStart + 1 : need init range coder = kMatchSpecLenStart + 2 : need init range coder and state = kMatchSpecLen_Error_Fail : Internal Code Failure = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error */ /* ---------- LZMA_DECODE_REAL ---------- */ /* LzmaDec_DecodeReal_3() can be implemented in external ASM file. 3 - is the code compatibility version of that function for check at link time. */ #define LZMA_DECODE_REAL LzmaDec_DecodeReal_3 /* LZMA_DECODE_REAL() In: RangeCoder is normalized if (p->dicPos == limit) { LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary, the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later. } Processing: The first LZMA symbol will be decoded in any case. All main checks for limits are at the end of main loop, It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit), RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX), that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit. So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte. Out: RangeCoder is normalized Result: SZ_OK - OK p->remainLen: < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset = kMatchSpecLenStart : the LZMA stream was finished with end mark SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary p->remainLen : undefined p->reps[*] : undefined */ #ifdef Z7_LZMA_DEC_OPT int Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); #else static int Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = GET_PROBS; unsigned state = (unsigned)p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lc = p->prop.lc; unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = CALC_POS_STATE(processedPos, pbMask); prob = probs + IsMatch + COMBINED_PS_STATE; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob) prob = probs + Literal; if (processedPos != 0 || checkDicSize != 0) prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); processedPos++; if (state < kNumLitStates) { state -= (state < 4) ? state : 3; symbol = 1; #ifdef Z7_LZMA_SIZE_OPT do { NORMAL_LITER_DEC } while (symbol < 0x100); #else NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC NORMAL_LITER_DEC #endif } else { unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; unsigned offs = 0x100; state -= (state < 10) ? 3 : 6; symbol = 1; #ifdef Z7_LZMA_SIZE_OPT do { unsigned bit; CLzmaProb *probLit; MATCHED_LITER_DEC } while (symbol < 0x100); #else { unsigned bit; CLzmaProb *probLit; MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC MATCHED_LITER_DEC } #endif } dic[dicPos++] = (Byte)symbol; continue; } { UPDATE_1(prob) prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob) state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob) prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob) prob = probs + IsRep0Long + COMBINED_PS_STATE; IF_BIT_0(prob) { UPDATE_0(prob) // that case was checked before with kBadRepCode // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; } // The caller doesn't allow (dicPos == limit) case here // so we don't need the following check: // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; } dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob) } else { UInt32 distance; UPDATE_1(prob) prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob) distance = rep1; } else { UPDATE_1(prob) prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob) distance = rep2; } else { UPDATE_1(prob) distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } #ifdef Z7_LZMA_SIZE_OPT { unsigned lim, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE; offset = 0; lim = (1 << kLenNumLowBits); } else { UPDATE_1(probLen) probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); offset = kLenNumLowSymbols; lim = (1 << kLenNumLowBits); } else { UPDATE_1(probLen) probLen = prob + LenHigh; offset = kLenNumLowSymbols * 2; lim = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, lim, len) len += offset; } #else { CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE; len = 1; TREE_GET_BIT(probLen, len) TREE_GET_BIT(probLen, len) TREE_GET_BIT(probLen, len) len -= 8; } else { UPDATE_1(probLen) probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen) probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); len = 1; TREE_GET_BIT(probLen, len) TREE_GET_BIT(probLen, len) TREE_GET_BIT(probLen, len) } else { UPDATE_1(probLen) probLen = prob + LenHigh; TREE_DECODE(probLen, (1 << kLenNumHighBits), len) len += kLenNumLowSymbols * 2; } } } #endif if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance) if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos; { UInt32 m = 1; distance++; do { REV_BIT_VAR(prob, distance, m) } while (--numDirectBits); distance -= m; } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; REV_BIT_CONST(prob, i, 1) REV_BIT_CONST(prob, i, 2) REV_BIT_CONST(prob, i, 4) REV_BIT_LAST (prob, i, 8) distance |= i; } if (distance == (UInt32)0xFFFFFFFF) { len = kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) { len += kMatchSpecLen_Error_Data + kMatchMinLen; // len = kMatchSpecLen_Error_Data; // len += kMatchMinLen; break; } } len += kMatchMinLen; { SizeT rem; unsigned curLen; SizeT pos; if ((rem = limit - dicPos) == 0) { /* We stop decoding and return SZ_OK, and we can resume decoding later. Any error conditions can be tested later in caller code. For more strict mode we can stop decoding with error // len += kMatchSpecLen_Error_Data; */ break; } curLen = ((rem < len) ? (unsigned)rem : len); pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); processedPos += (UInt32)curLen; len -= curLen; if (curLen <= dicBufSize - pos) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += (SizeT)curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE p->buf = buf; p->range = range; p->code = code; p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too. p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = (UInt32)state; if (len >= kMatchSpecLen_Error_Data) return SZ_ERROR_DATA; return SZ_OK; } #endif static void Z7_FASTCALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { unsigned len = (unsigned)p->remainLen; if (len == 0 /* || len >= kMatchSpecLenStart */) return; { SizeT dicPos = p->dicPos; Byte *dic; SizeT dicBufSize; SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ { SizeT rem = limit - dicPos; if (rem < len) { len = (unsigned)(rem); if (len == 0) return; } } if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += (UInt32)len; p->remainLen -= (UInt32)len; dic = p->dic; rep0 = p->reps[0]; dicBufSize = p->dicBufSize; do { dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; } while (--len); p->dicPos = dicPos; } } /* At staring of new stream we have one of the following symbols: - Literal - is allowed - Non-Rep-Match - is allowed only if it's end marker symbol - Rep-Match - is not allowed We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code */ #define kRange0 0xFFFFFFFF #define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) #define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) #if kBadRepCode != (0xC0000000 - 0x400) #error Stop_Compiling_Bad_LZMA_Check #endif /* LzmaDec_DecodeReal2(): It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize). We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(), and we support the following state of (p->checkDicSize): if (total_processed < p->prop.dicSize) then { (total_processed == p->processedPos) (p->checkDicSize == 0) } else (p->checkDicSize == p->prop.dicSize) */ static int Z7_FASTCALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit = p->dicPos + rem; } { int res = LZMA_DECODE_REAL(p, limit, bufLimit); if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; return res; } } typedef enum { DUMMY_INPUT_EOF, /* need more input data */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; #define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH) static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = *bufOut; const CLzmaProb *probs = GET_PROBS; unsigned state = (unsigned)p->state; ELzmaDummy res; for (;;) { const CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1); prob = probs + IsMatch + COMBINED_PS_STATE; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += ((UInt32)LZMA_LIT_SIZE * ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) + ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + (p->dicPos < p->reps[0] ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; const CLzmaProb *probLit; matchByte += matchByte; bit = offs; offs &= matchByte; probLit = prob + (offs + bit + symbol); GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; ) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK prob = probs + IsRep0Long + COMBINED_PS_STATE; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK break; } else { UPDATE_1_CHECK } } else { UPDATE_1_CHECK prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK } else { UPDATE_1_CHECK prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK } else { UPDATE_1_CHECK } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; const CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK probLen = prob + LenLow + GET_LEN_STATE; offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK probLen = prob + LenHigh; offset = kLenNumLowSymbols * 2; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len) len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot) if (posSlot >= kStartPosModelIndex) { unsigned numDirectBits = ((posSlot >> 1) - 1); if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; unsigned m = 1; do { REV_BIT_CHECK(prob, i, m) } while (--numDirectBits); } } } } break; } NORMALIZE_CHECK *bufOut = buf; return res; } void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState) { p->remainLen = kMatchSpecLenStart + 1; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->remainLen = kMatchSpecLenStart + 2; } if (initState) p->remainLen = kMatchSpecLenStart + 2; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } /* LZMA supports optional end_marker. So the decoder can lookahead for one additional LZMA-Symbol to check end_marker. That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream. When the decoder reaches dicLimit, it looks (finishMode) parameter: if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways: 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA. 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller must check (status) value. The caller can show the error, if the end of stream is expected, and the (status) is noit LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK. */ #define RETURN_NOT_FINISHED_FOR_FINISH \ *status = LZMA_STATUS_NOT_FINISHED; \ return SZ_ERROR_DATA; // for strict mode // return SZ_OK; // for relaxed mode SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; *status = LZMA_STATUS_NOT_SPECIFIED; if (p->remainLen > kMatchSpecLenStart) { if (p->remainLen > kMatchSpecLenStart + 2) return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA; for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize != 0 && p->tempBuf[0] != 0) return SZ_ERROR_DATA; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } p->code = ((UInt32)p->tempBuf[1] << 24) | ((UInt32)p->tempBuf[2] << 16) | ((UInt32)p->tempBuf[3] << 8) | ((UInt32)p->tempBuf[4]); if (p->checkDicSize == 0 && p->processedPos == 0 && p->code >= kBadRepCode) return SZ_ERROR_DATA; p->range = 0xFFFFFFFF; p->tempBufSize = 0; if (p->remainLen > kMatchSpecLenStart + 1) { SizeT numProbs = LzmaProps_GetNumProbs(&p->prop); SizeT i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; } p->remainLen = 0; } for (;;) { if (p->remainLen == kMatchSpecLenStart) { if (p->code != 0) return SZ_ERROR_DATA; *status = LZMA_STATUS_FINISHED_WITH_MARK; return SZ_OK; } LzmaDec_WriteRem(p, dicLimit); { // (p->remainLen == 0 || p->dicPos == dicLimit) int checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { RETURN_NOT_FINISHED_FOR_FINISH } checkEndMarkNow = 1; } // (p->remainLen == 0) if (p->tempBufSize == 0) { const Byte *bufLimit; int dummyProcessed = -1; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { const Byte *bufOut = src + inSize; ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut); if (dummyRes == DUMMY_INPUT_EOF) { size_t i; if (inSize >= LZMA_REQUIRED_INPUT_MAX) break; (*srcLen) += inSize; p->tempBufSize = (unsigned)inSize; for (i = 0; i < inSize; i++) p->tempBuf[i] = src[i]; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } dummyProcessed = (int)(bufOut - src); if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX) break; if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) { unsigned i; (*srcLen) += (unsigned)dummyProcessed; p->tempBufSize = (unsigned)dummyProcessed; for (i = 0; i < (unsigned)dummyProcessed; i++) p->tempBuf[i] = src[i]; // p->remainLen = kMatchSpecLen_Error_Data; RETURN_NOT_FINISHED_FOR_FINISH } bufLimit = src; // we will decode only one iteration } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; { int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit); SizeT processed = (SizeT)(p->buf - src); if (dummyProcessed < 0) { if (processed > inSize) break; } else if ((unsigned)dummyProcessed != processed) break; src += processed; inSize -= processed; (*srcLen) += processed; if (res != SZ_OK) { p->remainLen = kMatchSpecLen_Error_Data; return SZ_ERROR_DATA; } } continue; } { // we have some data in (p->tempBuf) // in strict mode: tempBufSize is not enough for one Symbol decoding. // in relaxed mode: tempBufSize not larger than required for one Symbol decoding. unsigned rem = p->tempBufSize; unsigned ahead = 0; int dummyProcessed = -1; while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize) p->tempBuf[rem++] = src[ahead++]; // ahead - the size of new data copied from (src) to (p->tempBuf) // rem - the size of temp buffer including new data from (src) if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { const Byte *bufOut = p->tempBuf + rem; ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut); if (dummyRes == DUMMY_INPUT_EOF) { if (rem >= LZMA_REQUIRED_INPUT_MAX) break; p->tempBufSize = rem; (*srcLen) += (SizeT)ahead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } dummyProcessed = (int)(bufOut - p->tempBuf); if ((unsigned)dummyProcessed < p->tempBufSize) break; if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) { (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize; p->tempBufSize = (unsigned)dummyProcessed; // p->remainLen = kMatchSpecLen_Error_Data; RETURN_NOT_FINISHED_FOR_FINISH } } p->buf = p->tempBuf; { // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf) int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf); SizeT processed = (SizeT)(p->buf - p->tempBuf); rem = p->tempBufSize; if (dummyProcessed < 0) { if (processed > LZMA_REQUIRED_INPUT_MAX) break; if (processed < rem) break; } else if ((unsigned)dummyProcessed != processed) break; processed -= rem; src += processed; inSize -= processed; (*srcLen) += processed; p->tempBufSize = 0; if (res != SZ_OK) { p->remainLen = kMatchSpecLen_Error_Data; return SZ_ERROR_DATA; } } } } } /* Some unexpected error: internal error of code, memory corruption or hardware failure */ p->remainLen = kMatchSpecLen_Error_Fail; return SZ_ERROR_FAIL; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->probs); p->probs = NULL; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->dic); p->dic = NULL; } void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = (Byte)(d % 9); d /= 9; p->pb = (Byte)(d / 5); p->lp = (Byte)(d % 5); return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (!p->probs || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb)); if (!p->probs) return SZ_ERROR_MEM; p->probs_1664 = p->probs + 1664; p->numProbs = numProbs; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)) RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)) p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)) RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)) { UInt32 dictSize = propNew.dicSize; SizeT mask = ((UInt32)1 << 12) - 1; if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1; else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1; dicBufSize = ((SizeT)dictSize + mask) & ~mask; if (dicBufSize < dictSize) dicBufSize = dictSize; } if (!p->dic || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize); if (!p->dic) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) { CLzmaDec p; SRes res; SizeT outSize = *destLen, inSize = *srcLen; *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_CONSTRUCT(&p) RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)) p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); *destLen = p.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; LzmaDec_FreeProbs(&p, alloc); return res; } tmp41wklro_/C/LzmaDec.h0000444000175000001440000001635314412267100016020 0ustar nabijaczleweliusers/* LzmaDec.h -- LZMA Decoder 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA_DEC_H #define ZIP7_INC_LZMA_DEC_H #include "7zTypes.h" EXTERN_C_BEGIN /* #define Z7_LZMA_PROB32 */ /* Z7_LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ typedef #ifdef Z7_LZMA_PROB32 UInt32 #else UInt16 #endif CLzmaProb; /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct { Byte lc; Byte lp; Byte pb; Byte _pad_; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { /* Don't change this structure. ASM code can use it. */ CLzmaProps prop; CLzmaProb *probs; CLzmaProb *probs_1664; Byte *dic; SizeT dicBufSize; SizeT dicPos; const Byte *buf; UInt32 range; UInt32 code; UInt32 processedPos; UInt32 checkDicSize; UInt32 reps[4]; UInt32 state; UInt32 remainLen; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_CONSTRUCT(p) { (p)->dic = NULL; (p)->probs = NULL; } #define LzmaDec_Construct(p) LzmaDec_CONSTRUCT(p) void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: - Stream with end mark. That end mark adds about 6 bytes to compressed size. - Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Construct() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); EXTERN_C_END #endif tmp41wklro_/C/LzmaEnc.c0000444000175000001440000024306414554141600016031 0ustar nabijaczleweliusers/* LzmaEnc.c -- LZMA Encoder 2024-01-24: Igor Pavlov : Public domain */ #include "Precomp.h" #include /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include #endif #include "CpuArch.h" #include "LzmaEnc.h" #include "LzFind.h" #ifndef Z7_ST #include "LzFindMt.h" #endif /* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p); void LzmaEnc_Finish(CLzmaEncHandle p); void LzmaEnc_SaveState(CLzmaEncHandle p); void LzmaEnc_RestoreState(CLzmaEncHandle p); #ifdef SHOW_STAT static unsigned g_STAT_OFFSET = 0; #endif /* for good normalization speed we still reserve 256 MB before 4 GB range */ #define kLzmaMaxHistorySize ((UInt32)15 << 28) // #define kNumTopBits 24 #define kTopValue ((UInt32)1 << 24) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 // #define kBitPrice (1 << kNumBitPriceShiftBits) #define REP_LEN_COUNT 64 void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->reduceSize = (UInt64)(Int64)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->numHashOutBits = 0; p->writeEndMark = 0; p->affinity = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : ( level <= 6 ? ((UInt32)1 << (level + 19)) : ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) ))); if (p->dictSize > p->reduceSize) { UInt32 v = (UInt32)p->reduceSize; const UInt32 kReduceMin = ((UInt32)1 << 12); if (v < kReduceMin) v = kReduceMin; if (p->dictSize > v) p->dictSize = v; } if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifndef Z7_ST ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* x86/x64: BSR: IF (SRC == 0) ZF = 1, DEST is undefined; AMD : DEST is unchanged; IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit BSR is slow in some processors LZCNT: IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64) IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits IF (DEST == 0) ZF = 1; LZCNT works only in new processors starting from Haswell. if LZCNT is not supported by processor, then it's executed as BSR. LZCNT can be faster than BSR, if supported. */ // #define LZMA_LOG_BSR #if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */ #if (defined(__clang__) && (__clang_major__ >= 6)) \ || (defined(__GNUC__) && (__GNUC__ >= 6)) #define LZMA_LOG_BSR #elif defined(_MSC_VER) && (_MSC_VER >= 1300) // #if defined(MY_CPU_ARM_OR_ARM64) #define LZMA_LOG_BSR // #endif #endif #endif // #include #ifdef LZMA_LOG_BSR #if defined(__clang__) \ || defined(__GNUC__) /* C code: : (30 - __builtin_clz(x)) gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31) clang10 for x64 : 31 + (bsr(x) xor -32) */ #define MY_clz(x) ((unsigned)__builtin_clz(x)) // __lzcnt32 // __builtin_ia32_lzcnt_u32 #else // #if defined(_MSC_VER) #ifdef MY_CPU_ARM_OR_ARM64 #define MY_clz _CountLeadingZeros #else // if defined(MY_CPU_X86_OR_AMD64) // #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU) // _BitScanReverse code is not optimal for some MSVC compilers #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \ res = (zz + zz) + (pos >> zz); } #endif // MY_CPU_X86_OR_AMD64 #endif // _MSC_VER #ifndef BSR2_RET #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \ res = (zz + zz) + (pos >> zz); } #endif unsigned GetPosSlot1(UInt32 pos); unsigned GetPosSlot1(UInt32 pos) { unsigned res; BSR2_RET(pos, res) return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res) } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res) } #else // ! LZMA_LOG_BSR #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) static void LzmaEnc_FastPosInit(Byte *g_FastPos) { unsigned slot; g_FastPos[0] = 0; g_FastPos[1] = 1; g_FastPos += 2; for (slot = 2; slot < kNumLogBits * 2; slot++) { size_t k = ((size_t)1 << ((slot >> 1) - 1)); size_t j; for (j = 0; j < k; j++) g_FastPos[j] = (Byte)slot; g_FastPos += k; } } /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */ /* #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> zz] + (zz * 2); } */ /* #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \ res = p->g_FastPos[pos >> zz] + (zz * 2); } */ #define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \ res = p->g_FastPos[pos >> zz] + (zz * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } #endif // LZMA_LOG_BSR #define LZMA_NUM_REPS 4 typedef UInt16 CState; typedef UInt16 CExtra; typedef struct { UInt32 price; CState state; CExtra extra; // 0 : normal // 1 : LIT : MATCH // > 1 : MATCH (extra-1) : LIT : REP0 (len) UInt32 len; UInt32 dist; UInt32 reps[LZMA_NUM_REPS]; } COptimal; // 18.06 #define kNumOpts (1 << 11) #define kPackReserve (kNumOpts * 8) // #define kNumOpts (1 << 12) // #define kPackReserve (1 + kNumOpts * 2) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 // #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) typedef #ifdef Z7_LZMA_PROB32 UInt32 #else UInt16 #endif CLzmaProb; #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { unsigned tableSize; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2]; // UInt32 prices2[kLenNumSymbolsTotal]; } CLenPriceEnc; #define GET_PRICE_LEN(p, posState, len) \ ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN]) /* #define GET_PRICE_LEN(p, posState, len) \ ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9))) */ typedef struct { UInt32 range; unsigned cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStreamPtr outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct { CLzmaProb *litProbs; unsigned state; UInt32 reps[LZMA_NUM_REPS]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances]; CLenEnc lenProbs; CLenEnc repLenProbs; } CSaveState; typedef UInt32 CProbPrice; struct CLzmaEnc { void *matchFinderObj; IMatchFinder2 matchFinder; unsigned optCur; unsigned optEnd; unsigned longestMatchLen; unsigned numPairs; UInt32 numAvail; unsigned state; unsigned numFastBytes; unsigned additionalOffset; UInt32 reps[LZMA_NUM_REPS]; unsigned lpMask, pbMask; CLzmaProb *litProbs; CRangeEnc rc; UInt32 backRes; unsigned lc, lp, pb; unsigned lclp; BoolInt fastMode; BoolInt writeEndMark; BoolInt finished; BoolInt multiThread; BoolInt needInit; // BoolInt _maxMode; UInt64 nowPos64; unsigned matchPriceCount; // unsigned alignPriceCount; int repLenEncCounter; unsigned distTableSize; UInt32 dictSize; SRes result; #ifndef Z7_ST BoolInt mtMode; // begin of CMatchFinderMt is used in LZ thread CMatchFinderMt matchFinderMt; // end of CMatchFinderMt is used in BT and HASH threads // #else // CMatchFinder matchFinderBase; #endif CMatchFinder matchFinderBase; // we suppose that we have 8-bytes alignment after CMatchFinder #ifndef Z7_ST Byte pad[128]; #endif // LZ thread CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; // we want {len , dist} pairs to be 8-bytes aligned in matches array UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2]; // we want 8-bytes alignment here UInt32 alignPrices[kAlignTableSize]; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances]; CLenEnc lenProbs; CLenEnc repLenProbs; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; COptimal opt[kNumOpts]; CSaveState saveState; // BoolInt mf_Failure; #ifndef Z7_ST Byte pad2[128]; #endif }; #define MFB (p->matchFinderBase) /* #ifndef Z7_ST #define MFB (p->matchFinderMt.MatchFinder) #endif */ // #define GET_CLzmaEnc_p CLzmaEnc *p = (CLzmaEnc*)(void *)p; // #define GET_const_CLzmaEnc_p const CLzmaEnc *p = (const CLzmaEnc*)(const void *)p; #define COPY_ARR(dest, src, arr) memcpy((dest)->arr, (src)->arr, sizeof((src)->arr)); #define COPY_LZMA_ENC_STATE(d, s, p) \ (d)->state = (s)->state; \ COPY_ARR(d, s, reps) \ COPY_ARR(d, s, posAlignEncoder) \ COPY_ARR(d, s, isRep) \ COPY_ARR(d, s, isRepG0) \ COPY_ARR(d, s, isRepG1) \ COPY_ARR(d, s, isRepG2) \ COPY_ARR(d, s, isMatch) \ COPY_ARR(d, s, isRep0Long) \ COPY_ARR(d, s, posSlotEncoder) \ COPY_ARR(d, s, posEncoders) \ (d)->lenProbs = (s)->lenProbs; \ (d)->repLenProbs = (s)->repLenProbs; \ memcpy((d)->litProbs, (s)->litProbs, ((size_t)0x300 * sizeof(CLzmaProb)) << (p)->lclp); void LzmaEnc_SaveState(CLzmaEncHandle p) { // GET_CLzmaEnc_p CSaveState *v = &p->saveState; COPY_LZMA_ENC_STATE(v, p, p) } void LzmaEnc_RestoreState(CLzmaEncHandle p) { // GET_CLzmaEnc_p const CSaveState *v = &p->saveState; COPY_LZMA_ENC_STATE(p, v, p) } Z7_NO_INLINE SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2) { // GET_CLzmaEnc_p CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX) return SZ_ERROR_PARAM; if (props.dictSize > kLzmaMaxHistorySize) props.dictSize = kLzmaMaxHistorySize; #ifndef LZMA_LOG_BSR { const UInt64 dict64 = props.dictSize; if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress)) return SZ_ERROR_PARAM; } #endif p->dictSize = props.dictSize; { unsigned fb = (unsigned)props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = (unsigned)props.lc; p->lp = (unsigned)props.lp; p->pb = (unsigned)props.pb; p->fastMode = (props.algo == 0); // p->_maxMode = True; MFB.btMode = (Byte)(props.btMode ? 1 : 0); // MFB.btMode = (Byte)(props.btMode); { unsigned numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes; } if (props.numHashBytes >= 5) numHashBytes = 5; MFB.numHashBytes = numHashBytes; // MFB.numHashBytes_Min = 2; MFB.numHashOutBits = (Byte)props.numHashOutBits; } MFB.cutValue = props.mc; p->writeEndMark = (BoolInt)props.writeEndMark; #ifndef Z7_ST /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); p->matchFinderMt.btSync.affinity = p->matchFinderMt.hashSync.affinity = props.affinity; #endif return SZ_OK; } void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize) { // GET_CLzmaEnc_p MFB.expectedDataSize = expectedDataSiize; } #define kState_Start 0 #define kState_LitAfterMatch 4 #define kState_LitAfterRep 5 #define kState_MatchAfterLit 7 #define kState_RepAfterLit 8 static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsLitState(s) ((s) < 7) #define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = NULL; p->bufBase = NULL; } #define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) { if (!p->bufBase) { p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE); if (!p->bufBase) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->bufBase); p->bufBase = NULL; } static void RangeEnc_Init(CRangeEnc *p) { p->range = 0xFFFFFFFF; p->cache = 0; p->low = 0; p->cacheSize = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } Z7_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) { const size_t num = (size_t)(p->buf - p->bufBase); if (p->res == SZ_OK) { if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; } p->processed += num; p->buf = p->bufBase; } Z7_NO_INLINE static void Z7_FASTCALL RangeEnc_ShiftLow(CRangeEnc *p) { UInt32 low = (UInt32)p->low; unsigned high = (unsigned)(p->low >> 32); p->low = (UInt32)(low << 8); if (low < (UInt32)0xFF000000 || high != 0) { { Byte *buf = p->buf; *buf++ = (Byte)(p->cache + high); p->cache = (unsigned)(low >> 24); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); if (p->cacheSize == 0) return; } high += 0xFF; for (;;) { Byte *buf = p->buf; *buf++ = (Byte)(high); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); if (--p->cacheSize == 0) return; } } p->cacheSize++; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } #define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); } #define RC_BIT_PRE(p, prob) \ ttt = *(prob); \ newBound = (range >> kNumBitModelTotalBits) * ttt; // #define Z7_LZMA_ENC_USE_BRANCH #ifdef Z7_LZMA_ENC_USE_BRANCH #define RC_BIT(p, prob, bit) { \ RC_BIT_PRE(p, prob) \ if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \ else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \ *(prob) = (CLzmaProb)ttt; \ RC_NORM(p) \ } #else #define RC_BIT(p, prob, bit) { \ UInt32 mask; \ RC_BIT_PRE(p, prob) \ mask = 0 - (UInt32)bit; \ range &= mask; \ mask &= newBound; \ range -= mask; \ (p)->low += mask; \ mask = (UInt32)bit - 1; \ range += newBound & mask; \ mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ mask += ((1 << kNumMoveBits) - 1); \ ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \ *(prob) = (CLzmaProb)ttt; \ RC_NORM(p) \ } #endif #define RC_BIT_0_BASE(p, prob) \ range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define RC_BIT_1_BASE(p, prob) \ range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \ #define RC_BIT_0(p, prob) \ RC_BIT_0_BASE(p, prob) \ RC_NORM(p) #define RC_BIT_1(p, prob) \ RC_BIT_1_BASE(p, prob) \ RC_NORM(p) static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob) { UInt32 range, ttt, newBound; range = p->range; RC_BIT_PRE(p, prob) RC_BIT_0(p, prob) p->range = range; } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym) { UInt32 range = p->range; sym |= 0x100; do { UInt32 ttt, newBound; // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1); CLzmaProb *prob = probs + (sym >> 8); UInt32 bit = (sym >> 7) & 1; sym <<= 1; RC_BIT(p, prob, bit) } while (sym < 0x10000); p->range = range; } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte) { UInt32 range = p->range; UInt32 offs = 0x100; sym |= 0x100; do { UInt32 ttt, newBound; CLzmaProb *prob; UInt32 bit; matchByte <<= 1; // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1); prob = probs + (offs + (matchByte & offs) + (sym >> 8)); bit = (sym >> 7) & 1; sym <<= 1; offs &= ~(matchByte ^ sym); RC_BIT(p, prob, bit) } while (sym < 0x10000); p->range = range; } static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) { UInt32 i; for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++) { const unsigned kCyclesBits = kNumBitPriceShiftBits; UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1)); unsigned bitCount = 0; unsigned j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); // printf("\n%3d: %5d", i, ProbPrices[i]); } } #define GET_PRICE(prob, bit) \ p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits] #define GET_PRICEa(prob, bit) \ ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits] #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices) { UInt32 price = 0; sym |= 0x100; do { unsigned bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); } while (sym >= 2); return price; } static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; sym |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1); sym <<= 1; offs &= ~(matchByte ^ sym); } while (sym < 0x10000); return price; } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym) { UInt32 range = rc->range; unsigned m = 1; do { UInt32 ttt, newBound; unsigned bit = sym & 1; // RangeEnc_EncodeBit(rc, probs + m, bit); sym >>= 1; RC_BIT(rc, probs + m, bit) m = (m << 1) | bit; } while (--numBits); rc->range = range; } static void LenEnc_Init(CLenEnc *p) { unsigned i; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++) p->low[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState) { UInt32 range, ttt, newBound; CLzmaProb *probs = p->low; range = rc->range; RC_BIT_PRE(rc, probs) if (sym >= kLenNumLowSymbols) { RC_BIT_1(rc, probs) probs += kLenNumLowSymbols; RC_BIT_PRE(rc, probs) if (sym >= kLenNumLowSymbols * 2) { RC_BIT_1(rc, probs) rc->range = range; // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2); LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2); return; } sym -= kLenNumLowSymbols; } // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym); { unsigned m; unsigned bit; RC_BIT_0(rc, probs) probs += (posState << (1 + kLenNumLowBits)); bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit) m = (1 << 1) + bit; bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit) m = (m << 1) + bit; bit = sym & 1; RC_BIT(rc, probs + m, bit) rc->range = range; } } static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices) { unsigned i; for (i = 0; i < 8; i += 2) { UInt32 price = startPrice; UInt32 prob; price += GET_PRICEa(probs[1 ], (i >> 2)); price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1); prob = probs[4 + (i >> 1)]; prices[i ] = price + GET_PRICEa_0(prob); prices[i + 1] = price + GET_PRICEa_1(prob); } } Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables( CLenPriceEnc *p, unsigned numPosStates, const CLenEnc *enc, const CProbPrice *ProbPrices) { UInt32 b; { unsigned prob = enc->low[0]; UInt32 a, c; unsigned posState; b = GET_PRICEa_1(prob); a = GET_PRICEa_0(prob); c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); for (posState = 0; posState < numPosStates; posState++) { UInt32 *prices = p->prices[posState]; const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits)); SetPrices_3(probs, a, prices, ProbPrices); SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices); } } /* { unsigned i; UInt32 b; a = GET_PRICEa_0(enc->low[0]); for (i = 0; i < kLenNumLowSymbols; i++) p->prices2[i] = a; a = GET_PRICEa_1(enc->low[0]); b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++) p->prices2[i] = b; a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); } */ // p->counter = numSymbols; // p->counter = 64; { unsigned i = p->tableSize; if (i > kLenNumLowSymbols * 2) { const CLzmaProb *probs = enc->high; UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2; i -= kLenNumLowSymbols * 2 - 1; i >>= 1; b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); do { /* p->prices2[i] = a + // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices); LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices); */ // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices); unsigned sym = --i + (1 << (kLenNumHighBits - 1)); UInt32 price = b; do { const unsigned bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); } while (sym >= 2); { const unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))]; prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob); prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob); } } while (i); { unsigned posState; const size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]); for (posState = 1; posState < numPosStates; posState++) memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num); } } } } /* #ifdef SHOW_STAT g_STAT_OFFSET += num; printf("\n MovePos %u", num); #endif */ #define MOVE_POS(p, num) { \ p->additionalOffset += (num); \ p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); } static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) { unsigned numPairs; p->additionalOffset++; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); { const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); // if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; } numPairs = (unsigned)(d - p->matches); } *numPairsRes = numPairs; #ifdef SHOW_STAT printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2); g_STAT_OFFSET++; { unsigned i; for (i = 0; i < numPairs; i += 2) printf("%2u %6u | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs == 0) return 0; { const unsigned len = p->matches[(size_t)numPairs - 2]; if (len != p->numFastBytes) return len; { UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; const Byte *p2 = p1 + len; const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1]; const Byte *lim = p1 + numAvail; for (; p2 != lim && *p2 == p2[dif]; p2++) {} return (unsigned)(p2 - p1); } } } } #define MARK_LIT ((UInt32)(Int32)-1) #define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; } #define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; } #define IsShortRep(p) ((p)->dist == 0) #define GetPrice_ShortRep(p, state, posState) \ ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState])) #define GetPrice_Rep_0(p, state, posState) ( \ GET_PRICE_1(p->isMatch[state][posState]) \ + GET_PRICE_1(p->isRep0Long[state][posState])) \ + GET_PRICE_1(p->isRep[state]) \ + GET_PRICE_0(p->isRepG0[state]) Z7_FORCE_INLINE static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState) { UInt32 price; UInt32 prob = p->isRepG0[state]; if (repIndex == 0) { price = GET_PRICE_0(prob); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(prob); prob = p->isRepG1[state]; if (repIndex == 1) price += GET_PRICE_0(prob); else { price += GET_PRICE_1(prob); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static unsigned Backward(CLzmaEnc *p, unsigned cur) { unsigned wr = cur + 1; p->optEnd = wr; for (;;) { UInt32 dist = p->opt[cur].dist; unsigned len = (unsigned)p->opt[cur].len; unsigned extra = (unsigned)p->opt[cur].extra; cur -= len; if (extra) { wr--; p->opt[wr].len = (UInt32)len; cur -= extra; len = extra; if (extra == 1) { p->opt[wr].dist = dist; dist = MARK_LIT; } else { p->opt[wr].dist = 0; len--; wr--; p->opt[wr].dist = MARK_LIT; p->opt[wr].len = 1; } } if (cur == 0) { p->backRes = dist; p->optCur = wr; return len; } wr--; p->opt[wr].dist = dist; p->opt[wr].len = (UInt32)len; } } #define LIT_PROBS(pos, prevByte) \ (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc)) static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) { unsigned last, cur; UInt32 reps[LZMA_NUM_REPS]; unsigned repLens[LZMA_NUM_REPS]; UInt32 *matches; { UInt32 numAvail; unsigned numPairs, mainLen, repMaxIndex, i, posState; UInt32 matchPrice, repMatchPrice; const Byte *data; Byte curByte, matchByte; p->optCur = p->optEnd = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLen; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { p->backRes = MARK_LIT; return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { unsigned len; const Byte *data2; reps[i] = p->reps[i]; data2 = data - reps[i]; if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (len = 2; len < numAvail && data[len] == data2[len]; len++) {} repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization break; } if (repLens[repMaxIndex] >= p->numFastBytes) { unsigned len; p->backRes = (UInt32)repMaxIndex; len = repLens[repMaxIndex]; MOVE_POS(p, len - 1) return len; } matches = p->matches; #define MATCHES matches // #define MATCHES p->matches if (mainLen >= p->numFastBytes) { p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS; MOVE_POS(p, mainLen - 1) return mainLen; } curByte = *data; matchByte = *(data - reps[0]); last = repLens[repMaxIndex]; if (last <= mainLen) last = mainLen; if (last < 2 && curByte != matchByte) { p->backRes = MARK_LIT; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsLitState(p->state) ? LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAs_Lit(&p->opt[1]) matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); // 18.06 if (matchByte == curByte && repLens[0] == 0) { UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAs_ShortRep(&p->opt[1]) } if (last < 2) { p->backRes = p->opt[1].dist; return 1; } } p->opt[1].len = 1; p->opt[0].reps[0] = reps[0]; p->opt[0].reps[1] = reps[1]; p->opt[0].reps[2] = reps[2]; p->opt[0].reps[3] = reps[3]; // ---------- REP ---------- for (i = 0; i < LZMA_NUM_REPS; i++) { unsigned repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState); do { UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen); COptimal *opt = &p->opt[repLen]; if (price2 < opt->price) { opt->price = price2; opt->len = (UInt32)repLen; opt->dist = (UInt32)i; opt->extra = 0; } } while (--repLen >= 2); } // ---------- MATCH ---------- { unsigned len = repLens[0] + 1; if (len <= mainLen) { unsigned offs = 0; UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); if (len < 2) len = 2; else while (len > MATCHES[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 dist = MATCHES[(size_t)offs + 1]; UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); unsigned lenToPosState = GetLenToPosState(len); if (dist < kNumFullDistances) price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)]; else { unsigned slot; GetPosSlot2(dist, slot) price += p->alignPrices[dist & kAlignMask]; price += p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (price < opt->price) { opt->price = price; opt->len = (UInt32)len; opt->dist = dist + LZMA_NUM_REPS; opt->extra = 0; } if (len == MATCHES[offs]) { offs += 2; if (offs == numPairs) break; } } } } cur = 0; #ifdef SHOW_STAT2 /* if (position >= 0) */ { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= last; i++) printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price); } #endif } // ---------- Optimal Parsing ---------- for (;;) { unsigned numAvail; UInt32 numAvailFull; unsigned newLen, numPairs, prev, state, posState, startLen; UInt32 litPrice, matchPrice, repMatchPrice; BoolInt nextIsLit; Byte curByte, matchByte; const Byte *data; COptimal *curOpt, *nextOpt; if (++cur == last) break; // 18.06 if (cur >= kNumOpts - 64) { unsigned j, best; UInt32 price = p->opt[cur].price; best = cur; for (j = cur + 1; j <= last; j++) { UInt32 price2 = p->opt[j].price; if (price >= price2) { price = price2; best = j; } } { unsigned delta = best - cur; if (delta != 0) { MOVE_POS(p, delta) } } cur = best; break; } newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLen = newLen; break; } curOpt = &p->opt[cur]; position++; // we need that check here, if skip_items in p->opt are possible /* if (curOpt->price >= kInfinityPrice) continue; */ prev = cur - curOpt->len; if (curOpt->len == 1) { state = (unsigned)p->opt[prev].state; if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { const COptimal *prevOpt; UInt32 b0; UInt32 dist = curOpt->dist; if (curOpt->extra) { prev -= (unsigned)curOpt->extra; state = kState_RepAfterLit; if (curOpt->extra == 1) state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit); } else { state = (unsigned)p->opt[prev].state; if (dist < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[prev]; b0 = prevOpt->reps[0]; if (dist < LZMA_NUM_REPS) { if (dist == 0) { reps[0] = b0; reps[1] = prevOpt->reps[1]; reps[2] = prevOpt->reps[2]; reps[3] = prevOpt->reps[3]; } else { reps[1] = b0; b0 = prevOpt->reps[1]; if (dist == 1) { reps[0] = b0; reps[2] = prevOpt->reps[2]; reps[3] = prevOpt->reps[3]; } else { reps[2] = b0; reps[0] = prevOpt->reps[dist]; reps[3] = prevOpt->reps[dist ^ 1]; } } } else { reps[0] = (dist - LZMA_NUM_REPS + 1); reps[1] = b0; reps[2] = prevOpt->reps[1]; reps[3] = prevOpt->reps[2]; } } curOpt->state = (CState)state; curOpt->reps[0] = reps[0]; curOpt->reps[1] = reps[1]; curOpt->reps[2] = reps[2]; curOpt->reps[3] = reps[3]; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - reps[0]); posState = (position & p->pbMask); /* The order of Price checks: < LIT <= SHORT_REP < LIT : REP_0 < REP [ : LIT : REP_0 ] < MATCH [ : LIT : REP_0 ] */ { UInt32 curPrice = curOpt->price; unsigned prob = p->isMatch[state][posState]; matchPrice = curPrice + GET_PRICE_1(prob); litPrice = curPrice + GET_PRICE_0(prob); } nextOpt = &p->opt[(size_t)cur + 1]; nextIsLit = False; // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice) // 18.new.06 if ((nextOpt->price < kInfinityPrice // && !IsLitState(state) && matchByte == curByte) || litPrice > nextOpt->price ) litPrice = 0; else { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); litPrice += (!IsLitState(state) ? LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); if (litPrice < nextOpt->price) { nextOpt->price = litPrice; nextOpt->len = 1; MakeAs_Lit(nextOpt) nextIsLit = True; } } repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); numAvailFull = p->numAvail; { unsigned temp = kNumOpts - 1 - cur; if (numAvailFull > temp) numAvailFull = (UInt32)temp; } // 18.06 // ---------- SHORT_REP ---------- if (IsLitState(state)) // 18.new if (matchByte == curByte) if (repMatchPrice < nextOpt->price) // 18.new // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1)) if ( // nextOpt->price >= kInfinityPrice || nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt || (nextOpt->dist != 0 // && nextOpt->extra <= 1 // 17.old ) ) { UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState); // if (shortRepPrice <= nextOpt->price) // 17.old if (shortRepPrice < nextOpt->price) // 18.new { nextOpt->price = shortRepPrice; nextOpt->len = 1; MakeAs_ShortRep(nextOpt) nextIsLit = False; } } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); // numAvail <= p->numFastBytes // ---------- LIT : REP_0 ---------- if (!nextIsLit && litPrice != 0 // 18.new && matchByte != curByte && numAvailFull > 2) { const Byte *data2 = data - reps[0]; if (data[1] == data2[1] && data[2] == data2[2]) { unsigned len; unsigned limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (len = 3; len < limit && data[len] == data2[len]; len++) {} { unsigned state2 = kLiteralNextStates[state]; unsigned posState2 = (position + 1) & p->pbMask; UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2); { unsigned offset = cur + len; if (last < offset) last = offset; // do { UInt32 price2; COptimal *opt; len--; // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2); price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len); opt = &p->opt[offset]; // offset--; if (price2 < opt->price) { opt->price = price2; opt->len = (UInt32)len; opt->dist = 0; opt->extra = 1; } } // while (len >= 3); } } } } startLen = 2; /* speed optimization */ { // ---------- REP ---------- unsigned repIndex = 0; // 17.old // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused for (; repIndex < LZMA_NUM_REPS; repIndex++) { unsigned len; UInt32 price; const Byte *data2 = data - reps[repIndex]; if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++) {} // if (len < startLen) continue; // 18.new: speed optimization { unsigned offset = cur + len; if (last < offset) last = offset; } { unsigned len2 = len; price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState); do { UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2); COptimal *opt = &p->opt[cur + len2]; if (price2 < opt->price) { opt->price = price2; opt->len = (UInt32)len2; opt->dist = (UInt32)repIndex; opt->extra = 0; } } while (--len2 >= 2); } if (repIndex == 0) startLen = len + 1; // 17.old // startLen = len + 1; // 18.new /* if (_maxMode) */ { // ---------- REP : LIT : REP_0 ---------- // numFastBytes + 1 + numFastBytes unsigned len2 = len + 1; unsigned limit = len2 + p->numFastBytes; if (limit > numAvailFull) limit = numAvailFull; len2 += 2; if (len2 <= limit) if (data[len2 - 2] == data2[len2 - 2]) if (data[len2 - 1] == data2[len2 - 1]) { unsigned state2 = kRepNextStates[state]; unsigned posState2 = (position + len) & p->pbMask; price += GET_PRICE_LEN(&p->repLenEnc, posState, len) + GET_PRICE_0(p->isMatch[state2][posState2]) + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), data[len], data2[len], p->ProbPrices); // state2 = kLiteralNextStates[state2]; state2 = kState_LitAfterRep; posState2 = (posState2 + 1) & p->pbMask; price += GetPrice_Rep_0(p, state2, posState2); for (; len2 < limit && data[len2] == data2[len2]; len2++) {} len2 -= len; // if (len2 >= 3) { { unsigned offset = cur + len + len2; if (last < offset) last = offset; // do { UInt32 price2; COptimal *opt; len2--; // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); opt = &p->opt[offset]; // offset--; if (price2 < opt->price) { opt->price = price2; opt->len = (UInt32)len2; opt->extra = (CExtra)(len + 1); opt->dist = (UInt32)repIndex; } } // while (len2 >= 3); } } } } } } // ---------- MATCH ---------- /* for (unsigned len = 2; len <= newLen; len++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2); MATCHES[numPairs] = (UInt32)newLen; numPairs += 2; } // startLen = 2; /* speed optimization */ if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 dist; unsigned offs, posSlot, len; { unsigned offset = cur + newLen; if (last < offset) last = offset; } offs = 0; while (startLen > MATCHES[offs]) offs += 2; dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot) for (len = /*2*/ startLen; ; len++) { UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); { COptimal *opt; unsigned lenNorm = len - 2; lenNorm = GetLenToPosState2(lenNorm); if (dist < kNumFullDistances) price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)]; else price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask]; opt = &p->opt[cur + len]; if (price < opt->price) { opt->price = price; opt->len = (UInt32)len; opt->dist = dist + LZMA_NUM_REPS; opt->extra = 0; } } if (len == MATCHES[offs]) { // if (p->_maxMode) { // MATCH : LIT : REP_0 const Byte *data2 = data - dist - 1; unsigned len2 = len + 1; unsigned limit = len2 + p->numFastBytes; if (limit > numAvailFull) limit = numAvailFull; len2 += 2; if (len2 <= limit) if (data[len2 - 2] == data2[len2 - 2]) if (data[len2 - 1] == data2[len2 - 1]) { for (; len2 < limit && data[len2] == data2[len2]; len2++) {} len2 -= len; // if (len2 >= 3) { unsigned state2 = kMatchNextStates[state]; unsigned posState2 = (position + len) & p->pbMask; unsigned offset; price += GET_PRICE_0(p->isMatch[state2][posState2]); price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), data[len], data2[len], p->ProbPrices); // state2 = kLiteralNextStates[state2]; state2 = kState_LitAfterMatch; posState2 = (posState2 + 1) & p->pbMask; price += GetPrice_Rep_0(p, state2, posState2); offset = cur + len + len2; if (last < offset) last = offset; // do { UInt32 price2; COptimal *opt; len2--; // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); opt = &p->opt[offset]; // offset--; if (price2 < opt->price) { opt->price = price2; opt->len = (UInt32)len2; opt->extra = (CExtra)(len + 1); opt->dist = dist + LZMA_NUM_REPS; } } // while (len2 >= 3); } } offs += 2; if (offs == numPairs) break; dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot) } } } } do p->opt[last].price = kInfinityPrice; while (--last); return Backward(p, cur); } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static unsigned GetOptimumFast(CLzmaEnc *p) { UInt32 numAvail, mainDist; unsigned mainLen, numPairs, repIndex, repLen, i; const Byte *data; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLen; numPairs = p->numPairs; } numAvail = p->numAvail; p->backRes = MARK_LIT; if (numAvail < 2) return 1; // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { unsigned len; const Byte *data2 = data - p->reps[i]; if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++) {} if (len >= p->numFastBytes) { p->backRes = (UInt32)i; MOVE_POS(p, len - 1) return len; } if (len > repLen) { repIndex = i; repLen = len; } } if (mainLen >= p->numFastBytes) { p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; MOVE_POS(p, mainLen - 1) return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = p->matches[(size_t)numPairs - 1]; while (numPairs > 2) { UInt32 dist2; if (mainLen != p->matches[(size_t)numPairs - 4] + 1) break; dist2 = p->matches[(size_t)numPairs - 3]; if (!ChangePair(dist2, mainDist)) break; numPairs -= 2; mainLen--; mainDist = dist2; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2) if ( repLen + 1 >= mainLen || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15))) { p->backRes = (UInt32)repIndex; MOVE_POS(p, repLen - 1) return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; { unsigned len1 = ReadMatchDistances(p, &p->numPairs); p->longestMatchLen = len1; if (len1 >= 2) { UInt32 newDist = p->matches[(size_t)p->numPairs - 1]; if ( (len1 >= mainLen && newDist < mainDist) || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist)) || (len1 > mainLen + 1) || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist))) return 1; } } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { unsigned len, limit; const Byte *data2 = data - p->reps[i]; if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2;; len++) { if (len >= limit) return 1; if (data[len] != data2[len]) break; } } p->backRes = mainDist + LZMA_NUM_REPS; if (mainLen != 2) { MOVE_POS(p, mainLen - 2) } return mainLen; } static void WriteEndMarker(CLzmaEnc *p, unsigned posState) { UInt32 range; range = p->rc.range; { UInt32 ttt, newBound; CLzmaProb *prob = &p->isMatch[p->state][posState]; RC_BIT_PRE(&p->rc, prob) RC_BIT_1(&p->rc, prob) prob = &p->isRep[p->state]; RC_BIT_PRE(&p->rc, prob) RC_BIT_0(&p->rc, prob) } p->state = kMatchNextStates[p->state]; p->rc.range = range; LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState); range = p->rc.range; { // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1); CLzmaProb *probs = p->posSlotEncoder[0]; unsigned m = 1; do { UInt32 ttt, newBound; RC_BIT_PRE(p, probs + m) RC_BIT_1(&p->rc, probs + m) m = (m << 1) + 1; } while (m < (1 << kNumPosSlotBits)); } { // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range; unsigned numBits = 30 - kNumAlignBits; do { range >>= 1; p->rc.low += range; RC_NORM(&p->rc) } while (--numBits); } { // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); CLzmaProb *probs = p->posAlignEncoder; unsigned m = 1; do { UInt32 ttt, newBound; RC_BIT_PRE(p, probs + m) RC_BIT_1(&p->rc, probs + m) m = (m << 1) + 1; } while (m < kAlignTableSize); } p->rc.range = range; } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; #ifndef Z7_ST if ( // p->mf_Failure || (p->mtMode && ( // p->matchFinderMt.failure_LZ_LZ || p->matchFinderMt.failure_LZ_BT)) ) { p->result = MY_HRES_ERROR_INTERNAL_ERROR; // printf("\nCheckErrors p->matchFinderMt.failureLZ\n"); } #endif if (MFB.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } Z7_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } Z7_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) { unsigned i; const CProbPrice *ProbPrices = p->ProbPrices; const CLzmaProb *probs = p->posAlignEncoder; // p->alignPriceCount = 0; for (i = 0; i < kAlignTableSize / 2; i++) { UInt32 price = 0; unsigned sym = i; unsigned m = 1; unsigned bit; UInt32 prob; bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; prob = probs[m]; p->alignPrices[i ] = price + GET_PRICEa_0(prob); p->alignPrices[i + 8] = price + GET_PRICEa_1(prob); // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); } } Z7_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) { // int y; for (y = 0; y < 100; y++) { UInt32 tempPrices[kNumFullDistances]; unsigned i, lps; const CProbPrice *ProbPrices = p->ProbPrices; p->matchPriceCount = 0; for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++) { unsigned posSlot = GetPosSlot1(i); unsigned footerBits = (posSlot >> 1) - 1; unsigned base = ((2 | (posSlot & 1)) << footerBits); const CLzmaProb *probs = p->posEncoders + (size_t)base * 2; // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices); UInt32 price = 0; unsigned m = 1; unsigned sym = i; unsigned offset = (unsigned)1 << footerBits; base += i; if (footerBits) do { unsigned bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; } while (--footerBits); { unsigned prob = probs[m]; tempPrices[base ] = price + GET_PRICEa_0(prob); tempPrices[base + offset] = price + GET_PRICEa_1(prob); } } for (lps = 0; lps < kNumLenToPosStates; lps++) { unsigned slot; unsigned distTableSize2 = (p->distTableSize + 1) >> 1; UInt32 *posSlotPrices = p->posSlotPrices[lps]; const CLzmaProb *probs = p->posSlotEncoder[lps]; for (slot = 0; slot < distTableSize2; slot++) { // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices); UInt32 price; unsigned bit; unsigned sym = slot + (1 << (kNumPosSlotBits - 1)); unsigned prob; bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit); bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))]; posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob); posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob); } { UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits); for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++) { posSlotPrices[(size_t)slot * 2 ] += delta; posSlotPrices[(size_t)slot * 2 + 1] += delta; delta += ((UInt32)1 << kNumBitPriceShiftBits); } } { UInt32 *dp = p->distancesPrices[lps]; dp[0] = posSlotPrices[0]; dp[1] = posSlotPrices[1]; dp[2] = posSlotPrices[2]; dp[3] = posSlotPrices[3]; for (i = 4; i < kNumFullDistances; i += 2) { UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)]; dp[i ] = slotPrice + tempPrices[i]; dp[i + 1] = slotPrice + tempPrices[i + 1]; } } } // } } static void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&MFB); #ifndef Z7_ST p->matchFinderMt.MatchFinder = &MFB; MatchFinderMt_Construct(&p->matchFinderMt); #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps((CLzmaEncHandle)(void *)p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = NULL; p->saveState.litProbs = NULL; } CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) { void *p; p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); if (p) LzmaEnc_Construct((CLzmaEnc *)p); return p; } static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->litProbs); ISzAlloc_Free(alloc, p->saveState.litProbs); p->litProbs = NULL; p->saveState.litProbs = NULL; } static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { #ifndef Z7_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&MFB, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { // GET_CLzmaEnc_p LzmaEnc_Destruct(p, alloc, allocBig); ISzAlloc_Free(alloc, p); } Z7_NO_INLINE static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->needInit) { #ifndef Z7_ST if (p->mtMode) { RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)) } #endif p->matchFinder.Init(p->matchFinderObj); p->needInit = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)) nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { unsigned numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]); // p->state = kLiteralNextStates[p->state]; curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 dist; unsigned len, posState; UInt32 range, ttt, newBound; CLzmaProb *probs; if (p->fastMode) len = GetOptimumFast(p); else { unsigned oci = p->optCur; if (p->optEnd == oci) len = GetOptimum(p, nowPos32); else { const COptimal *opt = &p->opt[oci]; len = opt->len; p->backRes = opt->dist; p->optCur = oci + 1; } } posState = (unsigned)nowPos32 & p->pbMask; range = p->rc.range; probs = &p->isMatch[p->state][posState]; RC_BIT_PRE(&p->rc, probs) dist = p->backRes; #ifdef SHOW_STAT2 printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist); #endif if (dist == MARK_LIT) { Byte curByte; const Byte *data; unsigned state; RC_BIT_0(&p->rc, probs) p->rc.range = range; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; probs = LIT_PROBS(nowPos32, *(data - 1)); curByte = *data; state = p->state; p->state = kLiteralNextStates[state]; if (IsLitState(state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0])); } else { RC_BIT_1(&p->rc, probs) probs = &p->isRep[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist < LZMA_NUM_REPS) { RC_BIT_1(&p->rc, probs) probs = &p->isRepG0[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 0) { RC_BIT_0(&p->rc, probs) probs = &p->isRep0Long[p->state][posState]; RC_BIT_PRE(&p->rc, probs) if (len != 1) { RC_BIT_1_BASE(&p->rc, probs) } else { RC_BIT_0_BASE(&p->rc, probs) p->state = kShortRepNextStates[p->state]; } } else { RC_BIT_1(&p->rc, probs) probs = &p->isRepG1[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 1) { RC_BIT_0_BASE(&p->rc, probs) dist = p->reps[1]; } else { RC_BIT_1(&p->rc, probs) probs = &p->isRepG2[p->state]; RC_BIT_PRE(&p->rc, probs) if (dist == 2) { RC_BIT_0_BASE(&p->rc, probs) dist = p->reps[2]; } else { RC_BIT_1_BASE(&p->rc, probs) dist = p->reps[3]; p->reps[3] = p->reps[2]; } p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = dist; } RC_NORM(&p->rc) p->rc.range = range; if (len != 1) { LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); --p->repLenEncCounter; p->state = kRepNextStates[p->state]; } } else { unsigned posSlot; RC_BIT_0(&p->rc, probs) p->rc.range = range; p->state = kMatchNextStates[p->state]; LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); // --p->lenEnc.counter; dist -= LZMA_NUM_REPS; p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = dist + 1; p->matchPriceCount++; GetPosSlot(dist, posSlot) // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot); { UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits); range = p->rc.range; probs = p->posSlotEncoder[GetLenToPosState(len)]; do { CLzmaProb *prob = probs + (sym >> kNumPosSlotBits); UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1; sym <<= 1; RC_BIT(&p->rc, prob, bit) } while (sym < (1 << kNumPosSlotBits * 2)); p->rc.range = range; } if (dist >= kStartPosModelIndex) { unsigned footerBits = ((posSlot >> 1) - 1); if (dist < kNumFullDistances) { unsigned base = ((2 | (posSlot & 1)) << footerBits); RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */)); } else { UInt32 pos2 = (dist | 0xF) << (32 - footerBits); range = p->rc.range; // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); /* do { range >>= 1; p->rc.low += range & (0 - ((dist >> --footerBits) & 1)); RC_NORM(&p->rc) } while (footerBits > kNumAlignBits); */ do { range >>= 1; p->rc.low += range & (0 - (pos2 >> 31)); pos2 += pos2; RC_NORM(&p->rc) } while (pos2 != 0xF0000000); // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); { unsigned m = 1; unsigned bit; bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) m = (m << 1) + bit; bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit) p->rc.range = range; // p->alignPriceCount++; } } } } } nowPos32 += (UInt32)len; p->additionalOffset -= len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { /* if (p->alignPriceCount >= 16) // kAlignTableSize FillAlignPrices(p); if (p->matchPriceCount >= 128) FillDistancesPrices(p); if (p->lenEnc.counter <= 0) LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); */ if (p->matchPriceCount >= 64) { FillAlignPrices(p); // { int y; for (y = 0; y < 100; y++) { FillDistancesPrices(p); // }} LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); } if (p->repLenEncCounter <= 0) { p->repLenEncCounter = REP_LEN_COUNT; LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (maxPackSize) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize) break; } else if (processed >= (1 << 17)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { UInt32 beforeSize = kNumOpts; UInt32 dictSize; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; #ifndef Z7_ST p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0)); #endif { const unsigned lclp = p->lc + p->lp; if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp); p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp); if (!p->litProbs || !p->saveState.litProbs) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); dictSize = p->dictSize; if (dictSize == ((UInt32)2 << 30) || dictSize == ((UInt32)3 << 30)) { /* 21.03 : here we reduce the dictionary for 2 reasons: 1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary. 2) we want to elimate useless last MatchFinder_Normalize3() for corner cases, where data size is aligned for 1 GB: 5/6/8 GB. That reducing must be >= 1 for such corner cases. */ dictSize -= 1; } if (beforeSize + dictSize < keepWindowSize) beforeSize = keepWindowSize - dictSize; /* in worst case we can look ahead for max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes. we send larger value for (keepAfter) to MantchFinder_Create(): (numFastBytes + LZMA_MATCH_LEN_MAX + 1) */ #ifndef Z7_ST if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */ , allocBig)) p->matchFinderObj = &p->matchFinderMt; MFB.bigHash = (Byte)(MFB.hashMask >= 0xFFFFFF ? 1 : 0); MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&MFB, dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */ , allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &MFB; MatchFinder_CreateVTable(&MFB, &p->matchFinder); } return SZ_OK; } static void LzmaEnc_Init(CLzmaEnc *p) { unsigned i; p->state = 0; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; RangeEnc_Init(&p->rc); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; for (i = 0; i < kNumStates; i++) { unsigned j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; unsigned j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances; i++) p->posEncoders[i] = kProbInitValue; } { const size_t num = (size_t)0x300 << (p->lp + p->lc); size_t k; CLzmaProb *probs = p->litProbs; for (k = 0; k < num; k++) probs[k] = kProbInitValue; } LenEnc_Init(&p->lenProbs); LenEnc_Init(&p->repLenProbs); p->optEnd = 0; p->optCur = 0; { for (i = 0; i < kNumOpts; i++) p->opt[i].price = kInfinityPrice; } p->additionalOffset = 0; p->pbMask = ((unsigned)1 << p->pb) - 1; p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); // p->mf_Failure = False; } static void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; p->repLenEncCounter = REP_LEN_COUNT; LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { unsigned i; for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; p->nowPos64 = 0; p->needInit = 1; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ISzAllocPtr alloc, ISzAllocPtr allocBig) { // GET_CLzmaEnc_p MatchFinder_SET_STREAM(&MFB, inStream) p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { // GET_CLzmaEnc_p MatchFinder_SET_STREAM(&MFB, inStream) return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { // GET_CLzmaEnc_p MatchFinder_SET_DIRECT_INPUT_BUF(&MFB, src, srcLen) LzmaEnc_SetDataSize(p, srcLen); return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle p) { #ifndef Z7_ST // GET_CLzmaEnc_p if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else UNUSED_VAR(p) #endif } typedef struct { ISeqOutStream vt; Byte *data; size_t rem; BoolInt overflow; } CLzmaEnc_SeqOutStreamBuf; static size_t SeqOutStreamBuf_Write(ISeqOutStreamPtr pp, const void *data, size_t size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLzmaEnc_SeqOutStreamBuf) if (p->rem < size) { size = p->rem; p->overflow = True; } if (size != 0) { memcpy(p->data, data, size); p->rem -= size; p->data += size; } return size; } /* UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p) { GET_const_CLzmaEnc_p return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } */ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p) { // GET_const_CLzmaEnc_p return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } // (desiredPackSize == 0) is not allowed SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { // GET_CLzmaEnc_p UInt64 nowPos64; SRes res; CLzmaEnc_SeqOutStreamBuf outStream; outStream.vt.Write = SeqOutStreamBuf_Write; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.vt; nowPos64 = p->nowPos64; res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } Z7_NO_INLINE static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgressPtr progress) { SRes res = SZ_OK; #ifndef Z7_ST Byte allocaDummy[0x300]; allocaDummy[0] = 0; allocaDummy[1] = allocaDummy[0]; #endif for (;;) { res = LzmaEnc_CodeOneBlock(p, 0, 0); if (res != SZ_OK || p->finished) break; if (progress) { res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish((CLzmaEncHandle)(void *)p); /* if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB)) res = SZ_ERROR_FAIL; } */ return res; } SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { // GET_CLzmaEnc_p RINOK(LzmaEnc_Prepare(p, outStream, inStream, alloc, allocBig)) return LzmaEnc_Encode2(p, progress); } SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *props, SizeT *size) { if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; { // GET_CLzmaEnc_p const UInt32 dictSize = p->dictSize; UInt32 v; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); // we write aligned dictionary value to properties for lzma decoder if (dictSize >= ((UInt32)1 << 21)) { const UInt32 kDictMask = ((UInt32)1 << 20) - 1; v = (dictSize + kDictMask) & ~kDictMask; if (v < dictSize) v = dictSize; } else { unsigned i = 11 * 2; do { v = (UInt32)(2 + (i & 1)) << (i >> 1); i++; } while (v < dictSize); } SetUi32(props + 1, v) return SZ_OK; } } unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p) { // GET_CLzmaEnc_p return (unsigned)p->writeEndMark; } SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { SRes res; // GET_CLzmaEnc_p CLzmaEnc_SeqOutStreamBuf outStream; outStream.vt.Write = SeqOutStreamBuf_Write; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; p->rc.outStream = &outStream.vt; res = LzmaEnc_MemPrepare(p, src, srcLen, 0, alloc, allocBig); if (res == SZ_OK) { res = LzmaEnc_Encode2(p, progress); if (res == SZ_OK && p->nowPos64 != srcLen) res = SZ_ERROR_FAIL; } *destLen -= (SizeT)outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzmaEncHandle p = LzmaEnc_Create(alloc); SRes res; if (!p) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } /* #ifndef Z7_ST void LzmaEnc_GetLzThreads(CLzmaEncHandle p, HANDLE lz_threads[2]) { GET_const_CLzmaEnc_p lz_threads[0] = p->matchFinderMt.hashSync.thread; lz_threads[1] = p->matchFinderMt.btSync.thread; } #endif */ tmp41wklro_/C/LzmaEnc.h0000444000175000001440000000625314415733200016032 0ustar nabijaczleweliusers/* LzmaEnc.h -- LZMA Encoder 2023-04-13 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA_ENC_H #define ZIP7_INC_LZMA_ENC_H #include "7zTypes.h" EXTERN_C_BEGIN #define LZMA_PROPS_SIZE 5 typedef struct { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (3 << 29) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ unsigned numHashOutBits; /* default = ? */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ // int _pad; UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. Encoder uses this value to reduce dictionary size */ UInt64 affinity; } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc* functions can return the following exit codes: SRes: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - ISeqOutStream write callback error SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) */ typedef struct CLzmaEnc CLzmaEnc; typedef CLzmaEnc * CLzmaEncHandle; // Z7_DECLARE_HANDLE(CLzmaEncHandle) CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); /* ---------- One Call Interface ---------- */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); EXTERN_C_END #endif tmp41wklro_/C/LzmaLib.c0000444000175000001440000000250314412267100016016 0ustar nabijaczleweliusers/* LzmaLib.c -- LZMA library wrapper 2023-04-02 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Alloc.h" #include "LzmaDec.h" #include "LzmaEnc.h" #include "LzmaLib.h" Z7_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } Z7_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } tmp41wklro_/C/LzmaLib.h0000444000175000001440000001105214412267100016022 0ustar nabijaczleweliusers/* LzmaLib.h -- LZMA library interface 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_LZMA_LIB_H #define ZIP7_INC_LZMA_LIB_H #include "7zTypes.h" EXTERN_C_BEGIN #define Z7_STDAPI int Z7_STDCALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 64 KB 0 32 1: 256 KB 0 32 2: 1 MB 0 32 3: 4 MB 0 32 4: 16 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7: 32 MB 1 64 8: 64 MB 1 64 9: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. In: dest - output data buffer destLen - output data buffer size src - input data srcLen - input data size Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ Z7_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data buffer destLen - output data buffer size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ Z7_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); EXTERN_C_END #endif tmp41wklro_/C/MtCoder.c0000444000175000001440000003242014476344520016036 0ustar nabijaczleweliusers/* MtCoder.c -- Multi-thread Coder 2023-09-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "MtCoder.h" #ifndef Z7_ST static SRes MtProgressThunk_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CMtProgressThunk) UInt64 inSize2 = 0; UInt64 outSize2 = 0; if (inSize != (UInt64)(Int64)-1) { inSize2 = inSize - p->inSize; p->inSize = inSize; } if (outSize != (UInt64)(Int64)-1) { outSize2 = outSize - p->outSize; p->outSize = outSize; } return MtProgress_ProgressAdd(p->mtProgress, inSize2, outSize2); } void MtProgressThunk_CreateVTable(CMtProgressThunk *p) { p->vt.Progress = MtProgressThunk_Progress; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static THREAD_FUNC_DECL ThreadFunc(void *pp); static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) { WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent); if (wres == 0) { t->stop = False; if (!Thread_WasCreated(&t->thread)) wres = Thread_Create(&t->thread, ThreadFunc, t); if (wres == 0) wres = Event_Set(&t->startEvent); } if (wres == 0) return SZ_OK; return MY_SRes_HRESULT_FROM_WRes(wres); } static void MtCoderThread_Destruct(CMtCoderThread *t) { if (Thread_WasCreated(&t->thread)) { t->stop = 1; Event_Set(&t->startEvent); Thread_Wait_Close(&t->thread); } Event_Close(&t->startEvent); if (t->inBuf) { ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf); t->inBuf = NULL; } } /* ThreadFunc2() returns: SZ_OK - in all normal cases (even for stream error or memory allocation error) SZ_ERROR_THREAD - in case of failure in system synch function */ static SRes ThreadFunc2(CMtCoderThread *t) { CMtCoder *mtc = t->mtCoder; for (;;) { unsigned bi; SRes res; SRes res2; BoolInt finished; unsigned bufIndex; size_t size; const Byte *inData; UInt64 readProcessed = 0; RINOK_THREAD(Event_Wait(&mtc->readEvent)) /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */ if (mtc->stopReading) { return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD; } res = MtProgress_GetError(&mtc->mtProgress); size = 0; inData = NULL; finished = True; if (res == SZ_OK) { size = mtc->blockSize; if (mtc->inStream) { if (!t->inBuf) { t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize); if (!t->inBuf) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SeqInStream_ReadMax(mtc->inStream, t->inBuf, &size); readProcessed = mtc->readProcessed + size; mtc->readProcessed = readProcessed; } if (res != SZ_OK) { mtc->readRes = res; /* after reading error - we can stop encoding of previous blocks */ MtProgress_SetError(&mtc->mtProgress, res); } else finished = (size != mtc->blockSize); } else { size_t rem; readProcessed = mtc->readProcessed; rem = mtc->inDataSize - (size_t)readProcessed; if (size > rem) size = rem; inData = mtc->inData + (size_t)readProcessed; readProcessed += size; mtc->readProcessed = readProcessed; finished = (mtc->inDataSize == (size_t)readProcessed); } } /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */ res2 = SZ_OK; if (Semaphore_Wait(&mtc->blocksSemaphore) != 0) { res2 = SZ_ERROR_THREAD; if (res == SZ_OK) { res = res2; // MtProgress_SetError(&mtc->mtProgress, res); } } bi = mtc->blockIndex; if (++mtc->blockIndex >= mtc->numBlocksMax) mtc->blockIndex = 0; bufIndex = (unsigned)(int)-1; if (res == SZ_OK) res = MtProgress_GetError(&mtc->mtProgress); if (res != SZ_OK) finished = True; if (!finished) { if (mtc->numStartedThreads < mtc->numStartedThreadsLimit && mtc->expectedDataSize != readProcessed) { res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]); if (res == SZ_OK) mtc->numStartedThreads++; else { MtProgress_SetError(&mtc->mtProgress, res); finished = True; } } } if (finished) mtc->stopReading = True; RINOK_THREAD(Event_Set(&mtc->readEvent)) if (res2 != SZ_OK) return res2; if (res == SZ_OK) { CriticalSection_Enter(&mtc->cs); bufIndex = mtc->freeBlockHead; mtc->freeBlockHead = mtc->freeBlockList[bufIndex]; CriticalSection_Leave(&mtc->cs); res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex, mtc->inStream ? t->inBuf : inData, size, finished); // MtProgress_Reinit(&mtc->mtProgress, t->index); if (res != SZ_OK) MtProgress_SetError(&mtc->mtProgress, res); } { CMtCoderBlock *block = &mtc->blocks[bi]; block->res = res; block->bufIndex = bufIndex; block->finished = finished; } #ifdef MTCODER_USE_WRITE_THREAD RINOK_THREAD(Event_Set(&mtc->writeEvents[bi])) #else { unsigned wi; { CriticalSection_Enter(&mtc->cs); wi = mtc->writeIndex; if (wi == bi) mtc->writeIndex = (unsigned)(int)-1; else mtc->ReadyBlocks[bi] = True; CriticalSection_Leave(&mtc->cs); } if (wi != bi) { if (res != SZ_OK || finished) return 0; continue; } if (mtc->writeRes != SZ_OK) res = mtc->writeRes; for (;;) { if (res == SZ_OK && bufIndex != (unsigned)(int)-1) { res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex); if (res != SZ_OK) { mtc->writeRes = res; MtProgress_SetError(&mtc->mtProgress, res); } } if (++wi >= mtc->numBlocksMax) wi = 0; { BoolInt isReady; CriticalSection_Enter(&mtc->cs); if (bufIndex != (unsigned)(int)-1) { mtc->freeBlockList[bufIndex] = mtc->freeBlockHead; mtc->freeBlockHead = bufIndex; } isReady = mtc->ReadyBlocks[wi]; if (isReady) mtc->ReadyBlocks[wi] = False; else mtc->writeIndex = wi; CriticalSection_Leave(&mtc->cs); RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore)) if (!isReady) break; } { CMtCoderBlock *block = &mtc->blocks[wi]; if (res == SZ_OK && block->res != SZ_OK) res = block->res; bufIndex = block->bufIndex; finished = block->finished; } } } #endif if (finished || res != SZ_OK) return 0; } } static THREAD_FUNC_DECL ThreadFunc(void *pp) { CMtCoderThread *t = (CMtCoderThread *)pp; for (;;) { if (Event_Wait(&t->startEvent) != 0) return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; if (t->stop) return 0; { SRes res = ThreadFunc2(t); CMtCoder *mtc = t->mtCoder; if (res != SZ_OK) { MtProgress_SetError(&mtc->mtProgress, res); } #ifndef MTCODER_USE_WRITE_THREAD { unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); if (numFinished == mtc->numStartedThreads) if (Event_Set(&mtc->finishedEvent) != 0) return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; } #endif } } } void MtCoder_Construct(CMtCoder *p) { unsigned i; p->blockSize = 0; p->numThreadsMax = 0; p->expectedDataSize = (UInt64)(Int64)-1; p->inStream = NULL; p->inData = NULL; p->inDataSize = 0; p->progress = NULL; p->allocBig = NULL; p->mtCallback = NULL; p->mtCallbackObject = NULL; p->allocatedBufsSize = 0; Event_Construct(&p->readEvent); Semaphore_Construct(&p->blocksSemaphore); for (i = 0; i < MTCODER_THREADS_MAX; i++) { CMtCoderThread *t = &p->threads[i]; t->mtCoder = p; t->index = i; t->inBuf = NULL; t->stop = False; Event_Construct(&t->startEvent); Thread_CONSTRUCT(&t->thread) } #ifdef MTCODER_USE_WRITE_THREAD for (i = 0; i < MTCODER_BLOCKS_MAX; i++) Event_Construct(&p->writeEvents[i]); #else Event_Construct(&p->finishedEvent); #endif CriticalSection_Init(&p->cs); CriticalSection_Init(&p->mtProgress.cs); } static void MtCoder_Free(CMtCoder *p) { unsigned i; /* p->stopReading = True; if (Event_IsCreated(&p->readEvent)) Event_Set(&p->readEvent); */ for (i = 0; i < MTCODER_THREADS_MAX; i++) MtCoderThread_Destruct(&p->threads[i]); Event_Close(&p->readEvent); Semaphore_Close(&p->blocksSemaphore); #ifdef MTCODER_USE_WRITE_THREAD for (i = 0; i < MTCODER_BLOCKS_MAX; i++) Event_Close(&p->writeEvents[i]); #else Event_Close(&p->finishedEvent); #endif } void MtCoder_Destruct(CMtCoder *p) { MtCoder_Free(p); CriticalSection_Delete(&p->cs); CriticalSection_Delete(&p->mtProgress.cs); } SRes MtCoder_Code(CMtCoder *p) { unsigned numThreads = p->numThreadsMax; unsigned numBlocksMax; unsigned i; SRes res = SZ_OK; if (numThreads > MTCODER_THREADS_MAX) numThreads = MTCODER_THREADS_MAX; numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++; if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; if (numBlocksMax > MTCODER_BLOCKS_MAX) numBlocksMax = MTCODER_BLOCKS_MAX; if (p->blockSize != p->allocatedBufsSize) { for (i = 0; i < MTCODER_THREADS_MAX; i++) { CMtCoderThread *t = &p->threads[i]; if (t->inBuf) { ISzAlloc_Free(p->allocBig, t->inBuf); t->inBuf = NULL; } } p->allocatedBufsSize = p->blockSize; } p->readRes = SZ_OK; MtProgress_Init(&p->mtProgress, p->progress); #ifdef MTCODER_USE_WRITE_THREAD for (i = 0; i < numBlocksMax; i++) { RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->writeEvents[i])) } #else RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent)) #endif { RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent)) RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax)) } for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++) p->freeBlockList[i] = i + 1; p->freeBlockList[MTCODER_BLOCKS_MAX - 1] = (unsigned)(int)-1; p->freeBlockHead = 0; p->readProcessed = 0; p->blockIndex = 0; p->numBlocksMax = numBlocksMax; p->stopReading = False; #ifndef MTCODER_USE_WRITE_THREAD p->writeIndex = 0; p->writeRes = SZ_OK; for (i = 0; i < MTCODER_BLOCKS_MAX; i++) p->ReadyBlocks[i] = False; p->numFinishedThreads = 0; #endif p->numStartedThreadsLimit = numThreads; p->numStartedThreads = 0; // for (i = 0; i < numThreads; i++) { CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; RINOK(MtCoderThread_CreateAndStart(nextThread)) } RINOK_THREAD(Event_Set(&p->readEvent)) #ifdef MTCODER_USE_WRITE_THREAD { unsigned bi = 0; for (;; bi++) { if (bi >= numBlocksMax) bi = 0; RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) { const CMtCoderBlock *block = &p->blocks[bi]; unsigned bufIndex = block->bufIndex; BoolInt finished = block->finished; if (res == SZ_OK && block->res != SZ_OK) res = block->res; if (bufIndex != (unsigned)(int)-1) { if (res == SZ_OK) { res = p->mtCallback->Write(p->mtCallbackObject, bufIndex); if (res != SZ_OK) MtProgress_SetError(&p->mtProgress, res); } CriticalSection_Enter(&p->cs); { p->freeBlockList[bufIndex] = p->freeBlockHead; p->freeBlockHead = bufIndex; } CriticalSection_Leave(&p->cs); } RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore)) if (finished) break; } } } #else { WRes wres = Event_Wait(&p->finishedEvent); res = MY_SRes_HRESULT_FROM_WRes(wres); } #endif if (res == SZ_OK) res = p->readRes; if (res == SZ_OK) res = p->mtProgress.res; #ifndef MTCODER_USE_WRITE_THREAD if (res == SZ_OK) res = p->writeRes; #endif if (res != SZ_OK) MtCoder_Free(p); return res; } #endif #undef RINOK_THREAD tmp41wklro_/C/MtCoder.h0000444000175000001440000000552114415733200016033 0ustar nabijaczleweliusers/* MtCoder.h -- Multi-thread Coder 2023-04-13 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_MT_CODER_H #define ZIP7_INC_MT_CODER_H #include "MtDec.h" EXTERN_C_BEGIN /* if ( defined MTCODER_USE_WRITE_THREAD) : main thread writes all data blocks to output stream if (not defined MTCODER_USE_WRITE_THREAD) : any coder thread can write data blocks to output stream */ /* #define MTCODER_USE_WRITE_THREAD */ #ifndef Z7_ST #define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) #define MTCODER_THREADS_MAX 64 #define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3) #else #define MTCODER_THREADS_MAX 1 #define MTCODER_BLOCKS_MAX 1 #endif #ifndef Z7_ST typedef struct { ICompressProgress vt; CMtProgress *mtProgress; UInt64 inSize; UInt64 outSize; } CMtProgressThunk; void MtProgressThunk_CreateVTable(CMtProgressThunk *p); #define MtProgressThunk_INIT(p) { (p)->inSize = 0; (p)->outSize = 0; } struct CMtCoder_; typedef struct { struct CMtCoder_ *mtCoder; unsigned index; int stop; Byte *inBuf; CAutoResetEvent startEvent; CThread thread; } CMtCoderThread; typedef struct { SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex, const Byte *src, size_t srcSize, int finished); SRes (*Write)(void *p, unsigned outBufIndex); } IMtCoderCallback2; typedef struct { SRes res; unsigned bufIndex; BoolInt finished; } CMtCoderBlock; typedef struct CMtCoder_ { /* input variables */ size_t blockSize; /* size of input block */ unsigned numThreadsMax; UInt64 expectedDataSize; ISeqInStreamPtr inStream; const Byte *inData; size_t inDataSize; ICompressProgressPtr progress; ISzAllocPtr allocBig; IMtCoderCallback2 *mtCallback; void *mtCallbackObject; /* internal variables */ size_t allocatedBufsSize; CAutoResetEvent readEvent; CSemaphore blocksSemaphore; BoolInt stopReading; SRes readRes; #ifdef MTCODER_USE_WRITE_THREAD CAutoResetEvent writeEvents[MTCODER_BLOCKS_MAX]; #else CAutoResetEvent finishedEvent; SRes writeRes; unsigned writeIndex; Byte ReadyBlocks[MTCODER_BLOCKS_MAX]; LONG numFinishedThreads; #endif unsigned numStartedThreadsLimit; unsigned numStartedThreads; unsigned numBlocksMax; unsigned blockIndex; UInt64 readProcessed; CCriticalSection cs; unsigned freeBlockHead; unsigned freeBlockList[MTCODER_BLOCKS_MAX]; CMtProgress mtProgress; CMtCoderBlock blocks[MTCODER_BLOCKS_MAX]; CMtCoderThread threads[MTCODER_THREADS_MAX]; } CMtCoder; void MtCoder_Construct(CMtCoder *p); void MtCoder_Destruct(CMtCoder *p); SRes MtCoder_Code(CMtCoder *p); #endif EXTERN_C_END #endif tmp41wklro_/C/MtDec.c0000444000175000001440000007203614565074040015500 0ustar nabijaczleweliusers/* MtDec.c -- Multi-thread Decoder 2024-02-20 : Igor Pavlov : Public domain */ #include "Precomp.h" // #define SHOW_DEBUG_INFO // #include #include #ifdef SHOW_DEBUG_INFO #include #endif #include "MtDec.h" #ifndef Z7_ST #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress) { p->progress = progress; p->res = SZ_OK; p->totalInSize = 0; p->totalOutSize = 0; } SRes MtProgress_Progress_ST(CMtProgress *p) { if (p->res == SZ_OK && p->progress) if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) p->res = SZ_ERROR_PROGRESS; return p->res; } SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize) { SRes res; CriticalSection_Enter(&p->cs); p->totalInSize += inSize; p->totalOutSize += outSize; if (p->res == SZ_OK && p->progress) if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) p->res = SZ_ERROR_PROGRESS; res = p->res; CriticalSection_Leave(&p->cs); return res; } SRes MtProgress_GetError(CMtProgress *p) { SRes res; CriticalSection_Enter(&p->cs); res = p->res; CriticalSection_Leave(&p->cs); return res; } void MtProgress_SetError(CMtProgress *p, SRes res) { CriticalSection_Enter(&p->cs); if (p->res == SZ_OK) p->res = res; CriticalSection_Leave(&p->cs); } #define RINOK_THREAD(x) RINOK_WRes(x) struct CMtDecBufLink_ { struct CMtDecBufLink_ *next; void *pad[3]; }; typedef struct CMtDecBufLink_ CMtDecBufLink; #define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink) #define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET) static THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp); static WRes MtDecThread_CreateEvents(CMtDecThread *t) { WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite); if (wres == 0) { wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead); if (wres == 0) return SZ_OK; } return wres; } static SRes MtDecThread_CreateAndStart(CMtDecThread *t) { WRes wres = MtDecThread_CreateEvents(t); // wres = 17; // for test if (wres == 0) { if (Thread_WasCreated(&t->thread)) return SZ_OK; wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t); if (wres == 0) return SZ_OK; } return MY_SRes_HRESULT_FROM_WRes(wres); } void MtDecThread_FreeInBufs(CMtDecThread *t) { if (t->inBuf) { void *link = t->inBuf; t->inBuf = NULL; do { void *next = ((CMtDecBufLink *)link)->next; ISzAlloc_Free(t->mtDec->alloc, link); link = next; } while (link); } } static void MtDecThread_CloseThread(CMtDecThread *t) { if (Thread_WasCreated(&t->thread)) { Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */ Event_Set(&t->canRead); Thread_Wait_Close(&t->thread); } Event_Close(&t->canRead); Event_Close(&t->canWrite); } static void MtDec_CloseThreads(CMtDec *p) { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) MtDecThread_CloseThread(&p->threads[i]); } static void MtDecThread_Destruct(CMtDecThread *t) { MtDecThread_CloseThread(t); MtDecThread_FreeInBufs(t); } static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted) { SRes res; CriticalSection_Enter(&p->mtProgress.cs); *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); res = p->mtProgress.res; CriticalSection_Leave(&p->mtProgress.cs); return res; } static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted) { SRes res; CriticalSection_Enter(&p->mtProgress.cs); p->mtProgress.totalInSize += inSize; p->mtProgress.totalOutSize += outSize; if (p->mtProgress.res == SZ_OK && p->mtProgress.progress) if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK) p->mtProgress.res = SZ_ERROR_PROGRESS; *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); res = p->mtProgress.res; CriticalSection_Leave(&p->mtProgress.cs); return res; } static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex) { CriticalSection_Enter(&p->mtProgress.cs); if (!p->needInterrupt || interruptIndex < p->interruptIndex) { p->interruptIndex = interruptIndex; p->needInterrupt = True; } CriticalSection_Leave(&p->mtProgress.cs); } Byte *MtDec_GetCrossBuff(CMtDec *p) { Byte *cr = p->crossBlock; if (!cr) { cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); if (!cr) return NULL; p->crossBlock = cr; } return MTDEC__DATA_PTR_FROM_LINK(cr); } /* MtDec_ThreadFunc2() returns: 0 - in all normal cases (even for stream error or memory allocation error) (!= 0) - WRes error return by system threading function */ // #define MTDEC_ProgessStep (1 << 22) #define MTDEC_ProgessStep (1 << 0) static WRes MtDec_ThreadFunc2(CMtDecThread *t) { CMtDec *p = t->mtDec; PRF_STR_INT("MtDec_ThreadFunc2", t->index) // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index); for (;;) { SRes res, codeRes; BoolInt wasInterrupted, isAllocError, overflow, finish; SRes threadingErrorSRes; BoolInt needCode, needWrite, needContinue; size_t inDataSize_Start; UInt64 inDataSize; // UInt64 inDataSize_Full; UInt64 blockIndex; UInt64 inPrev = 0; UInt64 outPrev = 0; UInt64 inCodePos; UInt64 outCodePos; Byte *afterEndData = NULL; size_t afterEndData_Size = 0; BoolInt afterEndData_IsCross = False; BoolInt canCreateNewThread = False; // CMtDecCallbackInfo parse; CMtDecThread *nextThread; PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index) RINOK_THREAD(Event_Wait(&t->canRead)) if (p->exitThread) return 0; PRF_STR_INT("after Event_Wait(&t->canRead)", t->index) // if (t->index == 3) return 19; // for test blockIndex = p->blockIndex++; // PRF(printf("\ncanRead\n")) res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); finish = p->readWasFinished; needCode = False; needWrite = False; isAllocError = False; overflow = False; inDataSize_Start = 0; inDataSize = 0; // inDataSize_Full = 0; if (res == SZ_OK && !wasInterrupted) { // if (p->inStream) { CMtDecBufLink *prev = NULL; CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; size_t crossSize = p->crossEnd - p->crossStart; PRF(printf("\ncrossSize = %d\n", crossSize)); for (;;) { if (!link) { link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); if (!link) { finish = True; // p->allocError_for_Read_BlockIndex = blockIndex; isAllocError = True; break; } link->next = NULL; if (prev) { // static unsigned g_num = 0; // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev)); prev->next = link; } else t->inBuf = (void *)link; } { Byte *data = MTDEC__DATA_PTR_FROM_LINK(link); Byte *parseData = data; size_t size; if (crossSize != 0) { inDataSize = crossSize; // inDataSize_Full = inDataSize; inDataSize_Start = crossSize; size = crossSize; parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d", (int)p->crossStart, (int)p->crossEnd, (int)finish)); } else { size = p->inBufSize; res = SeqInStream_ReadMax(p->inStream, data, &size); // size = 10; // test inDataSize += size; // inDataSize_Full = inDataSize; if (!prev) inDataSize_Start = size; p->readProcessed += size; finish = (size != p->inBufSize); if (finish) p->readWasFinished = True; // res = E_INVALIDARG; // test if (res != SZ_OK) { // PRF(printf("\nRead error = %d\n", res)) // we want to decode all data before error p->readRes = res; // p->readError_BlockIndex = blockIndex; p->readWasFinished = True; finish = True; res = SZ_OK; // break; } if (inDataSize - inPrev >= MTDEC_ProgessStep) { res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); if (res != SZ_OK || wasInterrupted) break; inPrev = inDataSize; } } { CMtDecCallbackInfo parse; parse.startCall = (prev == NULL); parse.src = parseData; parse.srcSize = size; parse.srcFinished = finish; parse.canCreateNewThread = True; PRF(printf("\nParse size = %d\n", (unsigned)size)); p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse); PRF(printf(" Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state)); needWrite = True; canCreateNewThread = parse.canCreateNewThread; // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize); if ( // parseRes != SZ_OK || // inDataSize - (size - parse.srcSize) > p->inBlockMax // || parse.state == MTDEC_PARSE_OVERFLOW // || wasInterrupted ) { // Overflow or Parse error - switch from MT decoding to ST decoding finish = True; overflow = True; { PRF(printf("\n Overflow")); // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished)); PRF(printf("\n inDataSize = %d", (unsigned)inDataSize)); } if (crossSize != 0) memcpy(data, parseData, size); p->crossStart = 0; p->crossEnd = 0; break; } if (crossSize != 0) { memcpy(data, parseData, parse.srcSize); p->crossStart += parse.srcSize; } if (parse.state != MTDEC_PARSE_CONTINUE || finish) { // we don't need to parse in current thread anymore if (parse.state == MTDEC_PARSE_END) finish = True; needCode = True; // p->crossFinished = finish; if (parse.srcSize == size) { // full parsed - no cross transfer p->crossStart = 0; p->crossEnd = 0; break; } if (parse.state == MTDEC_PARSE_END) { afterEndData = parseData + parse.srcSize; afterEndData_Size = size - parse.srcSize; if (crossSize != 0) afterEndData_IsCross = True; // we reduce data size to required bytes (parsed only) inDataSize -= afterEndData_Size; if (!prev) inDataSize_Start = parse.srcSize; break; } { // partial parsed - need cross transfer if (crossSize != 0) inDataSize = parse.srcSize; // it's only parsed now else { // partial parsed - is not in initial cross block - we need to copy new data to cross block Byte *cr = MtDec_GetCrossBuff(p); if (!cr) { { PRF(printf("\ncross alloc error error\n")); // res = SZ_ERROR_MEM; finish = True; // p->allocError_for_Read_BlockIndex = blockIndex; isAllocError = True; break; } } { size_t crSize = size - parse.srcSize; inDataSize -= crSize; p->crossEnd = crSize; p->crossStart = 0; memcpy(cr, parseData + parse.srcSize, crSize); } } // inDataSize_Full = inDataSize; if (!prev) inDataSize_Start = parse.srcSize; // it's partial size (parsed only) finish = False; break; } } if (parse.srcSize != size) { res = SZ_ERROR_FAIL; PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res)); break; } } } prev = link; link = link->next; if (crossSize != 0) { crossSize = 0; p->crossStart = 0; p->crossEnd = 0; } } } if (res == SZ_OK) res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted); } codeRes = SZ_OK; if (res == SZ_OK && needCode && !wasInterrupted) { codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index); if (codeRes != SZ_OK) { needCode = False; finish = True; // SZ_ERROR_MEM is expected error here. // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later. // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding. } } if (res != SZ_OK || wasInterrupted) finish = True; nextThread = NULL; threadingErrorSRes = SZ_OK; if (!finish) { if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread) { SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]); if (res2 == SZ_OK) { // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads)); p->numStartedThreads++; } else { PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads)); if (p->numStartedThreads == 1) { // if only one thread is possible, we leave muti-threading code finish = True; needCode = False; threadingErrorSRes = res2; } else p->numStartedThreads_Limit = p->numStartedThreads; } } if (!finish) { unsigned nextIndex = t->index + 1; nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex]; RINOK_THREAD(Event_Set(&nextThread->canRead)) // We have started executing for new iteration (with next thread) // And that next thread now is responsible for possible exit from decoding (threading_code) } } // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite) // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block): // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration // - otherwise we stop decoding and exit from MtDec_ThreadFunc2() // Don't change (finish) variable in the further code // ---------- CODE ---------- inPrev = 0; outPrev = 0; inCodePos = 0; outCodePos = 0; if (res == SZ_OK && needCode && codeRes == SZ_OK) { BoolInt isStartBlock = True; CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; for (;;) { size_t inSize; int stop; if (isStartBlock) inSize = inDataSize_Start; else { UInt64 rem = inDataSize - inCodePos; inSize = p->inBufSize; if (inSize > rem) inSize = (size_t)rem; } inCodePos += inSize; stop = True; codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index, (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize, (inCodePos == inDataSize), // srcFinished &inCodePos, &outCodePos, &stop); if (codeRes != SZ_OK) { PRF(printf("\nCode Interrupt error = %x\n", codeRes)); // we interrupt only later blocks MtDec_Interrupt(p, blockIndex); break; } if (stop || inCodePos == inDataSize) break; { const UInt64 inDelta = inCodePos - inPrev; const UInt64 outDelta = outCodePos - outPrev; if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep) { // Sleep(1); res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted); if (res != SZ_OK || wasInterrupted) break; inPrev = inCodePos; outPrev = outCodePos; } } link = link->next; isStartBlock = False; } } // ---------- WRITE ---------- RINOK_THREAD(Event_Wait(&t->canWrite)) { BoolInt isErrorMode = False; BoolInt canRecode = True; BoolInt needWriteToStream = needWrite; if (p->exitThread) return 0; // it's never executed in normal cases if (p->wasInterrupted) wasInterrupted = True; else { if (codeRes != SZ_OK) // || !needCode // check it !!! { p->wasInterrupted = True; p->codeRes = codeRes; if (codeRes == SZ_ERROR_MEM) isAllocError = True; } if (threadingErrorSRes) { p->wasInterrupted = True; p->threadingErrorSRes = threadingErrorSRes; needWriteToStream = False; } if (isAllocError) { p->wasInterrupted = True; p->isAllocError = True; needWriteToStream = False; } if (overflow) { p->wasInterrupted = True; p->overflow = True; needWriteToStream = False; } } if (needCode) { if (wasInterrupted) { inCodePos = 0; outCodePos = 0; } { const UInt64 inDelta = inCodePos - inPrev; const UInt64 outDelta = outCodePos - outPrev; // if (inDelta != 0 || outDelta != 0) res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta); } } needContinue = (!finish); // if (res == SZ_OK && needWrite && !wasInterrupted) if (needWrite) { // p->inProcessed += inCodePos; PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size)); res = p->mtCallback->Write(p->mtCallbackObject, t->index, res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite afterEndData, afterEndData_Size, afterEndData_IsCross, &needContinue, &canRecode); // res = SZ_ERROR_FAIL; // for test PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue)); PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed)); if (res != SZ_OK) { PRF(printf("\nWrite error = %d\n", res)); isErrorMode = True; p->wasInterrupted = True; } if (res != SZ_OK || (!needContinue && !finish)) { PRF(printf("\nWrite Interrupt error = %x\n", res)); MtDec_Interrupt(p, blockIndex); } } if (canRecode) if (!needCode || res != SZ_OK || p->wasInterrupted || codeRes != SZ_OK || wasInterrupted || p->numFilledThreads != 0 || isErrorMode) { if (p->numFilledThreads == 0) p->filledThreadStart = t->index; if (inDataSize != 0 || !finish) { t->inDataSize_Start = inDataSize_Start; t->inDataSize = inDataSize; p->numFilledThreads++; } PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads)); PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart)); } if (!finish) { RINOK_THREAD(Event_Set(&nextThread->canWrite)) } else { if (needContinue) { // we restore decoding with new iteration RINOK_THREAD(Event_Set(&p->threads[0].canWrite)) } else { // we exit from decoding if (t->index == 0) return SZ_OK; p->exitThread = True; } RINOK_THREAD(Event_Set(&p->threads[0].canRead)) } } } } #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include #else #include #endif #endif typedef #ifdef _WIN32 UINT_PTR #elif 1 uintptr_t #else ptrdiff_t #endif MY_uintptr_t; static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp) { WRes res; CMtDecThread *t = (CMtDecThread *)pp; CMtDec *p; // fprintf(stdout, "\n%d = %p\n", t->index, &t); res = MtDec_ThreadFunc2(t); p = t->mtDec; if (res == 0) return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes; { // it's unexpected situation for some threading function error if (p->exitThreadWRes == 0) p->exitThreadWRes = res; PRF(printf("\nthread exit error = %d\n", res)); p->exitThread = True; Event_Set(&p->threads[0].canRead); Event_Set(&p->threads[0].canWrite); MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); } return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res; } static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp) { #ifdef USE_ALLOCA CMtDecThread *t = (CMtDecThread *)pp; // fprintf(stderr, "\n%d = %p - before", t->index, &t); t->allocaPtr = alloca(t->index * 128); #endif return MtDec_ThreadFunc1(pp); } int MtDec_PrepareRead(CMtDec *p) { if (p->crossBlock && p->crossStart == p->crossEnd) { ISzAlloc_Free(p->alloc, p->crossBlock); p->crossBlock = NULL; } { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) if (i > p->numStartedThreads || p->numFilledThreads <= (i >= p->filledThreadStart ? i - p->filledThreadStart : i + p->numStartedThreads - p->filledThreadStart)) MtDecThread_FreeInBufs(&p->threads[i]); } return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd); } const Byte *MtDec_Read(CMtDec *p, size_t *inLim) { while (p->numFilledThreads != 0) { CMtDecThread *t = &p->threads[p->filledThreadStart]; if (*inLim != 0) { { void *link = t->inBuf; void *next = ((CMtDecBufLink *)link)->next; ISzAlloc_Free(p->alloc, link); t->inBuf = next; } if (t->inDataSize == 0) { MtDecThread_FreeInBufs(t); if (--p->numFilledThreads == 0) break; if (++p->filledThreadStart == p->numStartedThreads) p->filledThreadStart = 0; t = &p->threads[p->filledThreadStart]; } } { size_t lim = t->inDataSize_Start; if (lim != 0) t->inDataSize_Start = 0; else { UInt64 rem = t->inDataSize; lim = p->inBufSize; if (lim > rem) lim = (size_t)rem; } t->inDataSize -= lim; *inLim = lim; return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf); } } { size_t crossSize = p->crossEnd - p->crossStart; if (crossSize != 0) { const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; *inLim = crossSize; p->crossStart = 0; p->crossEnd = 0; return data; } *inLim = 0; if (p->crossBlock) { ISzAlloc_Free(p->alloc, p->crossBlock); p->crossBlock = NULL; } return NULL; } } void MtDec_Construct(CMtDec *p) { unsigned i; p->inBufSize = (size_t)1 << 18; p->numThreadsMax = 0; p->inStream = NULL; // p->inData = NULL; // p->inDataSize = 0; p->crossBlock = NULL; p->crossStart = 0; p->crossEnd = 0; p->numFilledThreads = 0; p->progress = NULL; p->alloc = NULL; p->mtCallback = NULL; p->mtCallbackObject = NULL; p->allocatedBufsSize = 0; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CMtDecThread *t = &p->threads[i]; t->mtDec = p; t->index = i; t->inBuf = NULL; Event_Construct(&t->canRead); Event_Construct(&t->canWrite); Thread_CONSTRUCT(&t->thread) } // Event_Construct(&p->finishedEvent); CriticalSection_Init(&p->mtProgress.cs); } static void MtDec_Free(CMtDec *p) { unsigned i; p->exitThread = True; for (i = 0; i < MTDEC_THREADS_MAX; i++) MtDecThread_Destruct(&p->threads[i]); // Event_Close(&p->finishedEvent); if (p->crossBlock) { ISzAlloc_Free(p->alloc, p->crossBlock); p->crossBlock = NULL; } } void MtDec_Destruct(CMtDec *p) { MtDec_Free(p); CriticalSection_Delete(&p->mtProgress.cs); } SRes MtDec_Code(CMtDec *p) { unsigned i; p->inProcessed = 0; p->blockIndex = 1; // it must be larger than not_defined index (0) p->isAllocError = False; p->overflow = False; p->threadingErrorSRes = SZ_OK; p->needContinue = True; p->readWasFinished = False; p->needInterrupt = False; p->interruptIndex = (UInt64)(Int64)-1; p->readProcessed = 0; p->readRes = SZ_OK; p->codeRes = SZ_OK; p->wasInterrupted = False; p->crossStart = 0; p->crossEnd = 0; p->filledThreadStart = 0; p->numFilledThreads = 0; { unsigned numThreads = p->numThreadsMax; if (numThreads > MTDEC_THREADS_MAX) numThreads = MTDEC_THREADS_MAX; p->numStartedThreads_Limit = numThreads; p->numStartedThreads = 0; } if (p->inBufSize != p->allocatedBufsSize) { for (i = 0; i < MTDEC_THREADS_MAX; i++) { CMtDecThread *t = &p->threads[i]; if (t->inBuf) MtDecThread_FreeInBufs(t); } if (p->crossBlock) { ISzAlloc_Free(p->alloc, p->crossBlock); p->crossBlock = NULL; } p->allocatedBufsSize = p->inBufSize; } MtProgress_Init(&p->mtProgress, p->progress); // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent)) p->exitThread = False; p->exitThreadWRes = 0; { WRes wres; SRes sres; CMtDecThread *nextThread = &p->threads[p->numStartedThreads++]; // wres = MtDecThread_CreateAndStart(nextThread); wres = MtDecThread_CreateEvents(nextThread); if (wres == 0) { wres = Event_Set(&nextThread->canWrite); if (wres == 0) { wres = Event_Set(&nextThread->canRead); if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread); wres = (WRes)(MY_uintptr_t)res; if (wres != 0) { p->needContinue = False; MtDec_CloseThreads(p); }}}} // wres = 17; // for test // wres = Event_Wait(&p->finishedEvent); sres = MY_SRes_HRESULT_FROM_WRes(wres); if (sres != 0) p->threadingErrorSRes = sres; if ( // wres == 0 // wres != 0 // || p->mtc.codeRes == SZ_ERROR_MEM p->isAllocError || p->threadingErrorSRes != SZ_OK || p->overflow) { // p->needContinue = True; } else p->needContinue = False; if (p->needContinue) return SZ_OK; // if (sres != SZ_OK) return sres; // return SZ_ERROR_FAIL; } } #endif #undef PRF tmp41wklro_/C/MtDec.h0000444000175000001440000001102614412267100015465 0ustar nabijaczleweliusers/* MtDec.h -- Multi-thread Decoder 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_MT_DEC_H #define ZIP7_INC_MT_DEC_H #include "7zTypes.h" #ifndef Z7_ST #include "Threads.h" #endif EXTERN_C_BEGIN #ifndef Z7_ST #ifndef Z7_ST #define MTDEC_THREADS_MAX 32 #else #define MTDEC_THREADS_MAX 1 #endif typedef struct { ICompressProgressPtr progress; SRes res; UInt64 totalInSize; UInt64 totalOutSize; CCriticalSection cs; } CMtProgress; void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress); SRes MtProgress_Progress_ST(CMtProgress *p); SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); SRes MtProgress_GetError(CMtProgress *p); void MtProgress_SetError(CMtProgress *p, SRes res); struct CMtDec; typedef struct { struct CMtDec_ *mtDec; unsigned index; void *inBuf; size_t inDataSize_Start; // size of input data in start block UInt64 inDataSize; // total size of input data in all blocks CThread thread; CAutoResetEvent canRead; CAutoResetEvent canWrite; void *allocaPtr; } CMtDecThread; void MtDecThread_FreeInBufs(CMtDecThread *t); typedef enum { MTDEC_PARSE_CONTINUE, // continue this block with more input data MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread MTDEC_PARSE_NEW, // new block MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) } EMtDecParseState; typedef struct { // in int startCall; const Byte *src; size_t srcSize; // in : (srcSize == 0) is allowed // out : it's allowed to return less that actually was used ? int srcFinished; // out EMtDecParseState state; BoolInt canCreateNewThread; UInt64 outPos; // check it (size_t) } CMtDecCallbackInfo; typedef struct { void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); // PreCode() and Code(): // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks SRes (*PreCode)(void *p, unsigned coderIndex); SRes (*Code)(void *p, unsigned coderIndex, const Byte *src, size_t srcSize, int srcFinished, UInt64 *inCodePos, UInt64 *outCodePos, int *stop); // stop - means stop another Code calls /* Write() must be called, if Parse() was called set (needWrite) if { && (was not interrupted by progress) && (was not interrupted in previous block) } out: if (*needContinue), decoder still need to continue decoding with new iteration, even after MTDEC_PARSE_END if (*canRecode), we didn't flush current block data, so we still can decode current block later. */ SRes (*Write)(void *p, unsigned coderIndex, BoolInt needWriteToStream, const Byte *src, size_t srcSize, BoolInt isCross, // int srcFinished, BoolInt *needContinue, BoolInt *canRecode); } IMtDecCallback2; typedef struct CMtDec_ { /* input variables */ size_t inBufSize; /* size of input block */ unsigned numThreadsMax; // size_t inBlockMax; unsigned numThreadsMax_2; ISeqInStreamPtr inStream; // const Byte *inData; // size_t inDataSize; ICompressProgressPtr progress; ISzAllocPtr alloc; IMtDecCallback2 *mtCallback; void *mtCallbackObject; /* internal variables */ size_t allocatedBufsSize; BoolInt exitThread; WRes exitThreadWRes; UInt64 blockIndex; BoolInt isAllocError; BoolInt overflow; SRes threadingErrorSRes; BoolInt needContinue; // CAutoResetEvent finishedEvent; SRes readRes; SRes codeRes; BoolInt wasInterrupted; unsigned numStartedThreads_Limit; unsigned numStartedThreads; Byte *crossBlock; size_t crossStart; size_t crossEnd; UInt64 readProcessed; BoolInt readWasFinished; UInt64 inProcessed; unsigned filledThreadStart; unsigned numFilledThreads; #ifndef Z7_ST BoolInt needInterrupt; UInt64 interruptIndex; CMtProgress mtProgress; CMtDecThread threads[MTDEC_THREADS_MAX]; #endif } CMtDec; void MtDec_Construct(CMtDec *p); void MtDec_Destruct(CMtDec *p); /* MtDec_Code() returns: SZ_OK - in most cases MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function */ SRes MtDec_Code(CMtDec *p); Byte *MtDec_GetCrossBuff(CMtDec *p); int MtDec_PrepareRead(CMtDec *p); const Byte *MtDec_Read(CMtDec *p, size_t *inLim); #endif EXTERN_C_END #endif tmp41wklro_/C/Ppmd.h0000444000175000001440000001275514401127160015402 0ustar nabijaczleweliusers/* Ppmd.h -- PPMD codec common code 2023-03-05 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #ifndef ZIP7_INC_PPMD_H #define ZIP7_INC_PPMD_H #include "CpuArch.h" EXTERN_C_BEGIN #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) /* PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block. if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields. if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields. if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed, if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional, and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit. PPMD code works slightly faster in (PPMD_32BIT) mode. */ #define PPMD_32BIT #endif #define PPMD_INT_BITS 7 #define PPMD_PERIOD_BITS 7 #define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) #define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) #define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) #define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) #define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) #define PPMD_N1 4 #define PPMD_N2 4 #define PPMD_N3 4 #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) MY_CPU_pragma_pack_push_1 /* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ /* SEE-contexts for PPM-contexts with masked symbols */ typedef struct { UInt16 Summ; /* Freq */ Byte Shift; /* Speed of Freq change; low Shift is for fast change */ Byte Count; /* Count to next change of Shift */ } CPpmd_See; #define Ppmd_See_UPDATE(p) \ { if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ { (p)->Summ = (UInt16)((p)->Summ << 1); \ (p)->Count = (Byte)(3 << (p)->Shift++); }} typedef struct { Byte Symbol; Byte Freq; UInt16 Successor_0; UInt16 Successor_1; } CPpmd_State; typedef struct CPpmd_State2_ { Byte Symbol; Byte Freq; } CPpmd_State2; typedef struct CPpmd_State4_ { UInt16 Successor_0; UInt16 Successor_1; } CPpmd_State4; MY_CPU_pragma_pop /* PPMD code can write full CPpmd_State structure data to CPpmd*_Context at (byte offset = 2) instead of some fields of original CPpmd*_Context structure. If we use pointers to different types, but that point to shared memory space, we can have aliasing problem (strict aliasing). XLC compiler in -O2 mode can change the order of memory write instructions in relation to read instructions, if we have use pointers to different types. To solve that aliasing problem we use combined CPpmd*_Context structure with unions that contain the fields from both structures: the original CPpmd*_Context and CPpmd_State. So we can access the fields from both structures via one pointer, and the compiler doesn't change the order of write instructions in relation to read instructions. If we don't use memory write instructions to shared memory in some local code, and we use only reading instructions (read only), then probably it's safe to use pointers to different types for reading. */ #ifdef PPMD_32BIT #define Ppmd_Ref_Type(type) type * #define Ppmd_GetRef(p, ptr) (ptr) #define Ppmd_GetPtr(p, ptr) (ptr) #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr) #else #define Ppmd_Ref_Type(type) UInt32 #define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) #define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs))) #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs)) #endif // PPMD_32BIT typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref; typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref; typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref; /* #ifdef MY_CPU_LE_UNALIGN // the unaligned 32-bit access latency can be too large, if the data is not in L1 cache. #define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0) #define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v) #else */ /* We can write 16-bit halves to 32-bit (Successor) field in any selected order. But the native order is more consistent way. So we use the native order, if LE/BE order can be detected here at compile time. */ #ifdef MY_CPU_BE #define Ppmd_GET_SUCCESSOR(p) \ ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) ) #define Ppmd_SET_SUCCESSOR(p, v) { \ (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \ (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); } #else #define Ppmd_GET_SUCCESSOR(p) \ ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) ) #define Ppmd_SET_SUCCESSOR(p, v) { \ (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \ (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); } #endif // #endif #define PPMD_SetAllBitsIn256Bytes(p) \ { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }} EXTERN_C_END #endif tmp41wklro_/C/Ppmd7.c0000444000175000001440000007253014476326460015501 0ustar nabijaczleweliusers/* Ppmd7.c -- PPMdH codec 2023-09-07 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" #include #include "Ppmd7.h" /* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */ // #define PPMD7_ORDER_0_SUPPPORT MY_ALIGN(16) static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; MY_ALIGN(16) static const UInt16 PPMD7_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; #define MAX_FREQ 124 #define UNIT_SIZE 12 #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) #define I2U(indx) ((unsigned)p->Indx2Units[indx]) #define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx]) #define REF(ptr) Ppmd_GetRef(p, ptr) #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) #define STATS(ctx) Ppmd7_GetStats(p, ctx) #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) #define SUFFIX(ctx) CTX((ctx)->Suffix) typedef CPpmd7_Context * PPMD7_CTX_PTR; struct CPpmd7_Node_; typedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref; typedef struct CPpmd7_Node_ { UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ UInt16 NU; CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ CPpmd7_Node_Ref Prev; } CPpmd7_Node; #define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd7_Node) void Ppmd7_Construct(CPpmd7 *p) { unsigned i, k, m; p->Base = NULL; for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) { unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); do { p->Units2Indx[k++] = (Byte)i; } while (--step); p->Indx2Units[i] = (Byte)k; } p->NS2BSIndx[0] = (0 << 1); p->NS2BSIndx[1] = (1 << 1); memset(p->NS2BSIndx + 2, (2 << 1), 9); memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); for (i = 0; i < 3; i++) p->NS2Indx[i] = (Byte)i; for (m = i, k = 1; i < 256; i++) { p->NS2Indx[i] = (Byte)m; if (--k == 0) k = (++m) - 2; } memcpy(p->ExpEscape, PPMD7_kExpEscape, 16); } void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Base); p->Size = 0; p->Base = NULL; } BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) { if (!p->Base || p->Size != size) { Ppmd7_Free(p, alloc); p->AlignOffset = (4 - size) & 3; if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL) return False; p->Size = size; } return True; } // ---------- Internal Memory Allocator ---------- /* We can use CPpmd7_Node in list of free units (as in Ppmd8) But we still need one additional list walk pass in Ppmd7_GlueFreeBlocks(). So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in Ppmd7_InsertNode() / Ppmd7_RemoveNode() */ #define EMPTY_NODE 0 static void Ppmd7_InsertNode(CPpmd7 *p, void *node, unsigned indx) { *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx]; p->FreeList[indx] = REF(node); } static void *Ppmd7_RemoveNode(CPpmd7 *p, unsigned indx) { CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); p->FreeList[indx] = *node; // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]); // p->FreeList[indx] = node->Next; return node; } static void Ppmd7_SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) { unsigned i, nu = I2U(oldIndx) - I2U(newIndx); ptr = (Byte *)ptr + U2B(I2U(newIndx)); if (I2U(i = U2I(nu)) != nu) { unsigned k = I2U(--i); Ppmd7_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); } Ppmd7_InsertNode(p, ptr, i); } /* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ typedef union { CPpmd7_Node Node; CPpmd7_Node_Ref NextRef; } CPpmd7_Node_Union; /* Original PPmdH (Ppmd7) code uses doubly linked list in Ppmd7_GlueFreeBlocks() we use single linked list similar to Ppmd8 code */ static void Ppmd7_GlueFreeBlocks(CPpmd7 *p) { /* we use first UInt16 field of 12-bytes UNITs as record type stamp CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0 CPpmd7_Context { UInt16 NumStats; : NumStats != 0 CPpmd7_Node { UInt16 Stamp : Stamp == 0 for free record : Stamp == 1 for head record and guard Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record. */ CPpmd7_Node_Ref head, n = 0; p->GlueCount = 255; /* we set guard NODE at LoUnit */ if (p->LoUnit != p->HiUnit) ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1; { /* Create list of free blocks. We still need one additional list walk pass before Glue. */ unsigned i; for (i = 0; i < PPMD_NUM_INDEXES; i++) { const UInt16 nu = I2U_UInt16(i); CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; p->FreeList[i] = 0; while (next != 0) { /* Don't change the order of the following commands: */ CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next); const CPpmd7_Node_Ref tmp = next; next = un->NextRef; un->Node.Stamp = EMPTY_NODE; un->Node.NU = nu; un->Node.Next = n; n = tmp; } } } head = n; /* Glue and Fill must walk the list in same direction */ { /* Glue free blocks */ CPpmd7_Node_Ref *prev = &head; while (n) { CPpmd7_Node *node = NODE(n); UInt32 nu = node->NU; n = node->Next; if (nu == 0) { *prev = n; continue; } prev = &node->Next; for (;;) { CPpmd7_Node *node2 = node + nu; nu += node2->NU; if (node2->Stamp != EMPTY_NODE || nu >= 0x10000) break; node->NU = (UInt16)nu; node2->NU = 0; } } } /* Fill lists of free blocks */ for (n = head; n != 0;) { CPpmd7_Node *node = NODE(n); UInt32 nu = node->NU; unsigned i; n = node->Next; if (nu == 0) continue; for (; nu > 128; nu -= 128, node += 128) Ppmd7_InsertNode(p, node, PPMD_NUM_INDEXES - 1); if (I2U(i = U2I(nu)) != nu) { unsigned k = I2U(--i); Ppmd7_InsertNode(p, node + k, (unsigned)nu - k - 1); } Ppmd7_InsertNode(p, node, i); } } Z7_NO_INLINE static void *Ppmd7_AllocUnitsRare(CPpmd7 *p, unsigned indx) { unsigned i; if (p->GlueCount == 0) { Ppmd7_GlueFreeBlocks(p); if (p->FreeList[indx] != 0) return Ppmd7_RemoveNode(p, indx); } i = indx; do { if (++i == PPMD_NUM_INDEXES) { UInt32 numBytes = U2B(I2U(indx)); Byte *us = p->UnitsStart; p->GlueCount--; return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL; } } while (p->FreeList[i] == 0); { void *block = Ppmd7_RemoveNode(p, i); Ppmd7_SplitBlock(p, block, i, indx); return block; } } static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx) { if (p->FreeList[indx] != 0) return Ppmd7_RemoveNode(p, indx); { UInt32 numBytes = U2B(I2U(indx)); Byte *lo = p->LoUnit; if ((UInt32)(p->HiUnit - lo) >= numBytes) { p->LoUnit = lo + numBytes; return lo; } } return Ppmd7_AllocUnitsRare(p, indx); } #define MEM_12_CPY(dest, src, num) \ { UInt32 *d = (UInt32 *)(dest); \ const UInt32 *z = (const UInt32 *)(src); \ unsigned n = (num); \ do { \ d[0] = z[0]; \ d[1] = z[1]; \ d[2] = z[2]; \ z += 3; \ d += 3; \ } while (--n); \ } /* static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) { unsigned i0 = U2I(oldNU); unsigned i1 = U2I(newNU); if (i0 == i1) return oldPtr; if (p->FreeList[i1] != 0) { void *ptr = Ppmd7_RemoveNode(p, i1); MEM_12_CPY(ptr, oldPtr, newNU) Ppmd7_InsertNode(p, oldPtr, i0); return ptr; } Ppmd7_SplitBlock(p, oldPtr, i0, i1); return oldPtr; } */ #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) { Ppmd_SET_SUCCESSOR(p, v) } Z7_NO_INLINE static void Ppmd7_RestartModel(CPpmd7 *p) { unsigned i, k; memset(p->FreeList, 0, sizeof(p->FreeList)); p->Text = p->Base + p->AlignOffset; p->HiUnit = p->Text + p->Size; p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; p->GlueCount = 0; p->OrderFall = p->MaxOrder; p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; p->PrevSuccess = 0; { CPpmd7_Context *mc = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd7_AllocUnits(p, PPMD_NUM_INDEXES - 1); */ p->LoUnit += U2B(256 / 2); p->MaxContext = p->MinContext = mc; p->FoundState = s; mc->NumStats = 256; mc->Union2.SummFreq = 256 + 1; mc->Union4.Stats = REF(s); mc->Suffix = 0; for (i = 0; i < 256; i++, s++) { s->Symbol = (Byte)i; s->Freq = 1; SetSuccessor(s, 0); } #ifdef PPMD7_ORDER_0_SUPPPORT if (p->MaxOrder == 0) { CPpmd_Void_Ref r = REF(mc); s = p->FoundState; for (i = 0; i < 256; i++, s++) SetSuccessor(s, r); return; } #endif } for (i = 0; i < 128; i++) for (k = 0; k < 8; k++) { unsigned m; UInt16 *dest = p->BinSumm[i] + k; const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD7_kInitBinEsc[k] / (i + 2)); for (m = 0; m < 64; m += 8) dest[m] = val; } for (i = 0; i < 25; i++) { CPpmd_See *s = p->See[i]; unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4)); for (k = 0; k < 16; k++, s++) { s->Summ = (UInt16)summ; s->Shift = (PPMD_PERIOD_BITS - 4); s->Count = 4; } } p->DummySee.Summ = 0; /* unused */ p->DummySee.Shift = PPMD_PERIOD_BITS; p->DummySee.Count = 64; /* unused */ } void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) { p->MaxOrder = maxOrder; Ppmd7_RestartModel(p); } /* Ppmd7_CreateSuccessors() It's called when (FoundState->Successor) is RAW-Successor, that is the link to position in Raw text. So we create Context records and write the links to FoundState->Successor and to identical RAW-Successors in suffix contexts of MinContex. The function returns: if (OrderFall == 0) then MinContext is already at MAX order, { return pointer to new or existing context of same MAX order } else { return pointer to new real context that will be (Order+1) in comparison with MinContext also it can return pointer to real context of same order, */ Z7_NO_INLINE static PPMD7_CTX_PTR Ppmd7_CreateSuccessors(CPpmd7 *p) { PPMD7_CTX_PTR c = p->MinContext; CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); Byte newSym, newFreq; unsigned numPs = 0; CPpmd_State *ps[PPMD7_MAX_ORDER]; if (p->OrderFall != 0) ps[numPs++] = p->FoundState; while (c->Suffix) { CPpmd_Void_Ref successor; CPpmd_State *s; c = SUFFIX(c); if (c->NumStats != 1) { Byte sym = p->FoundState->Symbol; for (s = STATS(c); s->Symbol != sym; s++); } else { s = ONE_STATE(c); } successor = SUCCESSOR(s); if (successor != upBranch) { // (c) is real record Context here, c = CTX(successor); if (numPs == 0) { // (c) is real record MAX Order Context here, // So we don't need to create any new contexts. return c; } break; } ps[numPs++] = s; } // All created contexts will have single-symbol with new RAW-Successor // All new RAW-Successors will point to next position in RAW text // after FoundState->Successor newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch); upBranch++; if (c->NumStats == 1) newFreq = ONE_STATE(c)->Freq; else { UInt32 cf, s0; CPpmd_State *s; for (s = STATS(c); s->Symbol != newSym; s++); cf = (UInt32)s->Freq - 1; s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf; /* cf - is frequency of symbol that will be Successor in new context records. s0 - is commulative frequency sum of another symbols from parent context. max(newFreq)= (s->Freq + 1), when (s0 == 1) we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[] so (s->Freq < 128) - is requirement for multi-symbol contexts */ newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1)); } // Create new single-symbol contexts from low order to high order in loop do { PPMD7_CTX_PTR c1; /* = AllocContext(p); */ if (p->HiUnit != p->LoUnit) c1 = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); else if (p->FreeList[0] != 0) c1 = (PPMD7_CTX_PTR)Ppmd7_RemoveNode(p, 0); else { c1 = (PPMD7_CTX_PTR)Ppmd7_AllocUnitsRare(p, 0); if (!c1) return NULL; } c1->NumStats = 1; ONE_STATE(c1)->Symbol = newSym; ONE_STATE(c1)->Freq = newFreq; SetSuccessor(ONE_STATE(c1), upBranch); c1->Suffix = REF(c); SetSuccessor(ps[--numPs], REF(c1)); c = c1; } while (numPs != 0); return c; } #define SWAP_STATES(s) \ { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } void Ppmd7_UpdateModel(CPpmd7 *p); Z7_NO_INLINE void Ppmd7_UpdateModel(CPpmd7 *p) { CPpmd_Void_Ref maxSuccessor, minSuccessor; PPMD7_CTX_PTR c, mc; unsigned s0, ns; if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) { /* Update Freqs in Suffix Context */ c = SUFFIX(p->MinContext); if (c->NumStats == 1) { CPpmd_State *s = ONE_STATE(c); if (s->Freq < 32) s->Freq++; } else { CPpmd_State *s = STATS(c); Byte sym = p->FoundState->Symbol; if (s->Symbol != sym) { do { // s++; if (s->Symbol == sym) break; s++; } while (s->Symbol != sym); if (s[0].Freq >= s[-1].Freq) { SWAP_STATES(s) s--; } } if (s->Freq < MAX_FREQ - 9) { s->Freq = (Byte)(s->Freq + 2); c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); } } } if (p->OrderFall == 0) { /* MAX ORDER context */ /* (FoundState->Successor) is RAW-Successor. */ p->MaxContext = p->MinContext = Ppmd7_CreateSuccessors(p); if (!p->MinContext) { Ppmd7_RestartModel(p); return; } SetSuccessor(p->FoundState, REF(p->MinContext)); return; } /* NON-MAX ORDER context */ { Byte *text = p->Text; *text++ = p->FoundState->Symbol; p->Text = text; if (text >= p->UnitsStart) { Ppmd7_RestartModel(p); return; } maxSuccessor = REF(text); } minSuccessor = SUCCESSOR(p->FoundState); if (minSuccessor) { // there is Successor for FoundState in MinContext. // So the next context will be one order higher than MinContext. if (minSuccessor <= maxSuccessor) { // minSuccessor is RAW-Successor. So we will create real contexts records: PPMD7_CTX_PTR cs = Ppmd7_CreateSuccessors(p); if (!cs) { Ppmd7_RestartModel(p); return; } minSuccessor = REF(cs); } // minSuccessor now is real Context pointer that points to existing (Order+1) context if (--p->OrderFall == 0) { /* if we move to MaxOrder context, then minSuccessor will be common Succesor for both: MinContext that is (MaxOrder - 1) MaxContext that is (MaxOrder) so we don't need new RAW-Successor, and we can use real minSuccessor as succssors for both MinContext and MaxContext. */ maxSuccessor = minSuccessor; /* if (MaxContext != MinContext) { there was order fall from MaxOrder and we don't need current symbol to transfer some RAW-Succesors to real contexts. So we roll back pointer in raw data for one position. } */ p->Text -= (p->MaxContext != p->MinContext); } } else { /* FoundState has NULL-Successor here. And only root 0-order context can contain NULL-Successors. We change Successor in FoundState to RAW-Successor, And next context will be same 0-order root Context. */ SetSuccessor(p->FoundState, maxSuccessor); minSuccessor = REF(p->MinContext); } mc = p->MinContext; c = p->MaxContext; p->MaxContext = p->MinContext = CTX(minSuccessor); if (c == mc) return; // s0 : is pure Escape Freq s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1); do { unsigned ns1; UInt32 sum; if ((ns1 = c->NumStats) != 1) { if ((ns1 & 1) == 0) { /* Expand for one UNIT */ const unsigned oldNU = ns1 >> 1; const unsigned i = U2I(oldNU); if (i != U2I((size_t)oldNU + 1)) { void *ptr = Ppmd7_AllocUnits(p, i + 1); void *oldPtr; if (!ptr) { Ppmd7_RestartModel(p); return; } oldPtr = STATS(c); MEM_12_CPY(ptr, oldPtr, oldNU) Ppmd7_InsertNode(p, oldPtr, i); c->Union4.Stats = STATS_REF(ptr); } } sum = c->Union2.SummFreq; /* max increase of Escape_Freq is 3 here. total increase of Union2.SummFreq for all symbols is less than 256 here */ sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1))); /* original PPMdH uses 16-bit variable for (sum) here. But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ // sum = (UInt16)sum; } else { // instead of One-symbol context we create 2-symbol context CPpmd_State *s = (CPpmd_State*)Ppmd7_AllocUnits(p, 0); if (!s) { Ppmd7_RestartModel(p); return; } { unsigned freq = c->Union2.State2.Freq; // s = *ONE_STATE(c); s->Symbol = c->Union2.State2.Symbol; s->Successor_0 = c->Union4.State4.Successor_0; s->Successor_1 = c->Union4.State4.Successor_1; // SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of // (Successor_0 and Successor_1) in LE/BE. c->Union4.Stats = REF(s); if (freq < MAX_FREQ / 4 - 1) freq <<= 1; else freq = MAX_FREQ - 4; // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context s->Freq = (Byte)freq; // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here sum = (UInt32)(freq + p->InitEsc + (ns > 3)); } } { CPpmd_State *s = STATS(c) + ns1; UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq; UInt32 sf = (UInt32)s0 + sum; s->Symbol = p->FoundState->Symbol; c->NumStats = (UInt16)(ns1 + 1); SetSuccessor(s, maxSuccessor); if (cf < 6 * sf) { cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf); sum += 3; /* It can add (0, 1, 2) to Escape_Freq */ } else { cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); sum += cf; } c->Union2.SummFreq = (UInt16)sum; s->Freq = (Byte)cf; } c = SUFFIX(c); } while (c != mc); } Z7_NO_INLINE static void Ppmd7_Rescale(CPpmd7 *p) { unsigned i, adder, sumFreq, escFreq; CPpmd_State *stats = STATS(p->MinContext); CPpmd_State *s = p->FoundState; /* Sort the list by Freq */ if (s != stats) { CPpmd_State tmp = *s; do s[0] = s[-1]; while (--s != stats); *s = tmp; } sumFreq = s->Freq; escFreq = p->MinContext->Union2.SummFreq - sumFreq; /* if (p->OrderFall == 0), adder = 0 : it's allowed to remove symbol from MAX Order context if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context */ adder = (p->OrderFall != 0); #ifdef PPMD7_ORDER_0_SUPPPORT adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context #endif sumFreq = (sumFreq + 4 + adder) >> 1; i = (unsigned)p->MinContext->NumStats - 1; s->Freq = (Byte)sumFreq; do { unsigned freq = (++s)->Freq; escFreq -= freq; freq = (freq + adder) >> 1; sumFreq += freq; s->Freq = (Byte)freq; if (freq > s[-1].Freq) { CPpmd_State tmp = *s; CPpmd_State *s1 = s; do { s1[0] = s1[-1]; } while (--s1 != stats && freq > s1[-1].Freq); *s1 = tmp; } } while (--i); if (s->Freq == 0) { /* Remove all items with Freq == 0 */ CPpmd7_Context *mc; unsigned numStats, numStatsNew, n0, n1; i = 0; do { i++; } while ((--s)->Freq == 0); /* We increase (escFreq) for the number of removed symbols. So we will have (0.5) increase for Escape_Freq in avarage per removed symbol after Escape_Freq halving */ escFreq += i; mc = p->MinContext; numStats = mc->NumStats; numStatsNew = numStats - i; mc->NumStats = (UInt16)(numStatsNew); n0 = (numStats + 1) >> 1; if (numStatsNew == 1) { /* Create Single-Symbol context */ unsigned freq = stats->Freq; do { escFreq >>= 1; freq = (freq + 1) >> 1; } while (escFreq > 1); s = ONE_STATE(mc); *s = *stats; s->Freq = (Byte)freq; // (freq <= 260 / 4) p->FoundState = s; Ppmd7_InsertNode(p, stats, U2I(n0)); return; } n1 = (numStatsNew + 1) >> 1; if (n0 != n1) { // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); unsigned i0 = U2I(n0); unsigned i1 = U2I(n1); if (i0 != i1) { if (p->FreeList[i1] != 0) { void *ptr = Ppmd7_RemoveNode(p, i1); p->MinContext->Union4.Stats = STATS_REF(ptr); MEM_12_CPY(ptr, (const void *)stats, n1) Ppmd7_InsertNode(p, stats, i0); } else Ppmd7_SplitBlock(p, stats, i0, i1); } } } { CPpmd7_Context *mc = p->MinContext; mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); // Escape_Freq halving here p->FoundState = STATS(mc); } } CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) { CPpmd_See *see; const CPpmd7_Context *mc = p->MinContext; unsigned numStats = mc->NumStats; if (numStats != 256) { unsigned nonMasked = numStats - numMasked; see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats) + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats) + 4 * (unsigned)(numMasked > nonMasked) + p->HiBitsFlag; { // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ const unsigned summ = (UInt16)see->Summ; // & 0xFFFF const unsigned r = (summ >> see->Shift); see->Summ = (UInt16)(summ - r); *escFreq = (UInt32)(r + (r == 0)); } } else { see = &p->DummySee; *escFreq = 1; } return see; } static void Ppmd7_NextContext(CPpmd7 *p) { PPMD7_CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); if (p->OrderFall == 0 && (const Byte *)c > p->Text) p->MaxContext = p->MinContext = c; else Ppmd7_UpdateModel(p); } void Ppmd7_Update1(CPpmd7 *p) { CPpmd_State *s = p->FoundState; unsigned freq = s->Freq; freq += 4; p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); s->Freq = (Byte)freq; if (freq > s[-1].Freq) { SWAP_STATES(s) p->FoundState = --s; if (freq > MAX_FREQ) Ppmd7_Rescale(p); } Ppmd7_NextContext(p); } void Ppmd7_Update1_0(CPpmd7 *p) { CPpmd_State *s = p->FoundState; CPpmd7_Context *mc = p->MinContext; unsigned freq = s->Freq; const unsigned summFreq = mc->Union2.SummFreq; p->PrevSuccess = (2 * freq > summFreq); p->RunLength += (Int32)p->PrevSuccess; mc->Union2.SummFreq = (UInt16)(summFreq + 4); freq += 4; s->Freq = (Byte)freq; if (freq > MAX_FREQ) Ppmd7_Rescale(p); Ppmd7_NextContext(p); } /* void Ppmd7_UpdateBin(CPpmd7 *p) { unsigned freq = p->FoundState->Freq; p->FoundState->Freq = (Byte)(freq + (freq < 128)); p->PrevSuccess = 1; p->RunLength++; Ppmd7_NextContext(p); } */ void Ppmd7_Update2(CPpmd7 *p) { CPpmd_State *s = p->FoundState; unsigned freq = s->Freq; freq += 4; p->RunLength = p->InitRL; p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); s->Freq = (Byte)freq; if (freq > MAX_FREQ) Ppmd7_Rescale(p); Ppmd7_UpdateModel(p); } /* PPMd Memory Map: { [ 0 ] contains subset of original raw text, that is required to create context records, Some symbols are not written, when max order context was reached [ Text ] free area [ UnitsStart ] CPpmd_State vectors and CPpmd7_Context records [ LoUnit ] free area for CPpmd_State and CPpmd7_Context items [ HiUnit ] CPpmd7_Context records [ Size ] end of array } These addresses don't cross at any time. And the following condtions is true for addresses: (0 <= Text < UnitsStart <= LoUnit <= HiUnit <= Size) Raw text is BYTE--aligned. the data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs. Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record. The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors. The code doesn't free UNITs allocated for CPpmd7_Context records. The code calls Ppmd7_RestartModel(), when there is no free memory for allocation. And Ppmd7_RestartModel() changes the state to orignal start state, with full free block. The code allocates UNITs with the following order: Allocation of 1 UNIT for Context record - from free space (HiUnit) down to (LoUnit) - from FreeList[0] - Ppmd7_AllocUnitsRare() Ppmd7_AllocUnits() for CPpmd_State vectors: - from FreeList[i] - from free space (LoUnit) up to (HiUnit) - Ppmd7_AllocUnitsRare() Ppmd7_AllocUnitsRare() - if (GlueCount == 0) { Glue lists, GlueCount = 255, allocate from FreeList[i]] } - loop for all higher sized FreeList[...] lists - from (UnitsStart - Text), GlueCount-- - ERROR Each Record with Context contains the CPpmd_State vector, where each CPpmd_State contains the link to Successor. There are 3 types of Successor: 1) NULL-Successor - NULL pointer. NULL-Successor links can be stored only in 0-order Root Context Record. We use 0 value as NULL-Successor 2) RAW-Successor - the link to position in raw text, that "RAW-Successor" is being created after first occurrence of new symbol for some existing context record. (RAW-Successor > 0). 3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1), that record is being created when we go via RAW-Successor again. For any successors at any time: the following condtions are true for Successor links: (NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor) ---------- Symbol Frequency, SummFreq and Range in Range_Coder ---------- CPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq The PPMd code tries to fulfill the condition: (SummFreq <= (256 * 128 = RC::kBot)) We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124) So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol. If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7. SummFreq and Escape_Freq can be changed in Ppmd7_Rescale() and *Update*() functions. Ppmd7_Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Ppmd7_Rescale() for max-order context. When the PPMd code still break (Total <= RC::Range) condition in range coder, we have two ways to resolve that problem: 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases. 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value. */ #undef MAX_FREQ #undef UNIT_SIZE #undef U2B #undef U2I #undef I2U #undef I2U_UInt16 #undef REF #undef STATS_REF #undef CTX #undef STATS #undef ONE_STATE #undef SUFFIX #undef NODE #undef EMPTY_NODE #undef MEM_12_CPY #undef SUCCESSOR #undef SWAP_STATES tmp41wklro_/C/Ppmd7.h0000444000175000001440000001100614412267100015456 0ustar nabijaczleweliusers/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec 2023-04-02 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ #ifndef ZIP7_INC_PPMD7_H #define ZIP7_INC_PPMD7_H #include "Ppmd.h" EXTERN_C_BEGIN #define PPMD7_MIN_ORDER 2 #define PPMD7_MAX_ORDER 64 #define PPMD7_MIN_MEM_SIZE (1 << 11) #define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) struct CPpmd7_Context_; typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref; // MY_CPU_pragma_pack_push_1 typedef struct CPpmd7_Context_ { UInt16 NumStats; union { UInt16 SummFreq; CPpmd_State2 State2; } Union2; union { CPpmd_State_Ref Stats; CPpmd_State4 State4; } Union4; CPpmd7_Context_Ref Suffix; } CPpmd7_Context; // MY_CPU_pragma_pop #define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2) typedef struct { UInt32 Range; UInt32 Code; UInt32 Low; IByteInPtr Stream; } CPpmd7_RangeDec; typedef struct { UInt32 Range; Byte Cache; // Byte _dummy_[3]; UInt64 Low; UInt64 CacheSize; IByteOutPtr Stream; } CPpmd7z_RangeEnc; typedef struct { CPpmd7_Context *MinContext, *MaxContext; CPpmd_State *FoundState; unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; Int32 RunLength, InitRL; /* must be 32-bit at least */ UInt32 Size; UInt32 GlueCount; UInt32 AlignOffset; Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; union { CPpmd7_RangeDec dec; CPpmd7z_RangeEnc enc; } rc; Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment Byte Units2Indx[128]; CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; Byte NS2BSIndx[256], NS2Indx[256]; Byte ExpEscape[16]; CPpmd_See DummySee, See[25][16]; UInt16 BinSumm[128][64]; // int LastSymbol; } CPpmd7; void Ppmd7_Construct(CPpmd7 *p); BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); #define Ppmd7_WasAllocated(p) ((p)->Base != NULL) /* ---------- Internal Functions ---------- */ #define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr) #define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context) #define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State) void Ppmd7_Update1(CPpmd7 *p); void Ppmd7_Update1_0(CPpmd7 *p); void Ppmd7_Update2(CPpmd7 *p); #define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3)) #define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4)) // #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3)) // #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4)) #define Ppmd7_GetBinSumm(p) \ &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \ [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \ + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \ + PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \ + (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ] CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); /* We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure: 1) Ppmd7a_*: original PPMdH 2) Ppmd7z_*: modified PPMdH with 7z Range Coder Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH) */ /* ---------- Decode ---------- */ #define PPMD7_SYM_END (-1) #define PPMD7_SYM_ERROR (-2) /* You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init() Ppmd7*_DecodeSymbol() out: >= 0 : decoded byte -1 : PPMD7_SYM_END : End of payload marker -2 : PPMD7_SYM_ERROR : Data error */ /* Ppmd7a_* : original PPMdH */ BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p); #define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0) int Ppmd7a_DecodeSymbol(CPpmd7 *p); /* Ppmd7z_* : modified PPMdH with 7z Range Coder */ BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p); #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) int Ppmd7z_DecodeSymbol(CPpmd7 *p); // Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim); /* ---------- Encode ---------- */ void Ppmd7z_Init_RangeEnc(CPpmd7 *p); void Ppmd7z_Flush_RangeEnc(CPpmd7 *p); // void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol); void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim); EXTERN_C_END #endif tmp41wklro_/C/Ppmd7Dec.c0000444000175000001440000001653614476326460016121 0ustar nabijaczleweliusers/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder 2023-09-07 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" #include "Ppmd7.h" #define kTopValue ((UInt32)1 << 24) #define READ_BYTE(p) IByteIn_Read((p)->Stream) BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p) { unsigned i; p->Code = 0; p->Range = 0xFFFFFFFF; if (READ_BYTE(p) != 0) return False; for (i = 0; i < 4; i++) p->Code = (p->Code << 8) | READ_BYTE(p); return (p->Code < 0xFFFFFFFF); } #define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \ { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8; #define RC_NORM_1(p) RC_NORM_BASE(p) } #define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} // we must use only one type of Normalization from two: LOCAL or REMOTE #define RC_NORM_LOCAL(p) // RC_NORM(p) #define RC_NORM_REMOTE(p) RC_NORM(p) #define R (&p->rc.dec) Z7_FORCE_INLINE // Z7_NO_INLINE static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size) { R->Code -= start * R->Range; R->Range *= size; RC_NORM_LOCAL(R) } #define RC_Decode(start, size) Ppmd7z_RD_Decode(p, start, size); #define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) #define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) // typedef CPpmd7_Context * CTX_PTR; #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) void Ppmd7_UpdateModel(CPpmd7 *p); #define MASK(sym) ((Byte *)charMask)[sym] // Z7_FORCE_INLINE // static int Ppmd7z_DecodeSymbol(CPpmd7 *p) { size_t charMask[256 / sizeof(size_t)]; if (p->MinContext->NumStats != 1) { CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); unsigned i; UInt32 count, hiCnt; const UInt32 summFreq = p->MinContext->Union2.SummFreq; count = RC_GetThreshold(summFreq); hiCnt = count; if ((Int32)(count -= s->Freq) < 0) { Byte sym; RC_DecodeFinal(0, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1_0(p); return sym; } p->PrevSuccess = 0; i = (unsigned)p->MinContext->NumStats - 1; do { if ((Int32)(count -= (++s)->Freq) < 0) { Byte sym; RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1(p); return sym; } } while (--i); if (hiCnt >= summFreq) return PPMD7_SYM_ERROR; hiCnt -= count; RC_Decode(hiCnt, summFreq - hiCnt) p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); PPMD_SetAllBitsIn256Bytes(charMask) // i = p->MinContext->NumStats - 1; // do { MASK((--s)->Symbol) = 0; } while (--i); { CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); MASK(s->Symbol) = 0; do { const unsigned sym0 = s2[0].Symbol; const unsigned sym1 = s2[1].Symbol; s2 += 2; MASK(sym0) = 0; MASK(sym1) = 0; } while (s2 < s); } } else { CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); UInt16 *prob = Ppmd7_GetBinSumm(p); UInt32 pr = *prob; UInt32 size0 = (R->Range >> 14) * pr; pr = PPMD_UPDATE_PROB_1(pr); if (R->Code < size0) { Byte sym; *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); // RangeDec_DecodeBit0(size0); R->Range = size0; RC_NORM_1(R) /* we can use single byte normalization here because of (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */ // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; // Ppmd7_UpdateBin(p); { unsigned freq = s->Freq; CPpmd7_Context *c = CTX(SUCCESSOR(s)); sym = s->Symbol; p->FoundState = s; p->PrevSuccess = 1; p->RunLength++; s->Freq = (Byte)(freq + (freq < 128)); // NextContext(p); if (p->OrderFall == 0 && (const Byte *)c > p->Text) p->MaxContext = p->MinContext = c; else Ppmd7_UpdateModel(p); } return sym; } *prob = (UInt16)pr; p->InitEsc = p->ExpEscape[pr >> 10]; // RangeDec_DecodeBit1(size0); R->Code -= size0; R->Range -= size0; RC_NORM_LOCAL(R) PPMD_SetAllBitsIn256Bytes(charMask) MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; p->PrevSuccess = 0; } for (;;) { CPpmd_State *s, *s2; UInt32 freqSum, count, hiCnt; CPpmd_See *see; CPpmd7_Context *mc; unsigned numMasked; RC_NORM_REMOTE(R) mc = p->MinContext; numMasked = mc->NumStats; do { p->OrderFall++; if (!mc->Suffix) return PPMD7_SYM_END; mc = Ppmd7_GetContext(p, mc->Suffix); } while (mc->NumStats == numMasked); s = Ppmd7_GetStats(p, mc); { unsigned num = mc->NumStats; unsigned num2 = num / 2; num &= 1; hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num); s += num; p->MinContext = mc; do { const unsigned sym0 = s[0].Symbol; const unsigned sym1 = s[1].Symbol; s += 2; hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0))); hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1))); } while (--num2); } see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); freqSum += hiCnt; count = RC_GetThreshold(freqSum); if (count < hiCnt) { Byte sym; s = Ppmd7_GetStats(p, p->MinContext); hiCnt = count; // count -= s->Freq & (UInt32)(MASK(s->Symbol)); // if ((Int32)count >= 0) { for (;;) { count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; } } s--; RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) // new (see->Summ) value can overflow over 16-bits in some rare cases Ppmd_See_UPDATE(see) p->FoundState = s; sym = s->Symbol; Ppmd7_Update2(p); return sym; } if (count >= freqSum) return PPMD7_SYM_ERROR; RC_Decode(hiCnt, freqSum - hiCnt) // We increase (see->Summ) for sum of Freqs of all non_Masked symbols. // new (see->Summ) value can overflow over 16-bits in some rare cases see->Summ = (UInt16)(see->Summ + freqSum); s = Ppmd7_GetStats(p, p->MinContext); s2 = s + p->MinContext->NumStats; do { MASK(s->Symbol) = 0; s++; } while (s != s2); } } /* Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim) { int sym = 0; if (buf != lim) do { sym = Ppmd7z_DecodeSymbol(p); if (sym < 0) break; *buf = (Byte)sym; } while (++buf < lim); p->LastSymbol = sym; return buf; } */ #undef kTopValue #undef READ_BYTE #undef RC_NORM_BASE #undef RC_NORM_1 #undef RC_NORM #undef RC_NORM_LOCAL #undef RC_NORM_REMOTE #undef R #undef RC_Decode #undef RC_DecodeFinal #undef RC_GetThreshold #undef CTX #undef SUCCESSOR #undef MASK tmp41wklro_/C/Ppmd7Enc.c0000444000175000001440000001764014476326460016130 0ustar nabijaczleweliusers/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder 2023-09-07 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" #include "Ppmd7.h" #define kTopValue ((UInt32)1 << 24) #define R (&p->rc.enc) void Ppmd7z_Init_RangeEnc(CPpmd7 *p) { R->Low = 0; R->Range = 0xFFFFFFFF; R->Cache = 0; R->CacheSize = 1; } Z7_NO_INLINE static void Ppmd7z_RangeEnc_ShiftLow(CPpmd7 *p) { if ((UInt32)R->Low < (UInt32)0xFF000000 || (unsigned)(R->Low >> 32) != 0) { Byte temp = R->Cache; do { IByteOut_Write(R->Stream, (Byte)(temp + (Byte)(R->Low >> 32))); temp = 0xFF; } while (--R->CacheSize != 0); R->Cache = (Byte)((UInt32)R->Low >> 24); } R->CacheSize++; R->Low = (UInt32)((UInt32)R->Low << 8); } #define RC_NORM_BASE(p) if (R->Range < kTopValue) { R->Range <<= 8; Ppmd7z_RangeEnc_ShiftLow(p); #define RC_NORM_1(p) RC_NORM_BASE(p) } #define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} // we must use only one type of Normalization from two: LOCAL or REMOTE #define RC_NORM_LOCAL(p) // RC_NORM(p) #define RC_NORM_REMOTE(p) RC_NORM(p) /* #define Ppmd7z_RangeEnc_Encode(p, start, _size_) \ { UInt32 size = _size_; \ R->Low += start * R->Range; \ R->Range *= size; \ RC_NORM_LOCAL(p); } */ Z7_FORCE_INLINE // Z7_NO_INLINE static void Ppmd7z_RangeEnc_Encode(CPpmd7 *p, UInt32 start, UInt32 size) { R->Low += start * R->Range; R->Range *= size; RC_NORM_LOCAL(p) } void Ppmd7z_Flush_RangeEnc(CPpmd7 *p) { unsigned i; for (i = 0; i < 5; i++) Ppmd7z_RangeEnc_ShiftLow(p); } #define RC_Encode(start, size) Ppmd7z_RangeEnc_Encode(p, start, size); #define RC_EncodeFinal(start, size) RC_Encode(start, size) RC_NORM_REMOTE(p) #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) #define SUFFIX(ctx) CTX((ctx)->Suffix) // typedef CPpmd7_Context * CTX_PTR; #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) void Ppmd7_UpdateModel(CPpmd7 *p); #define MASK(sym) ((Byte *)charMask)[sym] Z7_FORCE_INLINE static void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol) { size_t charMask[256 / sizeof(size_t)]; if (p->MinContext->NumStats != 1) { CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); UInt32 sum; unsigned i; R->Range /= p->MinContext->Union2.SummFreq; if (s->Symbol == symbol) { // R->Range /= p->MinContext->Union2.SummFreq; RC_EncodeFinal(0, s->Freq) p->FoundState = s; Ppmd7_Update1_0(p); return; } p->PrevSuccess = 0; sum = s->Freq; i = (unsigned)p->MinContext->NumStats - 1; do { if ((++s)->Symbol == symbol) { // R->Range /= p->MinContext->Union2.SummFreq; RC_EncodeFinal(sum, s->Freq) p->FoundState = s; Ppmd7_Update1(p); return; } sum += s->Freq; } while (--i); // R->Range /= p->MinContext->Union2.SummFreq; RC_Encode(sum, p->MinContext->Union2.SummFreq - sum) p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); PPMD_SetAllBitsIn256Bytes(charMask) // MASK(s->Symbol) = 0; // i = p->MinContext->NumStats - 1; // do { MASK((--s)->Symbol) = 0; } while (--i); { CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); MASK(s->Symbol) = 0; do { const unsigned sym0 = s2[0].Symbol; const unsigned sym1 = s2[1].Symbol; s2 += 2; MASK(sym0) = 0; MASK(sym1) = 0; } while (s2 < s); } } else { UInt16 *prob = Ppmd7_GetBinSumm(p); CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); UInt32 pr = *prob; const UInt32 bound = (R->Range >> 14) * pr; pr = PPMD_UPDATE_PROB_1(pr); if (s->Symbol == symbol) { *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); // RangeEnc_EncodeBit_0(p, bound); R->Range = bound; RC_NORM_1(p) // p->FoundState = s; // Ppmd7_UpdateBin(p); { const unsigned freq = s->Freq; CPpmd7_Context *c = CTX(SUCCESSOR(s)); p->FoundState = s; p->PrevSuccess = 1; p->RunLength++; s->Freq = (Byte)(freq + (freq < 128)); // NextContext(p); if (p->OrderFall == 0 && (const Byte *)c > p->Text) p->MaxContext = p->MinContext = c; else Ppmd7_UpdateModel(p); } return; } *prob = (UInt16)pr; p->InitEsc = p->ExpEscape[pr >> 10]; // RangeEnc_EncodeBit_1(p, bound); R->Low += bound; R->Range -= bound; RC_NORM_LOCAL(p) PPMD_SetAllBitsIn256Bytes(charMask) MASK(s->Symbol) = 0; p->PrevSuccess = 0; } for (;;) { CPpmd_See *see; CPpmd_State *s; UInt32 sum, escFreq; CPpmd7_Context *mc; unsigned i, numMasked; RC_NORM_REMOTE(p) mc = p->MinContext; numMasked = mc->NumStats; do { p->OrderFall++; if (!mc->Suffix) return; /* EndMarker (symbol = -1) */ mc = Ppmd7_GetContext(p, mc->Suffix); i = mc->NumStats; } while (i == numMasked); p->MinContext = mc; // see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); { if (i != 256) { unsigned nonMasked = i - numMasked; see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + p->HiBitsFlag + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - i) + 2 * (unsigned)(mc->Union2.SummFreq < 11 * i) + 4 * (unsigned)(numMasked > nonMasked); { // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ unsigned summ = (UInt16)see->Summ; // & 0xFFFF unsigned r = (summ >> see->Shift); see->Summ = (UInt16)(summ - r); escFreq = r + (r == 0); } } else { see = &p->DummySee; escFreq = 1; } } s = Ppmd7_GetStats(p, mc); sum = 0; // i = mc->NumStats; do { const unsigned cur = s->Symbol; if ((int)cur == symbol) { const UInt32 low = sum; const UInt32 freq = s->Freq; unsigned num2; Ppmd_See_UPDATE(see) p->FoundState = s; sum += escFreq; num2 = i / 2; i &= 1; sum += freq & (0 - (UInt32)i); if (num2 != 0) { s += i; do { const unsigned sym0 = s[0].Symbol; const unsigned sym1 = s[1].Symbol; s += 2; sum += (s[-2].Freq & (unsigned)(MASK(sym0))); sum += (s[-1].Freq & (unsigned)(MASK(sym1))); } while (--num2); } R->Range /= sum; RC_EncodeFinal(low, freq) Ppmd7_Update2(p); return; } sum += (s->Freq & (unsigned)(MASK(cur))); s++; } while (--i); { const UInt32 total = sum + escFreq; see->Summ = (UInt16)(see->Summ + total); R->Range /= total; RC_Encode(sum, escFreq) } { const CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); s--; MASK(s->Symbol) = 0; do { const unsigned sym0 = s2[0].Symbol; const unsigned sym1 = s2[1].Symbol; s2 += 2; MASK(sym0) = 0; MASK(sym1) = 0; } while (s2 < s); } } } void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim) { for (; buf < lim; buf++) { Ppmd7z_EncodeSymbol(p, *buf); } } #undef kTopValue #undef WRITE_BYTE #undef RC_NORM_BASE #undef RC_NORM_1 #undef RC_NORM #undef RC_NORM_LOCAL #undef RC_NORM_REMOTE #undef R #undef RC_Encode #undef RC_EncodeFinal #undef SUFFIX #undef CTX #undef SUCCESSOR #undef MASK tmp41wklro_/C/Precomp.h0000444000175000001440000000646014554710260016113 0ustar nabijaczleweliusers/* Precomp.h -- precompilation file 2024-01-25 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_PRECOMP_H #define ZIP7_INC_PRECOMP_H /* this file must be included before another *.h files and before . this file is included from the following files: C\*.c C\Util\*\Precomp.h <- C\Util\*\*.c CPP\Common\Common.h <- *\StdAfx.h <- *\*.cpp this file can set the following macros: Z7_LARGE_PAGES 1 Z7_LONG_PATH 1 Z7_WIN32_WINNT_MIN 0x0500 (or higher) : we require at least win2000+ for 7-Zip _WIN32_WINNT 0x0500 (or higher) WINVER _WIN32_WINNT UNICODE 1 _UNICODE 1 */ #include "Compiler.h" #ifdef _MSC_VER // #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty #if _MSC_VER >= 1912 // #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception. #endif #endif /* // for debug: #define UNICODE 1 #define _UNICODE 1 #define _WIN32_WINNT 0x0500 // win2000 #ifndef WINVER #define WINVER _WIN32_WINNT #endif */ #ifdef _WIN32 /* this "Precomp.h" file must be included before , if we want to define _WIN32_WINNT before . */ #ifndef Z7_LARGE_PAGES #ifndef Z7_NO_LARGE_PAGES #define Z7_LARGE_PAGES 1 #endif #endif #ifndef Z7_LONG_PATH #ifndef Z7_NO_LONG_PATH #define Z7_LONG_PATH 1 #endif #endif #ifndef Z7_DEVICE_FILE #ifndef Z7_NO_DEVICE_FILE // #define Z7_DEVICE_FILE 1 #endif #endif // we don't change macros if included after #ifndef _WINDOWS_ #ifndef Z7_WIN32_WINNT_MIN #if defined(_M_ARM64) || defined(__aarch64__) // #define Z7_WIN32_WINNT_MIN 0x0a00 // win10 #define Z7_WIN32_WINNT_MIN 0x0600 // vista #elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT) // #define Z7_WIN32_WINNT_MIN 0x0602 // win8 #define Z7_WIN32_WINNT_MIN 0x0600 // vista #elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64) #define Z7_WIN32_WINNT_MIN 0x0503 // win2003 // #elif defined(_M_IX86) || defined(__i386__) // #define Z7_WIN32_WINNT_MIN 0x0500 // win2000 #else // x86 and another(old) systems #define Z7_WIN32_WINNT_MIN 0x0500 // win2000 // #define Z7_WIN32_WINNT_MIN 0x0502 // win2003 // for debug #endif #endif // Z7_WIN32_WINNT_MIN #ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT #ifdef _WIN32_WINNT // #error Stop_Compiling_Bad_WIN32_WINNT #else #ifndef Z7_NO_DEFINE_WIN32_WINNT Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define _WIN32_WINNT Z7_WIN32_WINNT_MIN Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // _WIN32_WINNT #ifndef WINVER #define WINVER _WIN32_WINNT #endif #endif // Z7_DO_NOT_DEFINE_WIN32_WINNT #ifndef _MBCS #ifndef Z7_NO_UNICODE // UNICODE and _UNICODE are used by and by 7-zip code. #ifndef UNICODE #define UNICODE 1 #endif #ifndef _UNICODE Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define _UNICODE 1 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // Z7_NO_UNICODE #endif // _MBCS #endif // _WINDOWS_ // #include "7zWindows.h" #endif // _WIN32 #endif tmp41wklro_/C/RotateDefs.h0000444000175000001440000000274214443561660016552 0ustar nabijaczleweliusers/* RotateDefs.h -- Rotate functions 2023-06-18 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_ROTATE_DEFS_H #define ZIP7_INC_ROTATE_DEFS_H #ifdef _MSC_VER #include /* don't use _rotl with old MINGW. It can insert slow call to function. */ /* #if (_MSC_VER >= 1200) */ #pragma intrinsic(_rotl) #pragma intrinsic(_rotr) /* #endif */ #define rotlFixed(x, n) _rotl((x), (n)) #define rotrFixed(x, n) _rotr((x), (n)) #if (_MSC_VER >= 1300) #define Z7_ROTL64(x, n) _rotl64((x), (n)) #define Z7_ROTR64(x, n) _rotr64((x), (n)) #else #define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) #define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) #endif #else /* new compilers can translate these macros to fast commands. */ #if defined(__clang__) && (__clang_major__ >= 4) \ || defined(__GNUC__) && (__GNUC__ >= 5) /* GCC 4.9.0 and clang 3.5 can recognize more correct version: */ #define rotlFixed(x, n) (((x) << (n)) | ((x) >> (-(n) & 31))) #define rotrFixed(x, n) (((x) >> (n)) | ((x) << (-(n) & 31))) #define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (-(n) & 63))) #define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (-(n) & 63))) #else /* for old GCC / clang: */ #define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) #define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) #define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) #endif #endif #endif tmp41wklro_/C/Sha256.c0000444000175000001440000002670214570332460015452 0ustar nabijaczleweliusers/* Sha256.c -- SHA-256 Hash 2024-03-01 : Igor Pavlov : Public domain This code is based on public domain code from Wei Dai's Crypto++ library. */ #include "Precomp.h" #include #include "CpuArch.h" #include "RotateDefs.h" #include "Sha256.h" #if defined(_MSC_VER) && (_MSC_VER < 1900) // #define USE_MY_MM #endif #ifdef MY_CPU_X86_OR_AMD64 #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \ || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \ || defined(_MSC_VER) && (_MSC_VER >= 1200) #define Z7_COMPILER_SHA256_SUPPORTED #endif #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__ARM_FEATURE_SHA2) \ || defined(__ARM_FEATURE_CRYPTO) #define Z7_COMPILER_SHA256_SUPPORTED #else #if defined(MY_CPU_ARM64) \ || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \ || defined(Z7_MSC_VER_ORIGINAL) #if defined(__ARM_FP) && \ ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) \ ) \ || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) && \ (Z7_CLANG_VERSION < 170000 || \ Z7_CLANG_VERSION > 170001) #define Z7_COMPILER_SHA256_SUPPORTED #endif #endif #endif #endif #endif void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); #ifdef Z7_COMPILER_SHA256_SUPPORTED void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks; static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW; #define SHA256_UPDATE_BLOCKS(p) p->func_UpdateBlocks #else #define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks #endif BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo) { SHA256_FUNC_UPDATE_BLOCKS func = Sha256_UpdateBlocks; #ifdef Z7_COMPILER_SHA256_SUPPORTED if (algo != SHA256_ALGO_SW) { if (algo == SHA256_ALGO_DEFAULT) func = g_SHA256_FUNC_UPDATE_BLOCKS; else { if (algo != SHA256_ALGO_HW) return False; func = g_SHA256_FUNC_UPDATE_BLOCKS_HW; if (!func) return False; } } #else if (algo > 1) return False; #endif p->func_UpdateBlocks = func; return True; } /* define it for speed optimization */ #ifdef Z7_SFX #define STEP_PRE 1 #define STEP_MAIN 1 #else #define STEP_PRE 2 #define STEP_MAIN 4 // #define Z7_SHA256_UNROLL #endif #undef Z7_SHA256_BIG_W #if STEP_MAIN != 16 #define Z7_SHA256_BIG_W #endif void Sha256_InitState(CSha256 *p) { p->count = 0; p->state[0] = 0x6a09e667; p->state[1] = 0xbb67ae85; p->state[2] = 0x3c6ef372; p->state[3] = 0xa54ff53a; p->state[4] = 0x510e527f; p->state[5] = 0x9b05688c; p->state[6] = 0x1f83d9ab; p->state[7] = 0x5be0cd19; } void Sha256_Init(CSha256 *p) { p->func_UpdateBlocks = #ifdef Z7_COMPILER_SHA256_SUPPORTED g_SHA256_FUNC_UPDATE_BLOCKS; #else NULL; #endif Sha256_InitState(p); } #define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) #define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) #define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) #define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) #define Ch(x,y,z) (z^(x&(y^z))) #define Maj(x,y,z) ((x&y)|(z&(x|y))) #define W_PRE(i) (W[(i) + (size_t)(j)] = GetBe32(data + ((size_t)(j) + i) * 4)) #define blk2_main(j, i) s1(w(j, (i)-2)) + w(j, (i)-7) + s0(w(j, (i)-15)) #ifdef Z7_SHA256_BIG_W // we use +i instead of +(i) to change the order to solve CLANG compiler warning for signed/unsigned. #define w(j, i) W[(size_t)(j) + i] #define blk2(j, i) (w(j, i) = w(j, (i)-16) + blk2_main(j, i)) #else #if STEP_MAIN == 16 #define w(j, i) W[(i) & 15] #else #define w(j, i) W[((size_t)(j) + (i)) & 15] #endif #define blk2(j, i) (w(j, i) += blk2_main(j, i)) #endif #define W_MAIN(i) blk2(j, i) #define T1(wx, i) \ tmp = h + S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ h = g; \ g = f; \ f = e; \ e = d + tmp; \ tmp += S0(a) + Maj(a, b, c); \ d = c; \ c = b; \ b = a; \ a = tmp; \ #define R1_PRE(i) T1( W_PRE, i) #define R1_MAIN(i) T1( W_MAIN, i) #if (!defined(Z7_SHA256_UNROLL) || STEP_MAIN < 8) && (STEP_MAIN >= 4) #define R2_MAIN(i) \ R1_MAIN(i) \ R1_MAIN(i + 1) \ #endif #if defined(Z7_SHA256_UNROLL) && STEP_MAIN >= 8 #define T4( a,b,c,d,e,f,g,h, wx, i) \ h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ tmp = h; \ h += d; \ d = tmp + S0(a) + Maj(a, b, c); \ #define R4( wx, i) \ T4 ( a,b,c,d,e,f,g,h, wx, (i )); \ T4 ( d,a,b,c,h,e,f,g, wx, (i+1)); \ T4 ( c,d,a,b,g,h,e,f, wx, (i+2)); \ T4 ( b,c,d,a,f,g,h,e, wx, (i+3)); \ #define R4_PRE(i) R4( W_PRE, i) #define R4_MAIN(i) R4( W_MAIN, i) #define T8( a,b,c,d,e,f,g,h, wx, i) \ h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ d += h; \ h += S0(a) + Maj(a, b, c); \ #define R8( wx, i) \ T8 ( a,b,c,d,e,f,g,h, wx, i ); \ T8 ( h,a,b,c,d,e,f,g, wx, i+1); \ T8 ( g,h,a,b,c,d,e,f, wx, i+2); \ T8 ( f,g,h,a,b,c,d,e, wx, i+3); \ T8 ( e,f,g,h,a,b,c,d, wx, i+4); \ T8 ( d,e,f,g,h,a,b,c, wx, i+5); \ T8 ( c,d,e,f,g,h,a,b, wx, i+6); \ T8 ( b,c,d,e,f,g,h,a, wx, i+7); \ #define R8_PRE(i) R8( W_PRE, i) #define R8_MAIN(i) R8( W_MAIN, i) #endif // static extern MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64]; MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; #define K SHA256_K_ARRAY Z7_NO_INLINE void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks) { UInt32 W #ifdef Z7_SHA256_BIG_W [64]; #else [16]; #endif unsigned j; UInt32 a,b,c,d,e,f,g,h; #if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) UInt32 tmp; #endif a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; f = state[5]; g = state[6]; h = state[7]; while (numBlocks) { for (j = 0; j < 16; j += STEP_PRE) { #if STEP_PRE > 4 #if STEP_PRE < 8 R4_PRE(0); #else R8_PRE(0); #if STEP_PRE == 16 R8_PRE(8); #endif #endif #else R1_PRE(0) #if STEP_PRE >= 2 R1_PRE(1) #if STEP_PRE >= 4 R1_PRE(2) R1_PRE(3) #endif #endif #endif } for (j = 16; j < 64; j += STEP_MAIN) { #if defined(Z7_SHA256_UNROLL) && STEP_MAIN >= 8 #if STEP_MAIN < 8 R4_MAIN(0) #else R8_MAIN(0) #if STEP_MAIN == 16 R8_MAIN(8) #endif #endif #else R1_MAIN(0) #if STEP_MAIN >= 2 R1_MAIN(1) #if STEP_MAIN >= 4 R2_MAIN(2) #if STEP_MAIN >= 8 R2_MAIN(4) R2_MAIN(6) #if STEP_MAIN >= 16 R2_MAIN(8) R2_MAIN(10) R2_MAIN(12) R2_MAIN(14) #endif #endif #endif #endif #endif } a += state[0]; state[0] = a; b += state[1]; state[1] = b; c += state[2]; state[2] = c; d += state[3]; state[3] = d; e += state[4]; state[4] = e; f += state[5]; state[5] = f; g += state[6]; state[6] = g; h += state[7]; state[7] = h; data += 64; numBlocks--; } /* Wipe variables */ /* memset(W, 0, sizeof(W)); */ } #undef S0 #undef S1 #undef s0 #undef s1 #undef K #define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) void Sha256_Update(CSha256 *p, const Byte *data, size_t size) { if (size == 0) return; { unsigned pos = (unsigned)p->count & 0x3F; unsigned num; p->count += size; num = 64 - pos; if (num > size) { memcpy(p->buffer + pos, data, size); return; } if (pos != 0) { size -= num; memcpy(p->buffer + pos, data, num); data += num; Sha256_UpdateBlock(p); } } { size_t numBlocks = size >> 6; SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks); size &= 0x3F; if (size == 0) return; data += (numBlocks << 6); memcpy(p->buffer, data, size); } } void Sha256_Final(CSha256 *p, Byte *digest) { unsigned pos = (unsigned)p->count & 0x3F; unsigned i; p->buffer[pos++] = 0x80; if (pos > (64 - 8)) { while (pos != 64) { p->buffer[pos++] = 0; } // memset(&p->buf.buffer[pos], 0, 64 - pos); Sha256_UpdateBlock(p); pos = 0; } /* if (pos & 3) { p->buffer[pos] = 0; p->buffer[pos + 1] = 0; p->buffer[pos + 2] = 0; pos += 3; pos &= ~3; } { for (; pos < 64 - 8; pos += 4) *(UInt32 *)(&p->buffer[pos]) = 0; } */ memset(&p->buffer[pos], 0, (64 - 8) - pos); { UInt64 numBits = (p->count << 3); SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)) SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)) } Sha256_UpdateBlock(p); for (i = 0; i < 8; i += 2) { UInt32 v0 = p->state[i]; UInt32 v1 = p->state[(size_t)i + 1]; SetBe32(digest , v0) SetBe32(digest + 4, v1) digest += 8; } Sha256_InitState(p); } void Sha256Prepare(void) { #ifdef Z7_COMPILER_SHA256_SUPPORTED SHA256_FUNC_UPDATE_BLOCKS f, f_hw; f = Sha256_UpdateBlocks; f_hw = NULL; #ifdef MY_CPU_X86_OR_AMD64 #ifndef USE_MY_MM if (CPU_IsSupported_SHA() && CPU_IsSupported_SSSE3() // && CPU_IsSupported_SSE41() ) #endif #else if (CPU_IsSupported_SHA2()) #endif { // printf("\n========== HW SHA256 ======== \n"); f = f_hw = Sha256_UpdateBlocks_HW; } g_SHA256_FUNC_UPDATE_BLOCKS = f; g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw; #endif } #undef S0 #undef S1 #undef s0 #undef s1 #undef Ch #undef Maj #undef W_MAIN #undef W_PRE #undef w #undef blk2_main #undef blk2 #undef T1 #undef T4 #undef T8 #undef R1_PRE #undef R1_MAIN #undef R2_MAIN #undef R4 #undef R4_PRE #undef R4_MAIN #undef R8 #undef R8_PRE #undef R8_MAIN #undef STEP_PRE #undef STEP_MAIN #undef Z7_SHA256_BIG_W #undef Z7_SHA256_UNROLL #undef Z7_COMPILER_SHA256_SUPPORTED tmp41wklro_/C/Sha256.h0000444000175000001440000000343314412267100015444 0ustar nabijaczleweliusers/* Sha256.h -- SHA-256 Hash 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_SHA256_H #define ZIP7_INC_SHA256_H #include "7zTypes.h" EXTERN_C_BEGIN #define SHA256_NUM_BLOCK_WORDS 16 #define SHA256_NUM_DIGEST_WORDS 8 #define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4) #define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4) typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks); /* if (the system supports different SHA256 code implementations) { (CSha256::func_UpdateBlocks) will be used (CSha256::func_UpdateBlocks) can be set by Sha256_Init() - to default (fastest) Sha256_SetFunction() - to any algo } else { (CSha256::func_UpdateBlocks) is ignored. } */ typedef struct { SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks; UInt64 count; UInt64 _pad_2[2]; UInt32 state[SHA256_NUM_DIGEST_WORDS]; Byte buffer[SHA256_BLOCK_SIZE]; } CSha256; #define SHA256_ALGO_DEFAULT 0 #define SHA256_ALGO_SW 1 #define SHA256_ALGO_HW 2 /* Sha256_SetFunction() return: 0 - (algo) value is not supported, and func_UpdateBlocks was not changed 1 - func_UpdateBlocks was set according (algo) value. */ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo); void Sha256_InitState(CSha256 *p); void Sha256_Init(CSha256 *p); void Sha256_Update(CSha256 *p, const Byte *data, size_t size); void Sha256_Final(CSha256 *p, Byte *digest); // void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); /* call Sha256Prepare() once at program start. It prepares all supported implementations, and detects the fastest implementation. */ void Sha256Prepare(void); EXTERN_C_END #endif tmp41wklro_/C/Sha256Opt.c0000444000175000001440000002742114570332460016134 0ustar nabijaczleweliusers/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Compiler.h" #include "CpuArch.h" #if defined(_MSC_VER) #if (_MSC_VER < 1900) && (_MSC_VER >= 1200) // #define USE_MY_MM #endif #endif // #define Z7_USE_HW_SHA_STUB // for debug #ifdef MY_CPU_X86_OR_AMD64 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check #define USE_HW_SHA #elif defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) #define USE_HW_SHA #if !defined(_INTEL_COMPILER) // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) #if !defined(__SHA__) || !defined(__SSSE3__) #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) #endif #endif #elif defined(_MSC_VER) #ifdef USE_MY_MM #define USE_VER_MIN 1300 #else #define USE_VER_MIN 1900 #endif #if (_MSC_VER >= USE_VER_MIN) #define USE_HW_SHA #else #define Z7_USE_HW_SHA_STUB #endif #endif // #endif // MY_CPU_X86_OR_AMD64 #ifndef USE_HW_SHA // #define Z7_USE_HW_SHA_STUB // for debug #endif #ifdef USE_HW_SHA // #pragma message("Sha256 HW") // sse/sse2/ssse3: #include // sha*: #include #if defined (__clang__) && defined(_MSC_VER) // #if !defined(__SSSE3__) // #endif #if !defined(__SHA__) #include #endif #else #ifdef USE_MY_MM #include "My_mm.h" #endif #endif /* SHA256 uses: SSE2: _mm_loadu_si128 _mm_storeu_si128 _mm_set_epi32 _mm_add_epi32 _mm_shuffle_epi32 / pshufd SSSE3: _mm_shuffle_epi8 / pshufb _mm_alignr_epi8 SHA: _mm_sha256* */ // K array must be aligned for 16-bytes at least. // The compiler can look align attribute and selects // movdqu - for code without align attribute // movdqa - for code with align attribute extern MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64]; #define K SHA256_K_ARRAY #define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src); #define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src); #define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src); #define LOAD_SHUFFLE(m, k) \ m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ m = _mm_shuffle_epi8(m, mask); \ #define SM1(g0, g1, g2, g3) \ SHA256_MSG1(g3, g0); \ #define SM2(g0, g1, g2, g3) \ tmp = _mm_alignr_epi8(g1, g0, 4); \ ADD_EPI32(g2, tmp) \ SHA25G_MSG2(g2, g1); \ // #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k) // #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1) #define NNN(g0, g1, g2, g3) #define RND2(t0, t1) \ t0 = _mm_sha256rnds2_epu32(t0, t1, msg); #define RND2_0(m, k) \ msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \ RND2(state0, state1); \ msg = _mm_shuffle_epi32(msg, 0x0E); \ #define RND2_1 \ RND2(state1, state0); \ // We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2 #define R4(k, g0, g1, g2, g3, OP0, OP1) \ RND2_0(g0, k) \ OP0(g0, g1, g2, g3) \ RND2_1 \ OP1(g0, g1, g2, g3) \ #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \ R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \ R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \ R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \ #define PREPARE_STATE \ tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \ state0 = _mm_shuffle_epi32(state1, 0x1B); /* efgh */ \ state1 = state0; \ state0 = _mm_unpacklo_epi64(state0, tmp); /* cdgh */ \ state1 = _mm_unpackhi_epi64(state1, tmp); /* abef */ \ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); #ifdef ATTRIB_SHA ATTRIB_SHA #endif void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) { const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203); __m128i tmp; __m128i state0, state1; if (numBlocks == 0) return; state0 = _mm_loadu_si128((const __m128i *) (const void *) &state[0]); state1 = _mm_loadu_si128((const __m128i *) (const void *) &state[4]); PREPARE_STATE do { __m128i state0_save, state1_save; __m128i m0, m1, m2, m3; __m128i msg; // #define msg tmp state0_save = state0; state1_save = state1; LOAD_SHUFFLE (m0, 0) LOAD_SHUFFLE (m1, 1) LOAD_SHUFFLE (m2, 2) LOAD_SHUFFLE (m3, 3) R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ) R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ) ADD_EPI32(state0, state0_save) ADD_EPI32(state1, state1_save) data += 64; } while (--numBlocks); PREPARE_STATE _mm_storeu_si128((__m128i *) (void *) &state[0], state0); _mm_storeu_si128((__m128i *) (void *) &state[4], state1); } #endif // USE_HW_SHA #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__ARM_FEATURE_SHA2) \ || defined(__ARM_FEATURE_CRYPTO) #define USE_HW_SHA #else #if defined(MY_CPU_ARM64) \ || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \ || defined(Z7_MSC_VER_ORIGINAL) #if defined(__ARM_FP) && \ ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) \ ) \ || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) && \ (Z7_CLANG_VERSION < 170000 || \ Z7_CLANG_VERSION > 170001) #define USE_HW_SHA #endif #endif #endif #endif #ifdef USE_HW_SHA // #pragma message("=== Sha256 HW === ") #if defined(__clang__) || defined(__GNUC__) #if !defined(__ARM_FEATURE_SHA2) && \ !defined(__ARM_FEATURE_CRYPTO) #ifdef MY_CPU_ARM64 #if defined(__clang__) #define ATTRIB_SHA __attribute__((__target__("crypto"))) #else #define ATTRIB_SHA __attribute__((__target__("+crypto"))) #endif #else #if defined(__clang__) && (__clang_major__ >= 1) #define ATTRIB_SHA __attribute__((__target__("armv8-a,sha2"))) #else #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #endif #endif #endif #else // _MSC_VER // for arm32 #define _ARM_USE_NEW_NEON_INTRINSICS #endif #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) #include #else #if defined(__clang__) && __clang_major__ < 16 #if !defined(__ARM_FEATURE_SHA2) && \ !defined(__ARM_FEATURE_CRYPTO) // #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ") Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1 // #if defined(__clang__) && __clang_major__ < 13 #define __ARM_FEATURE_CRYPTO 1 // #else #define __ARM_FEATURE_SHA2 1 // #endif Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // clang #if defined(__clang__) #if defined(__ARM_ARCH) && __ARM_ARCH < 8 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER // #pragma message("#define __ARM_ARCH 8") #undef __ARM_ARCH #define __ARM_ARCH 8 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif // clang #include #if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \ defined(__ARM_FEATURE_CRYPTO) && \ defined(__ARM_FEATURE_SHA2) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #undef __ARM_FEATURE_CRYPTO #undef __ARM_FEATURE_SHA2 #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER // #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ") #endif #endif // Z7_MSC_VER_ORIGINAL typedef uint32x4_t v128; // typedef __n128 v128; // MSVC #ifdef MY_CPU_BE #define MY_rev32_for_LE(x) #else #define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x))) #endif #define LOAD_128(_p) (*(const v128 *)(const void *)(_p)) #define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v) #define LOAD_SHUFFLE(m, k) \ m = LOAD_128((data + (k) * 16)); \ MY_rev32_for_LE(m); \ // K array must be aligned for 16-bytes at least. extern MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64]; #define K SHA256_K_ARRAY #define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src); #define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3); #define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0) #define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1) #define NNN(g0, g1, g2, g3) #define R4(k, g0, g1, g2, g3, OP0, OP1) \ msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \ tmp = state0; \ state0 = vsha256hq_u32( state0, state1, msg ); \ state1 = vsha256h2q_u32( state1, tmp, msg ); \ OP0(g0, g1, g2, g3); \ OP1(g0, g1, g2, g3); \ #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ R4 ( (k)*4+0, m0, m1, m2, m3, OP0, OP1 ) \ R4 ( (k)*4+1, m1, m2, m3, m0, OP2, OP3 ) \ R4 ( (k)*4+2, m2, m3, m0, m1, OP4, OP5 ) \ R4 ( (k)*4+3, m3, m0, m1, m2, OP6, OP7 ) \ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); #ifdef ATTRIB_SHA ATTRIB_SHA #endif void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) { v128 state0, state1; if (numBlocks == 0) return; state0 = LOAD_128(&state[0]); state1 = LOAD_128(&state[4]); do { v128 state0_save, state1_save; v128 m0, m1, m2, m3; v128 msg, tmp; state0_save = state0; state1_save = state1; LOAD_SHUFFLE (m0, 0) LOAD_SHUFFLE (m1, 1) LOAD_SHUFFLE (m2, 2) LOAD_SHUFFLE (m3, 3) R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ) R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ) state0 = vaddq_u32(state0, state0_save); state1 = vaddq_u32(state1, state1_save); data += 64; } while (--numBlocks); STORE_128(&state[0], state0); STORE_128(&state[4], state1); } #endif // USE_HW_SHA #endif // MY_CPU_ARM_OR_ARM64 #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB) // #error Stop_Compiling_UNSUPPORTED_SHA // #include // We can compile this file with another C compiler, // or we can compile asm version. // So we can generate real code instead of this stub function. // #include "Sha256.h" // #if defined(_MSC_VER) #pragma message("Sha256 HW-SW stub was used") // #endif void Z7_FASTCALL Sha256_UpdateBlocks (UInt32 state[8], const Byte *data, size_t numBlocks); void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) { Sha256_UpdateBlocks(state, data, numBlocks); /* UNUSED_VAR(state); UNUSED_VAR(data); UNUSED_VAR(numBlocks); exit(1); return; */ } #endif #undef K #undef RND2 #undef RND2_0 #undef RND2_1 #undef MY_rev32_for_LE #undef NNN #undef LOAD_128 #undef STORE_128 #undef LOAD_SHUFFLE #undef SM1 #undef SM2 #undef NNN #undef R4 #undef R16 #undef PREPARE_STATE #undef USE_HW_SHA #undef ATTRIB_SHA #undef USE_VER_MIN #undef Z7_USE_HW_SHA_STUB tmp41wklro_/C/Sort.c0000444000175000001440000000503512317770100015417 0ustar nabijaczleweliusers/* Sort.c -- Sort functions 2014-04-05 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Sort.h" #define HeapSortDown(p, k, size, temp) \ { for (;;) { \ size_t s = (k << 1); \ if (s > size) break; \ if (s < size && p[s + 1] > p[s]) s++; \ if (temp >= p[s]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSort(UInt32 *p, size_t size) { if (size <= 1) return; p--; { size_t i = size / 2; do { UInt32 temp = p[i]; size_t k = i; HeapSortDown(p, k, size, temp) } while (--i != 0); } /* do { size_t k = 1; UInt32 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) } while (size > 1); */ while (size > 3) { UInt32 temp = p[size]; size_t k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) } { UInt32 temp = p[size]; p[size] = p[1]; if (size > 2 && p[2] < temp) { p[1] = p[2]; p[2] = temp; } else p[1] = temp; } } void HeapSort64(UInt64 *p, size_t size) { if (size <= 1) return; p--; { size_t i = size / 2; do { UInt64 temp = p[i]; size_t k = i; HeapSortDown(p, k, size, temp) } while (--i != 0); } /* do { size_t k = 1; UInt64 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) } while (size > 1); */ while (size > 3) { UInt64 temp = p[size]; size_t k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) } { UInt64 temp = p[size]; p[size] = p[1]; if (size > 2 && p[2] < temp) { p[1] = p[2]; p[2] = temp; } else p[1] = temp; } } /* #define HeapSortRefDown(p, vals, n, size, temp) \ { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ size_t s = (k << 1); \ if (s > size) break; \ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ if (val >= vals[p[s]]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) { if (size <= 1) return; p--; { size_t i = size / 2; do { UInt32 temp = p[i]; HeapSortRefDown(p, vals, i, size, temp); } while (--i != 0); } do { UInt32 temp = p[size]; p[size--] = p[1]; HeapSortRefDown(p, vals, 1, size, temp); } while (size > 1); } */ tmp41wklro_/C/Sort.h0000444000175000001440000000052714401154240015422 0ustar nabijaczleweliusers/* Sort.h -- Sort functions 2023-03-05 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_SORT_H #define ZIP7_INC_SORT_H #include "7zTypes.h" EXTERN_C_BEGIN void HeapSort(UInt32 *p, size_t size); void HeapSort64(UInt64 *p, size_t size); /* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ EXTERN_C_END #endif tmp41wklro_/C/SwapBytes.c0000444000175000001440000005463714570332460016433 0ustar nabijaczleweliusers/* SwapBytes.c -- Byte Swap conversion filter 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "Compiler.h" #include "CpuArch.h" #include "RotateDefs.h" #include "SwapBytes.h" typedef UInt16 CSwapUInt16; typedef UInt32 CSwapUInt32; // #define k_SwapBytes_Mode_BASE 0 #ifdef MY_CPU_X86_OR_AMD64 #define k_SwapBytes_Mode_SSE2 1 #define k_SwapBytes_Mode_SSSE3 2 #define k_SwapBytes_Mode_AVX2 3 // #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) #if defined(__clang__) && (__clang_major__ >= 4) \ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_AVX2 #define SWAP_ATTRIB_SSE2 __attribute__((__target__("sse2"))) #define SWAP_ATTRIB_SSSE3 __attribute__((__target__("ssse3"))) #define SWAP_ATTRIB_AVX2 __attribute__((__target__("avx2"))) #elif defined(_MSC_VER) #if (_MSC_VER == 1900) #pragma warning(disable : 4752) // found Intel(R) Advanced Vector Extensions; consider using /arch:AVX #endif #if (_MSC_VER >= 1900) #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_AVX2 #elif (_MSC_VER >= 1500) // (VS2008) #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_SSSE3 #elif (_MSC_VER >= 1310) // (VS2003) #define k_SwapBytes_Mode_MAX k_SwapBytes_Mode_SSE2 #endif #endif // _MSC_VER /* // for debug #ifdef k_SwapBytes_Mode_MAX #undef k_SwapBytes_Mode_MAX #endif */ #ifndef k_SwapBytes_Mode_MAX #define k_SwapBytes_Mode_MAX 0 #endif #if (k_SwapBytes_Mode_MAX != 0) && defined(MY_CPU_AMD64) #define k_SwapBytes_Mode_MIN k_SwapBytes_Mode_SSE2 #else #define k_SwapBytes_Mode_MIN 0 #endif #if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_AVX2) #define USE_SWAP_AVX2 #endif #if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSSE3) #define USE_SWAP_SSSE3 #endif #if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSE2) #define USE_SWAP_128 #endif #if k_SwapBytes_Mode_MAX <= k_SwapBytes_Mode_MIN || !defined(USE_SWAP_128) #define FORCE_SWAP_MODE #endif #ifdef USE_SWAP_128 /* MMX SSE SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 SSE4A AES AVX, AVX2, FMA */ #include // sse2 // typedef __m128i v128; #define SWAP2_128(i) { \ const __m128i v = *(const __m128i *)(const void *)(items + (i) * 8); \ *( __m128i *)( void *)(items + (i) * 8) = \ _mm_or_si128( \ _mm_slli_epi16(v, 8), \ _mm_srli_epi16(v, 8)); } // _mm_or_si128() has more ports to execute than _mm_add_epi16(). static #ifdef SWAP_ATTRIB_SSE2 SWAP_ATTRIB_SSE2 #endif void Z7_FASTCALL SwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP2_128(0) SWAP2_128(1) items += 2 * 8; SWAP2_128(0) SWAP2_128(1) items += 2 * 8; } while (items != lim); } /* // sse2 #define SWAP4_128_pack(i) { \ __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \ __m128i v0 = _mm_unpacklo_epi8(v, mask); \ __m128i v1 = _mm_unpackhi_epi8(v, mask); \ v0 = _mm_shufflelo_epi16(v0, 0x1b); \ v1 = _mm_shufflelo_epi16(v1, 0x1b); \ v0 = _mm_shufflehi_epi16(v0, 0x1b); \ v1 = _mm_shufflehi_epi16(v1, 0x1b); \ *(__m128i *)(void *)(items + (i) * 4) = _mm_packus_epi16(v0, v1); } static #ifdef SWAP_ATTRIB_SSE2 SWAP_ATTRIB_SSE2 #endif void Z7_FASTCALL SwapBytes4_128_pack(CSwapUInt32 *items, const CSwapUInt32 *lim) { const __m128i mask = _mm_setzero_si128(); // const __m128i mask = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, 0); Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP4_128_pack(0); items += 1 * 4; // SWAP4_128_pack(0); SWAP4_128_pack(1); items += 2 * 4; } while (items != lim); } // sse2 #define SWAP4_128_shift(i) { \ __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \ __m128i v2; \ v2 = _mm_or_si128( \ _mm_slli_si128(_mm_and_si128(v, mask), 1), \ _mm_and_si128(_mm_srli_si128(v, 1), mask)); \ v = _mm_or_si128( \ _mm_slli_epi32(v, 24), \ _mm_srli_epi32(v, 24)); \ *(__m128i *)(void *)(items + (i) * 4) = _mm_or_si128(v2, v); } static #ifdef SWAP_ATTRIB_SSE2 SWAP_ATTRIB_SSE2 #endif void Z7_FASTCALL SwapBytes4_128_shift(CSwapUInt32 *items, const CSwapUInt32 *lim) { #define M1 0xff00 const __m128i mask = _mm_set_epi32(M1, M1, M1, M1); Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { // SWAP4_128_shift(0) SWAP4_128_shift(1) items += 2 * 4; // SWAP4_128_shift(0) SWAP4_128_shift(1) items += 2 * 4; SWAP4_128_shift(0); items += 1 * 4; } while (items != lim); } */ #if defined(USE_SWAP_SSSE3) || defined(USE_SWAP_AVX2) #define SWAP_SHUF_REV_SEQ_2_VALS(v) (v)+1, (v) #define SWAP_SHUF_REV_SEQ_4_VALS(v) (v)+3, (v)+2, (v)+1, (v) #define SWAP2_SHUF_MASK_16_BYTES \ SWAP_SHUF_REV_SEQ_2_VALS (0 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (1 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (2 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (3 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (4 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (5 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (6 * 2), \ SWAP_SHUF_REV_SEQ_2_VALS (7 * 2) #define SWAP4_SHUF_MASK_16_BYTES \ SWAP_SHUF_REV_SEQ_4_VALS (0 * 4), \ SWAP_SHUF_REV_SEQ_4_VALS (1 * 4), \ SWAP_SHUF_REV_SEQ_4_VALS (2 * 4), \ SWAP_SHUF_REV_SEQ_4_VALS (3 * 4) #if defined(USE_SWAP_AVX2) /* if we use 256_BIT_INIT_MASK, each static array mask will be larger for 16 bytes */ // #define SWAP_USE_256_BIT_INIT_MASK #endif #if defined(SWAP_USE_256_BIT_INIT_MASK) && defined(USE_SWAP_AVX2) #define SWAP_MASK_INIT_SIZE 32 #else #define SWAP_MASK_INIT_SIZE 16 #endif MY_ALIGN(SWAP_MASK_INIT_SIZE) static const Byte k_ShufMask_Swap2[] = { SWAP2_SHUF_MASK_16_BYTES #if SWAP_MASK_INIT_SIZE > 16 , SWAP2_SHUF_MASK_16_BYTES #endif }; MY_ALIGN(SWAP_MASK_INIT_SIZE) static const Byte k_ShufMask_Swap4[] = { SWAP4_SHUF_MASK_16_BYTES #if SWAP_MASK_INIT_SIZE > 16 , SWAP4_SHUF_MASK_16_BYTES #endif }; #ifdef USE_SWAP_SSSE3 #include // ssse3 #define SHUF_128(i) *(items + (i)) = \ _mm_shuffle_epi8(*(items + (i)), mask); // SSSE3 // Z7_NO_INLINE static #ifdef SWAP_ATTRIB_SSSE3 SWAP_ATTRIB_SSSE3 #endif Z7_ATTRIB_NO_VECTORIZE void Z7_FASTCALL ShufBytes_128(void *items8, const void *lim8, const void *mask128_ptr) { __m128i *items = (__m128i *)items8; const __m128i *lim = (const __m128i *)lim8; // const __m128i mask = _mm_set_epi8(SHUF_SWAP2_MASK_16_VALS); // const __m128i mask = _mm_set_epi8(SHUF_SWAP4_MASK_16_VALS); // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); // const __m128i mask = *(const __m128i *)(const void *)&(k_ShufMask_Swap4[0]); const __m128i mask = *(const __m128i *)mask128_ptr; Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SHUF_128(0) SHUF_128(1) items += 2; SHUF_128(0) SHUF_128(1) items += 2; } while (items != lim); } #endif // USE_SWAP_SSSE3 #ifdef USE_SWAP_AVX2 #include // avx, avx2 #if defined(__clang__) #include #include #endif #define SHUF_256(i) *(items + (i)) = \ _mm256_shuffle_epi8(*(items + (i)), mask); // AVX2 // Z7_NO_INLINE static #ifdef SWAP_ATTRIB_AVX2 SWAP_ATTRIB_AVX2 #endif Z7_ATTRIB_NO_VECTORIZE void Z7_FASTCALL ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr) { __m256i *items = (__m256i *)items8; const __m256i *lim = (const __m256i *)lim8; /* UNUSED_VAR(mask128_ptr) __m256i mask = for Swap4: _mm256_setr_epi8(SWAP4_SHUF_MASK_16_BYTES, SWAP4_SHUF_MASK_16_BYTES); for Swap2: _mm256_setr_epi8(SWAP2_SHUF_MASK_16_BYTES, SWAP2_SHUF_MASK_16_BYTES); */ const __m256i mask = #if SWAP_MASK_INIT_SIZE > 16 *(const __m256i *)(const void *)mask128_ptr; #else /* msvc: broadcastsi128() version reserves the stack for no reason msvc 19.29-: _mm256_insertf128_si256() / _mm256_set_m128i)) versions use non-avx movdqu xmm0,XMMWORD PTR [r8] msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want */ // _mm256_broadcastsi128_si256(*mask128_ptr); #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000) #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1) #else #define MY_mm256_set_m128i _mm256_set_m128i #endif MY_mm256_set_m128i( *(const __m128i *)mask128_ptr, *(const __m128i *)mask128_ptr); #endif Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SHUF_256(0) SHUF_256(1) items += 2; SHUF_256(0) SHUF_256(1) items += 2; } while (items != lim); } #endif // USE_SWAP_AVX2 #endif // USE_SWAP_SSSE3 || USE_SWAP_AVX2 #endif // USE_SWAP_128 // compile message "NEON intrinsics not available with the soft-float ABI" #elif defined(MY_CPU_ARM_OR_ARM64) \ && defined(MY_CPU_LE) \ && !defined(Z7_DISABLE_ARM_NEON) #if defined(__clang__) && (__clang_major__ >= 8) \ || defined(__GNUC__) && (__GNUC__ >= 6) #if defined(__ARM_FP) #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 4)) \ || defined(MY_CPU_ARM64) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) #define USE_SWAP_128 #ifdef MY_CPU_ARM64 // #define SWAP_ATTRIB_NEON __attribute__((__target__(""))) #else #if defined(Z7_CLANG_VERSION) // #define SWAP_ATTRIB_NEON __attribute__((__target__("neon"))) #else // #pragma message("SWAP_ATTRIB_NEON __attribute__((__target__(fpu=neon))") #define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=neon"))) #endif #endif // MY_CPU_ARM64 #endif // __ARM_NEON #endif // __ARM_ARCH #endif // __ARM_FP #elif defined(_MSC_VER) #if (_MSC_VER >= 1910) #define USE_SWAP_128 #endif #endif #ifdef USE_SWAP_128 #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) #include #else /* #if !defined(__ARM_NEON) #if defined(Z7_GCC_VERSION) && (__GNUC__ < 5) \ || defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 90201) \ || defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 100100) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #pragma message("#define __ARM_NEON 1") // #define __ARM_NEON 1 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif */ #include #endif #endif #ifndef USE_SWAP_128 #define FORCE_SWAP_MODE #else #ifdef MY_CPU_ARM64 // for debug : comment it #define FORCE_SWAP_MODE #else #define k_SwapBytes_Mode_NEON 1 #endif // typedef uint8x16_t v128; #define SWAP2_128(i) *(uint8x16_t *) (void *)(items + (i) * 8) = \ vrev16q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 8)); #define SWAP4_128(i) *(uint8x16_t *) (void *)(items + (i) * 4) = \ vrev32q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 4)); // Z7_NO_INLINE static #ifdef SWAP_ATTRIB_NEON SWAP_ATTRIB_NEON #endif Z7_ATTRIB_NO_VECTORIZE void Z7_FASTCALL SwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP2_128(0) SWAP2_128(1) items += 2 * 8; SWAP2_128(0) SWAP2_128(1) items += 2 * 8; } while (items != lim); } // Z7_NO_INLINE static #ifdef SWAP_ATTRIB_NEON SWAP_ATTRIB_NEON #endif Z7_ATTRIB_NO_VECTORIZE void Z7_FASTCALL SwapBytes4_128(CSwapUInt32 *items, const CSwapUInt32 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP4_128(0) SWAP4_128(1) items += 2 * 4; SWAP4_128(0) SWAP4_128(1) items += 2 * 4; } while (items != lim); } #endif // USE_SWAP_128 #else // MY_CPU_ARM_OR_ARM64 #define FORCE_SWAP_MODE #endif // MY_CPU_ARM_OR_ARM64 #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_X86) /* _byteswap_ushort() in MSVC x86 32-bit works via slow { mov dh, al; mov dl, ah } So we use own versions of byteswap function */ #if (_MSC_VER < 1400 ) // old MSVC-X86 without _rotr16() support #define SWAP2_16(i) { UInt32 v = items[i]; v += (v << 16); v >>= 8; items[i] = (CSwapUInt16)v; } #else // is new MSVC-X86 with fast _rotr16() #include #define SWAP2_16(i) { items[i] = _rotr16(items[i], 8); } #endif #else // is not MSVC-X86 #define SWAP2_16(i) { CSwapUInt16 v = items[i]; items[i] = Z7_BSWAP16(v); } #endif // MSVC-X86 #if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) #define SWAP4_32(i) { CSwapUInt32 v = items[i]; items[i] = Z7_BSWAP32(v); } #else #define SWAP4_32(i) \ { UInt32 v = items[i]; \ v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff); \ v = rotlFixed(v, 16); \ items[i] = v; } #endif #if defined(FORCE_SWAP_MODE) && defined(USE_SWAP_128) #define DEFAULT_Swap2 SwapBytes2_128 #if !defined(MY_CPU_X86_OR_AMD64) #define DEFAULT_Swap4 SwapBytes4_128 #endif #endif #if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4) #define SWAP_BASE_FUNCS_PREFIXES \ Z7_FORCE_INLINE \ static \ Z7_ATTRIB_NO_VECTOR \ void Z7_FASTCALL #if defined(MY_CPU_ARM_OR_ARM64) #if defined(__clang__) #pragma GCC diagnostic ignored "-Wlanguage-extension-token" #endif #endif #ifdef MY_CPU_64BIT #if defined(MY_CPU_ARM64) \ && defined(__ARM_ARCH) && (__ARM_ARCH >= 8) \ && ( (defined(__GNUC__) && (__GNUC__ >= 4)) \ || (defined(__clang__) && (__clang_major__ >= 4))) #define SWAP2_64_VAR(v) asm ("rev16 %x0,%x0" : "+r" (v)); #define SWAP4_64_VAR(v) asm ("rev32 %x0,%x0" : "+r" (v)); #else // is not ARM64-GNU #if !defined(MY_CPU_X86_OR_AMD64) || (k_SwapBytes_Mode_MIN == 0) || !defined(USE_SWAP_128) #define SWAP2_64_VAR(v) \ v = ( 0x00ff00ff00ff00ff & (v >> 8)) \ + ((0x00ff00ff00ff00ff & v) << 8); /* plus gives faster code in MSVC */ #endif #ifdef Z7_CPU_FAST_BSWAP_SUPPORTED #define SWAP4_64_VAR(v) \ v = Z7_BSWAP64(v); \ v = Z7_ROTL64(v, 32); #else #define SWAP4_64_VAR(v) \ v = ( 0x000000ff000000ff & (v >> 24)) \ + ((0x000000ff000000ff & v) << 24 ) \ + ( 0x0000ff000000ff00 & (v >> 8)) \ + ((0x0000ff000000ff00 & v) << 8 ) \ ; #endif #endif // ARM64-GNU #ifdef SWAP2_64_VAR #define SWAP2_64(i) { \ UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 4); \ SWAP2_64_VAR(v) \ *(UInt64 *)(void *)(items + (i) * 4) = v; } SWAP_BASE_FUNCS_PREFIXES SwapBytes2_64(CSwapUInt16 *items, const CSwapUInt16 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP2_64(0) SWAP2_64(1) items += 2 * 4; SWAP2_64(0) SWAP2_64(1) items += 2 * 4; } while (items != lim); } #define DEFAULT_Swap2 SwapBytes2_64 #if !defined(FORCE_SWAP_MODE) #define SWAP2_DEFAULT_MODE 0 #endif #else // !defined(SWAP2_64_VAR) #define DEFAULT_Swap2 SwapBytes2_128 #if !defined(FORCE_SWAP_MODE) #define SWAP2_DEFAULT_MODE 1 #endif #endif // SWAP2_64_VAR #define SWAP4_64(i) { \ UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 2); \ SWAP4_64_VAR(v) \ *(UInt64 *)(void *)(items + (i) * 2) = v; } SWAP_BASE_FUNCS_PREFIXES SwapBytes4_64(CSwapUInt32 *items, const CSwapUInt32 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP4_64(0) SWAP4_64(1) items += 2 * 2; SWAP4_64(0) SWAP4_64(1) items += 2 * 2; } while (items != lim); } #define DEFAULT_Swap4 SwapBytes4_64 #else // is not 64BIT #if defined(MY_CPU_ARM_OR_ARM64) \ && defined(__ARM_ARCH) && (__ARM_ARCH >= 6) \ && ( (defined(__GNUC__) && (__GNUC__ >= 4)) \ || (defined(__clang__) && (__clang_major__ >= 4))) #ifdef MY_CPU_64BIT #define SWAP2_32_VAR(v) asm ("rev16 %w0,%w0" : "+r" (v)); #else #define SWAP2_32_VAR(v) asm ("rev16 %0,%0" : "+r" (v)); // for clang/gcc // asm ("rev16 %r0,%r0" : "+r" (a)); // for gcc #endif #elif defined(_MSC_VER) && (_MSC_VER < 1300) && defined(MY_CPU_X86) \ || !defined(Z7_CPU_FAST_BSWAP_SUPPORTED) \ || !defined(Z7_CPU_FAST_ROTATE_SUPPORTED) // old msvc doesn't support _byteswap_ulong() #define SWAP2_32_VAR(v) \ v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff); #else // is not ARM and is not old-MSVC-X86 and fast BSWAP/ROTATE are supported #define SWAP2_32_VAR(v) \ v = Z7_BSWAP32(v); \ v = rotlFixed(v, 16); #endif // GNU-ARM* #define SWAP2_32(i) { \ UInt32 v = *(const UInt32 *)(const void *)(items + (i) * 2); \ SWAP2_32_VAR(v); \ *(UInt32 *)(void *)(items + (i) * 2) = v; } SWAP_BASE_FUNCS_PREFIXES SwapBytes2_32(CSwapUInt16 *items, const CSwapUInt16 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP2_32(0) SWAP2_32(1) items += 2 * 2; SWAP2_32(0) SWAP2_32(1) items += 2 * 2; } while (items != lim); } SWAP_BASE_FUNCS_PREFIXES SwapBytes4_32(CSwapUInt32 *items, const CSwapUInt32 *lim) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE do { SWAP4_32(0) SWAP4_32(1) items += 2; SWAP4_32(0) SWAP4_32(1) items += 2; } while (items != lim); } #define DEFAULT_Swap2 SwapBytes2_32 #define DEFAULT_Swap4 SwapBytes4_32 #if !defined(FORCE_SWAP_MODE) #define SWAP2_DEFAULT_MODE 0 #endif #endif // MY_CPU_64BIT #endif // if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4) #if !defined(FORCE_SWAP_MODE) static unsigned g_SwapBytes_Mode; #endif /* size of largest unrolled loop iteration: 128 bytes = 4 * 32 bytes (AVX). */ #define SWAP_ITERATION_BLOCK_SIZE_MAX (1 << 7) // 32 bytes for (AVX) or 2 * 16-bytes for NEON. #define SWAP_VECTOR_ALIGN_SIZE (1 << 5) Z7_NO_INLINE void z7_SwapBytes2(CSwapUInt16 *items, size_t numItems) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--) { SWAP2_16(0) items++; } { const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt16) - 1; size_t numItems2 = numItems; CSwapUInt16 *lim; numItems &= k_Align_Mask; numItems2 &= ~(size_t)k_Align_Mask; lim = items + numItems2; if (numItems2 != 0) { #if !defined(FORCE_SWAP_MODE) #ifdef MY_CPU_X86_OR_AMD64 #ifdef USE_SWAP_AVX2 if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3) ShufBytes_256((__m256i *)(void *)items, (const __m256i *)(const void *)lim, (const __m128i *)(const void *)&(k_ShufMask_Swap2[0])); else #endif #ifdef USE_SWAP_SSSE3 if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3) ShufBytes_128((__m128i *)(void *)items, (const __m128i *)(const void *)lim, (const __m128i *)(const void *)&(k_ShufMask_Swap2[0])); else #endif #endif // MY_CPU_X86_OR_AMD64 #if SWAP2_DEFAULT_MODE == 0 if (g_SwapBytes_Mode != 0) SwapBytes2_128(items, lim); else #endif #endif // FORCE_SWAP_MODE DEFAULT_Swap2(items, lim); } items = lim; } Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0; numItems--) { SWAP2_16(0) items++; } } Z7_NO_INLINE void z7_SwapBytes4(CSwapUInt32 *items, size_t numItems) { Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--) { SWAP4_32(0) items++; } { const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt32) - 1; size_t numItems2 = numItems; CSwapUInt32 *lim; numItems &= k_Align_Mask; numItems2 &= ~(size_t)k_Align_Mask; lim = items + numItems2; if (numItems2 != 0) { #if !defined(FORCE_SWAP_MODE) #ifdef MY_CPU_X86_OR_AMD64 #ifdef USE_SWAP_AVX2 if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3) ShufBytes_256((__m256i *)(void *)items, (const __m256i *)(const void *)lim, (const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); else #endif #ifdef USE_SWAP_SSSE3 if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3) ShufBytes_128((__m128i *)(void *)items, (const __m128i *)(const void *)lim, (const __m128i *)(const void *)&(k_ShufMask_Swap4[0])); else #endif #else // MY_CPU_X86_OR_AMD64 if (g_SwapBytes_Mode != 0) SwapBytes4_128(items, lim); else #endif // MY_CPU_X86_OR_AMD64 #endif // FORCE_SWAP_MODE DEFAULT_Swap4(items, lim); } items = lim; } Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE for (; numItems != 0; numItems--) { SWAP4_32(0) items++; } } // #define SHOW_HW_STATUS #ifdef SHOW_HW_STATUS #include #define PRF(x) x #else #define PRF(x) #endif void z7_SwapBytesPrepare(void) { #ifndef FORCE_SWAP_MODE unsigned mode = 0; // k_SwapBytes_Mode_BASE; #ifdef MY_CPU_ARM_OR_ARM64 { if (CPU_IsSupported_NEON()) { // #pragma message ("=== SwapBytes NEON") PRF(printf("\n=== SwapBytes NEON\n");) mode = k_SwapBytes_Mode_NEON; } } #else // MY_CPU_ARM_OR_ARM64 { #ifdef USE_SWAP_AVX2 if (CPU_IsSupported_AVX2()) { // #pragma message ("=== SwapBytes AVX2") PRF(printf("\n=== SwapBytes AVX2\n");) mode = k_SwapBytes_Mode_AVX2; } else #endif #ifdef USE_SWAP_SSSE3 if (CPU_IsSupported_SSSE3()) { // #pragma message ("=== SwapBytes SSSE3") PRF(printf("\n=== SwapBytes SSSE3\n");) mode = k_SwapBytes_Mode_SSSE3; } else #endif #if !defined(MY_CPU_AMD64) if (CPU_IsSupported_SSE2()) #endif { // #pragma message ("=== SwapBytes SSE2") PRF(printf("\n=== SwapBytes SSE2\n");) mode = k_SwapBytes_Mode_SSE2; } } #endif // MY_CPU_ARM_OR_ARM64 g_SwapBytes_Mode = mode; // g_SwapBytes_Mode = 0; // for debug #endif // FORCE_SWAP_MODE PRF(printf("\n=== SwapBytesPrepare\n");) } #undef PRF tmp41wklro_/C/SwapBytes.h0000444000175000001440000000055314412267100016415 0ustar nabijaczleweliusers/* SwapBytes.h -- Byte Swap conversion filter 2023-04-02 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_SWAP_BYTES_H #define ZIP7_INC_SWAP_BYTES_H #include "7zTypes.h" EXTERN_C_BEGIN void z7_SwapBytes2(UInt16 *data, size_t numItems); void z7_SwapBytes4(UInt32 *data, size_t numItems); void z7_SwapBytesPrepare(void); EXTERN_C_END #endif tmp41wklro_/C/Threads.c0000444000175000001440000003336414601321020016057 0ustar nabijaczleweliusers/* Threads.c -- multithreading library 2024-03-28 : Igor Pavlov : Public domain */ #include "Precomp.h" #ifdef _WIN32 #ifndef USE_THREADS_CreateThread #include #endif #include "Threads.h" static WRes GetError(void) { const DWORD res = GetLastError(); return res ? (WRes)res : 1; } static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); } static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } WRes HandlePtr_Close(HANDLE *p) { if (*p != NULL) { if (!CloseHandle(*p)) return GetError(); *p = NULL; } return 0; } WRes Handle_WaitObject(HANDLE h) { DWORD dw = WaitForSingleObject(h, INFINITE); /* (dw) result: WAIT_OBJECT_0 // 0 WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space WAIT_FAILED // 0xFFFFFFFF */ if (dw == WAIT_FAILED) { dw = GetLastError(); if (dw == 0) return WAIT_FAILED; } return (WRes)dw; } #define Thread_Wait(p) Handle_WaitObject(*(p)) WRes Thread_Wait_Close(CThread *p) { WRes res = Thread_Wait(p); WRes res2 = Thread_Close(p); return (res != 0 ? res : res2); } WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ #ifdef USE_THREADS_CreateThread DWORD threadId; *p = CreateThread(NULL, 0, func, param, 0, &threadId); #else unsigned threadId; *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); #endif /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(*p); } WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) { #ifdef USE_THREADS_CreateThread UNUSED_VAR(affinity) return Thread_Create(p, func, param); #else /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ HANDLE h; WRes wres; unsigned threadId; h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); *p = h; wres = HandleToWRes(h); if (h) { { // DWORD_PTR prevMask = SetThreadAffinityMask(h, (DWORD_PTR)affinity); /* if (prevMask == 0) { // affinity change is non-critical error, so we can ignore it // wres = GetError(); } */ } { DWORD prevSuspendCount = ResumeThread(h); /* ResumeThread() returns: 0 : was_not_suspended 1 : was_resumed -1 : error */ if (prevSuspendCount == (DWORD)-1) wres = GetError(); } } /* maybe we must use errno here, but probably GetLastError() is also OK. */ return wres; #endif } static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); return HandleToWRes(*p); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore() *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); return HandleToWRes(*p); } WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { // if (Semaphore_IsCreated(p)) { WRes wres = Semaphore_Close(p); if (wres != 0) return wres; } return Semaphore_Create(p, initCount, maxCount); } static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) { return Semaphore_Release(p, (LONG)num, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection() can raise exception: Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception Windows Vista+ : no exceptions */ #ifdef _MSC_VER #ifdef __clang__ #pragma GCC diagnostic ignored "-Wlanguage-extension-token" #endif __try #endif { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } #ifdef _MSC_VER __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } #endif return 0; } #else // _WIN32 // ---------- POSIX ---------- #if defined(__linux__) && !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) #ifndef Z7_AFFINITY_DISABLE // _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET // clang < 3.6 : unknown warning group '-Wreserved-id-macro' // clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" // clang >= 13 : do not give warning #if !defined(_GNU_SOURCE) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER // #define _GNU_SOURCE Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif // !defined(_GNU_SOURCE) #endif // Z7_AFFINITY_DISABLE #endif // __linux__ #include "Threads.h" #include #include #include #ifdef Z7_AFFINITY_SUPPORTED // #include #endif // #include // #define PRF(p) p #define PRF(p) #define Print(s) PRF(printf("\n%s\n", s);) WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) { // new thread in Posix probably inherits affinity from parrent thread Print("Thread_Create_With_CpuSet") pthread_attr_t attr; int ret; // int ret2; p->_created = 0; RINOK(pthread_attr_init(&attr)) ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if (!ret) { if (cpuSet) { // pthread_attr_setaffinity_np() is not supported for MUSL compile. // so we check for __GLIBC__ here #if defined(Z7_AFFINITY_SUPPORTED) && defined( __GLIBC__) /* printf("\n affinity :"); unsigned i; for (i = 0; i < sizeof(*cpuSet) && i < 8; i++) { Byte b = *((const Byte *)cpuSet + i); char temp[32]; #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) temp[0] = GET_HEX_CHAR((b & 0xF)); temp[1] = GET_HEX_CHAR((b >> 4)); // temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian // temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian temp[2] = 0; printf("%s", temp); } printf("\n"); */ // ret2 = pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); // if (ret2) ret = ret2; #endif } ret = pthread_create(&p->_tid, &attr, func, param); if (!ret) { p->_created = 1; /* if (cpuSet) { // ret2 = pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet); // if (ret2) ret = ret2; } */ } } // ret2 = pthread_attr_destroy(&attr); // if (ret2 != 0) ret = ret2; return ret; } WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { return Thread_Create_With_CpuSet(p, func, param, NULL); } WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) { Print("Thread_Create_WithAffinity") CCpuSet cs; unsigned i; CpuSet_Zero(&cs); for (i = 0; i < sizeof(affinity) * 8; i++) { if (affinity == 0) break; if (affinity & 1) { CpuSet_Set(&cs, i); } affinity >>= 1; } return Thread_Create_With_CpuSet(p, func, param, &cs); } WRes Thread_Close(CThread *p) { // Print("Thread_Close") int ret; if (!p->_created) return 0; ret = pthread_detach(p->_tid); p->_tid = 0; p->_created = 0; return ret; } WRes Thread_Wait_Close(CThread *p) { // Print("Thread_Wait_Close") void *thread_return; int ret; if (!p->_created) return EINVAL; ret = pthread_join(p->_tid, &thread_return); // probably we can't use that (_tid) after pthread_join(), so we close thread here p->_created = 0; p->_tid = 0; return ret; } static WRes Event_Create(CEvent *p, int manualReset, int signaled) { RINOK(pthread_mutex_init(&p->_mutex, NULL)) RINOK(pthread_cond_init(&p->_cond, NULL)) p->_manual_reset = manualReset; p->_state = (signaled ? True : False); p->_created = 1; return 0; } WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, True, signaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, False, signaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } #if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) // freebsd: #pragma GCC diagnostic ignored "-Wthread-safety-analysis" #endif WRes Event_Set(CEvent *p) { RINOK(pthread_mutex_lock(&p->_mutex)) p->_state = True; { const int res1 = pthread_cond_broadcast(&p->_cond); const int res2 = pthread_mutex_unlock(&p->_mutex); return (res2 ? res2 : res1); } } WRes Event_Reset(CEvent *p) { RINOK(pthread_mutex_lock(&p->_mutex)) p->_state = False; return pthread_mutex_unlock(&p->_mutex); } WRes Event_Wait(CEvent *p) { RINOK(pthread_mutex_lock(&p->_mutex)) while (p->_state == False) { // ETIMEDOUT // ret = pthread_cond_wait(&p->_cond, &p->_mutex); // if (ret != 0) break; } if (p->_manual_reset == False) { p->_state = False; } return pthread_mutex_unlock(&p->_mutex); } WRes Event_Close(CEvent *p) { if (!p->_created) return 0; p->_created = 0; { const int res1 = pthread_mutex_destroy(&p->_mutex); const int res2 = pthread_cond_destroy(&p->_cond); return (res1 ? res1 : res2); } } WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { if (initCount > maxCount || maxCount < 1) return EINVAL; RINOK(pthread_mutex_init(&p->_mutex, NULL)) RINOK(pthread_cond_init(&p->_cond, NULL)) p->_count = initCount; p->_maxCount = maxCount; p->_created = 1; return 0; } WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { if (Semaphore_IsCreated(p)) { /* WRes wres = Semaphore_Close(p); if (wres != 0) return wres; */ if (initCount > maxCount || maxCount < 1) return EINVAL; // return EINVAL; // for debug p->_count = initCount; p->_maxCount = maxCount; return 0; } return Semaphore_Create(p, initCount, maxCount); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { UInt32 newCount; int ret; if (releaseCount < 1) return EINVAL; RINOK(pthread_mutex_lock(&p->_mutex)) newCount = p->_count + releaseCount; if (newCount > p->_maxCount) ret = ERROR_TOO_MANY_POSTS; // EINVAL; else { p->_count = newCount; ret = pthread_cond_broadcast(&p->_cond); } RINOK(pthread_mutex_unlock(&p->_mutex)) return ret; } WRes Semaphore_Wait(CSemaphore *p) { RINOK(pthread_mutex_lock(&p->_mutex)) while (p->_count < 1) { pthread_cond_wait(&p->_cond, &p->_mutex); } p->_count--; return pthread_mutex_unlock(&p->_mutex); } WRes Semaphore_Close(CSemaphore *p) { if (!p->_created) return 0; p->_created = 0; { const int res1 = pthread_mutex_destroy(&p->_mutex); const int res2 = pthread_cond_destroy(&p->_cond); return (res1 ? res1 : res2); } } WRes CriticalSection_Init(CCriticalSection *p) { // Print("CriticalSection_Init") if (!p) return EINTR; return pthread_mutex_init(&p->_mutex, NULL); } void CriticalSection_Enter(CCriticalSection *p) { // Print("CriticalSection_Enter") if (p) { // int ret = pthread_mutex_lock(&p->_mutex); } } void CriticalSection_Leave(CCriticalSection *p) { // Print("CriticalSection_Leave") if (p) { // int ret = pthread_mutex_unlock(&p->_mutex); } } void CriticalSection_Delete(CCriticalSection *p) { // Print("CriticalSection_Delete") if (p) { // int ret = pthread_mutex_destroy(&p->_mutex); } } LONG InterlockedIncrement(LONG volatile *addend) { // Print("InterlockedIncrement") #ifdef USE_HACK_UNSAFE_ATOMIC LONG val = *addend + 1; *addend = val; return val; #else #if defined(__clang__) && (__clang_major__ >= 8) #pragma GCC diagnostic ignored "-Watomic-implicit-seq-cst" #endif return __sync_add_and_fetch(addend, 1); #endif } LONG InterlockedDecrement(LONG volatile *addend) { // Print("InterlockedDecrement") #ifdef USE_HACK_UNSAFE_ATOMIC LONG val = *addend - 1; *addend = val; return val; #else return __sync_sub_and_fetch(addend, 1); #endif } #endif // _WIN32 WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) { if (Event_IsCreated(p)) return Event_Reset(p); return AutoResetEvent_CreateNotSignaled(p); } #undef PRF #undef Print tmp41wklro_/C/Threads.h0000444000175000001440000001625114601321020016060 0ustar nabijaczleweliusers/* Threads.h -- multithreading library 2024-03-28 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_THREADS_H #define ZIP7_INC_THREADS_H #ifdef _WIN32 #include "7zWindows.h" #else #include "Compiler.h" // #define Z7_AFFINITY_DISABLE #if defined(__linux__) #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) #ifndef Z7_AFFINITY_DISABLE #define Z7_AFFINITY_SUPPORTED // #pragma message(" ==== Z7_AFFINITY_SUPPORTED") #if !defined(_GNU_SOURCE) // #pragma message(" ==== _GNU_SOURCE set") // we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define _GNU_SOURCE Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #endif #endif #endif #endif #include #endif #include "7zTypes.h" EXTERN_C_BEGIN #ifdef _WIN32 WRes HandlePtr_Close(HANDLE *h); WRes Handle_WaitObject(HANDLE h); typedef HANDLE CThread; #define Thread_CONSTRUCT(p) { *(p) = NULL; } #define Thread_WasCreated(p) (*(p) != NULL) #define Thread_Close(p) HandlePtr_Close(p) // #define Thread_Wait(p) Handle_WaitObject(*(p)) #ifdef UNDER_CE // if (USE_THREADS_CreateThread is defined), we use _beginthreadex() // if (USE_THREADS_CreateThread is not definned), we use CreateThread() #define USE_THREADS_CreateThread #endif typedef #ifdef USE_THREADS_CreateThread DWORD #else unsigned #endif THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_RET_ZERO 0 typedef DWORD_PTR CAffinityMask; typedef DWORD_PTR CCpuSet; #define CpuSet_Zero(p) *(p) = (0) #define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu)) #else // _WIN32 typedef struct { pthread_t _tid; int _created; } CThread; #define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; } #define Thread_WasCreated(p) ((p)->_created != 0) WRes Thread_Close(CThread *p); // #define Thread_Wait Thread_Wait_Close typedef void * THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_RET_ZERO NULL typedef UInt64 CAffinityMask; #ifdef Z7_AFFINITY_SUPPORTED typedef cpu_set_t CCpuSet; #define CpuSet_Zero(p) CPU_ZERO(p) #define CpuSet_Set(p, cpu) CPU_SET(cpu, p) #define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) #else typedef UInt64 CCpuSet; #define CpuSet_Zero(p) *(p) = (0) #define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu)) #define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) #endif #endif // _WIN32 #define THREAD_FUNC_CALL_TYPE Z7_STDCALL #if defined(_WIN32) && defined(__GNUC__) /* GCC compiler for x86 32-bit uses the rule: the stack is 16-byte aligned before CALL instruction for function calling. But only root function main() contains instructions that set 16-byte alignment for stack pointer. And another functions just keep alignment, if it was set in some parent function. The problem: if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(), the root function of thread doesn't set 16-byte alignment. And stack frames in all child functions also will be unaligned in that case. Here we set (force_align_arg_pointer) attribute for root function of new thread. Do we need (force_align_arg_pointer) also for another systems? */ #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer)) // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions #else #define THREAD_FUNC_ATTRIB_ALIGN_ARG #endif #define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity); WRes Thread_Wait_Close(CThread *p); #ifdef _WIN32 #define Thread_Create_With_CpuSet(p, func, param, cs) \ Thread_Create_With_Affinity(p, func, param, *cs) #else WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); #endif #ifdef _WIN32 typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(p) *(p) = NULL #define Event_IsCreated(p) (*(p) != NULL) #define Event_Close(p) HandlePtr_Close(p) #define Event_Wait(p) Handle_WaitObject(*(p)) WRes Event_Set(CEvent *p); WRes Event_Reset(CEvent *p); WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); typedef HANDLE CSemaphore; #define Semaphore_Construct(p) *(p) = NULL #define Semaphore_IsCreated(p) (*(p) != NULL) #define Semaphore_Close(p) HandlePtr_Close(p) #define Semaphore_Wait(p) Handle_WaitObject(*(p)) WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #else // _WIN32 typedef struct { int _created; int _manual_reset; int _state; pthread_mutex_t _mutex; pthread_cond_t _cond; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(p) (p)->_created = 0 #define Event_IsCreated(p) ((p)->_created) WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); WRes Event_Set(CEvent *p); WRes Event_Reset(CEvent *p); WRes Event_Wait(CEvent *p); WRes Event_Close(CEvent *p); typedef struct { int _created; UInt32 _count; UInt32 _maxCount; pthread_mutex_t _mutex; pthread_cond_t _cond; } CSemaphore; #define Semaphore_Construct(p) (p)->_created = 0 #define Semaphore_IsCreated(p) ((p)->_created) WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef struct { pthread_mutex_t _mutex; } CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); void CriticalSection_Delete(CCriticalSection *cs); void CriticalSection_Enter(CCriticalSection *cs); void CriticalSection_Leave(CCriticalSection *cs); LONG InterlockedIncrement(LONG volatile *addend); LONG InterlockedDecrement(LONG volatile *addend); #endif // _WIN32 WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p); EXTERN_C_END #endif tmp41wklro_/C/Util/0000700000175000001440000000000014706260545015241 5ustar nabijaczleweliuserstmp41wklro_/C/Util/7z/0000700000175000001440000000000014706260545015601 5ustar nabijaczleweliuserstmp41wklro_/C/Util/7z/7z.dsp0000444000175000001440000001530614554735340016667 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /FAcs /Yu"Precomp.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /Yu"Precomp.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7z.h # End Source File # Begin Source File SOURCE=..\..\7zAlloc.c # End Source File # Begin Source File SOURCE=..\..\7zAlloc.h # End Source File # Begin Source File SOURCE=..\..\7zArcIn.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zCrcOpt.c # End Source File # Begin Source File SOURCE=..\..\7zDec.c # ADD CPP /D "_7ZIP_PPMD_SUPPPORT" # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.c # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\BraIA64.c # End Source File # Begin Source File SOURCE=..\..\CpuArch.c # End Source File # Begin Source File SOURCE=..\..\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\Delta.c # End Source File # Begin Source File SOURCE=..\..\Delta.h # End Source File # Begin Source File SOURCE=..\..\Lzma2Dec.c # End Source File # Begin Source File SOURCE=..\..\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Ppmd.h # End Source File # Begin Source File SOURCE=..\..\Ppmd7.c # End Source File # Begin Source File SOURCE=..\..\Ppmd7.h # End Source File # Begin Source File SOURCE=..\..\Ppmd7Dec.c # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compiler.h # End Source File # Begin Source File SOURCE=.\Precomp.c # ADD CPP /Yc"Precomp.h" # End Source File # Begin Source File SOURCE=..\..\Precomp.h # End Source File # Begin Source File SOURCE=.\Precomp.h # End Source File # End Group # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project tmp41wklro_/C/Util/7z/7z.dsw0000444000175000001440000000101710767422400016660 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/C/Util/7z/7zMain.c0000444000175000001440000005243314567654200017131 0ustar nabijaczleweliusers/* 7zMain.c - Test application for 7z Decoder 2024-02-28 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include #ifndef USE_WINDOWS_FILE /* for mkdir */ #ifdef _WIN32 #include #else #include #include #ifdef __GNUC__ #include #endif #include // #include #include #include #endif #endif #include "../../7zFile.h" #include "../../7z.h" #include "../../7zAlloc.h" #include "../../7zBuf.h" #include "../../7zCrc.h" #include "../../7zVersion.h" #include "../../CpuArch.h" #define kInputBufSize ((size_t)1 << 18) static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; // static const ISzAlloc g_Alloc_temp = { SzAllocTemp, SzFreeTemp }; static void Print(const char *s) { fputs(s, stdout); } static int Buf_EnsureSize(CBuf *dest, size_t size) { if (dest->size >= size) return 1; Buf_Free(dest, &g_Alloc); return Buf_Create(dest, size, &g_Alloc); } #ifndef _WIN32 #define MY_USE_UTF8 #endif /* #define MY_USE_UTF8 */ #ifdef MY_USE_UTF8 #define MY_UTF8_START(n) (0x100 - (1 << (7 - (n)))) #define MY_UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) #define MY_UTF8_HEAD(n, val) ((Byte)(MY_UTF8_START(n) + (val >> (6 * (n))))) #define MY_UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F))) static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim) { size_t size = 0; for (;;) { UInt32 val; if (src == srcLim) return size; size++; val = *src++; if (val < 0x80) continue; if (val < MY_UTF8_RANGE(1)) { size++; continue; } if (val >= 0xD800 && val < 0xDC00 && src != srcLim) { const UInt32 c2 = *src; if (c2 >= 0xDC00 && c2 < 0xE000) { src++; size += 3; continue; } } size += 2; } } static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim) { for (;;) { UInt32 val; if (src == srcLim) return dest; val = *src++; if (val < 0x80) { *dest++ = (Byte)val; continue; } if (val < MY_UTF8_RANGE(1)) { dest[0] = MY_UTF8_HEAD(1, val); dest[1] = MY_UTF8_CHAR(0, val); dest += 2; continue; } if (val >= 0xD800 && val < 0xDC00 && src != srcLim) { const UInt32 c2 = *src; if (c2 >= 0xDC00 && c2 < 0xE000) { src++; val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; dest[0] = MY_UTF8_HEAD(3, val); dest[1] = MY_UTF8_CHAR(2, val); dest[2] = MY_UTF8_CHAR(1, val); dest[3] = MY_UTF8_CHAR(0, val); dest += 4; continue; } } dest[0] = MY_UTF8_HEAD(2, val); dest[1] = MY_UTF8_CHAR(1, val); dest[2] = MY_UTF8_CHAR(0, val); dest += 3; } } static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) { size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen); destLen += 1; if (!Buf_EnsureSize(dest, destLen)) return SZ_ERROR_MEM; *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0; return SZ_OK; } #endif static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s #ifndef MY_USE_UTF8 , UINT codePage #endif ) { size_t len = 0; for (len = 0; s[len] != 0; len++) {} #ifndef MY_USE_UTF8 { const size_t size = len * 3 + 100; if (!Buf_EnsureSize(buf, size)) return SZ_ERROR_MEM; { buf->data[0] = 0; if (len != 0) { const char defaultChar = '_'; BOOL defUsed; const unsigned numChars = (unsigned)WideCharToMultiByte( codePage, 0, (LPCWSTR)s, (int)len, (char *)buf->data, (int)size, &defaultChar, &defUsed); if (numChars == 0 || numChars >= size) return SZ_ERROR_FAIL; buf->data[numChars] = 0; } return SZ_OK; } } #else return Utf16_To_Utf8Buf(buf, s, len); #endif } #ifdef _WIN32 #ifndef USE_WINDOWS_FILE static UINT g_FileCodePage = CP_ACP; #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage #endif #else #define MY_FILE_CODE_PAGE_PARAM #endif static WRes MyCreateDir(const UInt16 *name) { #ifdef USE_WINDOWS_FILE return CreateDirectoryW((LPCWSTR)name, NULL) ? 0 : GetLastError(); #else CBuf buf; WRes res; Buf_Init(&buf); RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)) res = #ifdef _WIN32 _mkdir((const char *)buf.data) #else mkdir((const char *)buf.data, 0777) #endif == 0 ? 0 : errno; Buf_Free(&buf, &g_Alloc); return res; #endif } static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) { #ifdef USE_WINDOWS_FILE return OutFile_OpenW(p, (LPCWSTR)name); #else CBuf buf; WRes res; Buf_Init(&buf); RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)) res = OutFile_Open(p, (const char *)buf.data); Buf_Free(&buf, &g_Alloc); return res; #endif } static SRes PrintString(const UInt16 *s) { CBuf buf; SRes res; Buf_Init(&buf); res = Utf16_To_Char(&buf, s #ifndef MY_USE_UTF8 , CP_OEMCP #endif ); if (res == SZ_OK) Print((const char *)buf.data); Buf_Free(&buf, &g_Alloc); return res; } static void UInt64ToStr(UInt64 value, char *s, int numDigits) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (unsigned)(value % 10)); value /= 10; } while (value != 0); for (numDigits -= pos; numDigits > 0; numDigits--) *s++ = ' '; do *s++ = temp[--pos]; while (pos); *s = '\0'; } static char *UIntToStr(char *s, unsigned value, int numDigits) { char temp[16]; int pos = 0; do temp[pos++] = (char)('0' + (value % 10)); while (value /= 10); for (numDigits -= pos; numDigits > 0; numDigits--) *s++ = '0'; do *s++ = temp[--pos]; while (pos); *s = '\0'; return s; } static void UIntToStr_2(char *s, unsigned value) { s[0] = (char)('0' + (value / 10)); s[1] = (char)('0' + (value % 10)); } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) #ifndef _WIN32 // MS uses long for BOOL, but long is 32-bit in MS. So we use int. // typedef long BOOL; typedef int BOOL; typedef struct { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME; static LONG TIME_GetBias(void) { const time_t utc = time(NULL); struct tm *ptm = localtime(&utc); const int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ ptm = gmtime(&utc); ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ return (int)(mktime(ptm) - utc); } #define TICKS_PER_SEC 10000000 #define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32)) #define SET_FILETIME(ft, v64) \ (ft)->dwLowDateTime = (DWORD)v64; \ (ft)->dwHighDateTime = (DWORD)(v64 >> 32); #define WINAPI #define TRUE 1 static BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime) { UInt64 v = GET_TIME_64(fileTime); v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC); SET_FILETIME(localFileTime, v) return TRUE; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt32 kFileTimeStartYear = 1601; static const UInt32 kUnixTimeStartYear = 1970; static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft) { const UInt64 kUnixTimeOffset = (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); const UInt64 winTime = GET_TIME_64(ft); return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; } #if defined(_AIX) #define MY_ST_TIMESPEC st_timespec #else #define MY_ST_TIMESPEC timespec #endif static void FILETIME_To_timespec(const FILETIME *ft, struct MY_ST_TIMESPEC *ts) { if (ft) { const Int64 sec = Time_FileTimeToUnixTime64(ft); // time_t is long const time_t sec2 = (time_t)sec; if (sec2 == sec) { ts->tv_sec = sec2; { const UInt64 winTime = GET_TIME_64(ft); ts->tv_nsec = (long)((winTime % 10000000) * 100); } return; } } // else { ts->tv_sec = 0; // ts.tv_nsec = UTIME_NOW; // set to the current time ts->tv_nsec = UTIME_OMIT; // keep old timesptamp } } static WRes Set_File_FILETIME(const UInt16 *name, const FILETIME *mTime) { struct timespec times[2]; const int flags = 0; // follow link // = AT_SYMLINK_NOFOLLOW; // don't follow link CBuf buf; int res; Buf_Init(&buf); RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)) FILETIME_To_timespec(NULL, ×[0]); FILETIME_To_timespec(mTime, ×[1]); res = utimensat(AT_FDCWD, (const char *)buf.data, times, flags); Buf_Free(&buf, &g_Alloc); if (res == 0) return 0; return errno; } #endif static void NtfsFileTime_to_FILETIME(const CNtfsFileTime *t, FILETIME *ft) { ft->dwLowDateTime = (DWORD)(t->Low); ft->dwHighDateTime = (DWORD)(t->High); } static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s) { unsigned year, mon, hour, min, sec; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; UInt32 t; UInt32 v; // UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); UInt64 v64; { FILETIME fileTime, locTime; NtfsFileTime_to_FILETIME(nTime, &fileTime); if (!FileTimeToLocalFileTime(&fileTime, &locTime)) { locTime.dwHighDateTime = locTime.dwLowDateTime = 0; } v64 = locTime.dwLowDateTime | ((UInt64)locTime.dwHighDateTime << 32); } v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 0;; mon++) { const UInt32 d = ms[mon]; if (v < d) break; v -= d; } s = UIntToStr(s, year, 4); *s++ = '-'; UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3; UIntToStr_2(s, hour); s[2] = ':'; s += 3; UIntToStr_2(s, min); s[2] = ':'; s += 3; UIntToStr_2(s, sec); s[2] = 0; } static void PrintLF(void) { Print("\n"); } static void PrintError(char *s) { Print("\nERROR: "); Print(s); PrintLF(); } static void PrintError_WRes(const char *message, WRes wres) { Print("\nERROR: "); Print(message); PrintLF(); { char s[32]; UIntToStr(s, (unsigned)wres, 1); Print("System error code: "); Print(s); } // sprintf(buffer + strlen(buffer), "\nSystem error code: %d", (unsigned)wres); #ifdef _WIN32 { char *s = NULL; if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, wres, 0, (LPSTR) &s, 0, NULL) != 0 && s) { Print(" : "); Print(s); LocalFree(s); } } #else { const char *s = strerror(wres); if (s) { Print(" : "); Print(s); } } #endif PrintLF(); } static void GetAttribString(UInt32 wa, BoolInt isDir, char *s) { #ifdef USE_WINDOWS_FILE s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); s[5] = 0; #else s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.'); s[1] = 0; #endif } // #define NUM_PARENTS_MAX 128 int Z7_CDECL main(int numargs, char *args[]) { ISzAlloc allocImp; ISzAlloc allocTempImp; CFileInStream archiveStream; CLookToRead2 lookStream; CSzArEx db; SRes res; UInt16 *temp = NULL; size_t tempSize = 0; // UInt32 parents[NUM_PARENTS_MAX]; Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"); if (numargs == 1) { Print( "Usage: 7zDec \n\n" "\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full paths\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; #endif allocImp = g_Alloc; allocTempImp = g_Alloc; // allocTempImp = g_Alloc_temp; { WRes wres = #ifdef UNDER_CE InFile_OpenW(&archiveStream.file, L"\test.7z"); // change it #else InFile_Open(&archiveStream.file, args[2]); #endif if (wres != 0) { PrintError_WRes("cannot open input file", wres); return 1; } } FileInStream_CreateVTable(&archiveStream); archiveStream.wres = 0; LookToRead2_CreateVTable(&lookStream, False); lookStream.buf = NULL; res = SZ_OK; { lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize); if (!lookStream.buf) res = SZ_ERROR_MEM; else { lookStream.bufSize = kInputBufSize; lookStream.realStream = &archiveStream.vt; LookToRead2_INIT(&lookStream) } } CrcGenerateTable(); SzArEx_Init(&db); if (res == SZ_OK) { res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); } if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, fullPaths = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) { } else if (strcmp(command, "x") == 0) { fullPaths = 1; } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } if (res == SZ_OK) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; // const CSzFileItem *f = db.Files + i; size_t len; const BoolInt isDir = SzArEx_IsDir(&db, i); if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); // len = SzArEx_GetFullNameLen(&db, i); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); if (!temp) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); /* if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) { res = SZ_ERROR_FAIL; break; } */ if (listCommand) { char attr[8], s[32], t[32]; UInt64 fileSize; GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); fileSize = SzArEx_GetFileSize(&db, i); UInt64ToStr(fileSize, s, 10); if (SzBitWithVals_Check(&db.MTime, i)) ConvertFileTimeToString(&db.MTime.Vals[i], t); else { size_t j; for (j = 0; j < 19; j++) t[j] = ' '; t[j] = '\0'; } Print(t); Print(" "); Print(attr); Print(" "); Print(s); Print(" "); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) Print("/"); PrintLF(); continue; } Print(testCommand ? "T ": "- "); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) Print("/"); else { res = SzArEx_Extract(&db, &lookStream.vt, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } if (!testCommand) { CSzFile outFile; size_t processedSize; size_t j; UInt16 *name = (UInt16 *)temp; const UInt16 *destPath = (const UInt16 *)name; for (j = 0; name[j] != 0; j++) if (name[j] == '/') { if (fullPaths) { name[j] = 0; MyCreateDir(name); name[j] = CHAR_PATH_SEPARATOR; } else destPath = name + j + 1; } if (isDir) { MyCreateDir(destPath); PrintLF(); continue; } else { const WRes wres = OutFile_OpenUtf16(&outFile, destPath); if (wres != 0) { PrintError_WRes("cannot open output file", wres); res = SZ_ERROR_FAIL; break; } } processedSize = outSizeProcessed; { const WRes wres = File_Write(&outFile, outBuffer + offset, &processedSize); if (wres != 0 || processedSize != outSizeProcessed) { PrintError_WRes("cannot write output file", wres); res = SZ_ERROR_FAIL; break; } } { FILETIME mtime; FILETIME *mtimePtr = NULL; #ifdef USE_WINDOWS_FILE FILETIME ctime; FILETIME *ctimePtr = NULL; #endif if (SzBitWithVals_Check(&db.MTime, i)) { const CNtfsFileTime *t = &db.MTime.Vals[i]; mtime.dwLowDateTime = (DWORD)(t->Low); mtime.dwHighDateTime = (DWORD)(t->High); mtimePtr = &mtime; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.CTime, i)) { const CNtfsFileTime *t = &db.CTime.Vals[i]; ctime.dwLowDateTime = (DWORD)(t->Low); ctime.dwHighDateTime = (DWORD)(t->High); ctimePtr = &ctime; } if (mtimePtr || ctimePtr) SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr); #endif { const WRes wres = File_Close(&outFile); if (wres != 0) { PrintError_WRes("cannot close output file", wres); res = SZ_ERROR_FAIL; break; } } #ifndef USE_WINDOWS_FILE #ifdef _WIN32 mtimePtr = mtimePtr; #else if (mtimePtr) Set_File_FILETIME(destPath, mtimePtr); #endif #endif } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) { UInt32 attrib = db.Attribs.Vals[i]; /* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker. We remove posix bits, if we detect posix mode field */ if ((attrib & 0xF0000000) != 0) attrib &= 0x7FFF; SetFileAttributesW((LPCWSTR)destPath, attrib); } #endif } PrintLF(); } ISzAlloc_Free(&allocImp, outBuffer); } } SzFree(NULL, temp); SzArEx_Free(&db, &allocImp); ISzAlloc_Free(&allocImp, lookStream.buf); File_Close(&archiveStream.file); if (res == SZ_OK) { Print("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("cannot allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else if (res == SZ_ERROR_READ /* || archiveStream.Res != 0 */) PrintError_WRes("Read Error", archiveStream.wres); else { char s[32]; UInt64ToStr((unsigned)res, s, 0); PrintError(s); } return 1; } tmp41wklro_/C/Util/7z/makefile0000444000175000001440000000141614576773420017321 0ustar nabijaczleweliusersCFLAGS = $(CFLAGS) -DZ7_PPMD_SUPPORT -DZ7_EXTRACT_ONLY PROG = 7zDec.exe C_OBJS = \ $O\7zAlloc.obj \ $O\7zBuf.obj \ $O\7zFile.obj \ $O\7zDec.obj \ $O\7zArcIn.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ 7Z_OBJS = \ $O\7zMain.obj \ !include "../../../CPP/7zip/Crc.mak" !include "../../../CPP/7zip/LzmaDec.mak" OBJS = \ $O\Precomp.obj \ $(7Z_OBJS) \ $(C_OBJS) \ $(ASM_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(CCOMPL_USE) $(C_OBJS): ../../$(*B).c $(CCOMPL_USE) $O\Precomp.obj: Precomp.c $(CCOMPL_PCH) !include "../../Asm_c.mak" tmp41wklro_/C/Util/7z/makefile.gcc0000444000175000001440000000102014400144000020007 0ustar nabijaczleweliusersPROG = 7zdec LOCAL_FLAGS = -DZ7_PPMD_SUPPORT -DZ7_EXTRACT_ONLY include ../../../CPP/7zip/LzmaDec_gcc.mak OBJS = \ $(LZMA_DEC_OPT_OBJS) \ $O/Bcj2.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ $O/CpuArch.o \ $O/Delta.o \ $O/Lzma2Dec.o \ $O/LzmaDec.o \ $O/Ppmd7.o \ $O/Ppmd7Dec.o \ $O/7zCrc.o \ $O/7zCrcOpt.o \ $O/7zAlloc.o \ $O/7zArcIn.o \ $O/7zBuf.o \ $O/7zBuf2.o \ $O/7zDec.o \ $O/7zMain.o \ $O/7zFile.o \ $O/7zStream.o \ include ../../7zip_gcc_c.mak tmp41wklro_/C/Util/7z/Precomp.c0000444000175000001440000000013512100022440017331 0ustar nabijaczleweliusers/* Precomp.c -- StdAfx 2013-01-21 : Igor Pavlov : Public domain */ #include "Precomp.h" tmp41wklro_/C/Util/7z/Precomp.h0000444000175000001440000000046614553671000017365 0ustar nabijaczleweliusers/* Precomp.h -- Precomp 2024-01-23 : Igor Pavlov : Public domain */ // #ifndef ZIP7_INC_PRECOMP_LOC_H // #define ZIP7_INC_PRECOMP_LOC_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Precomp.h" // #endif tmp41wklro_/C/Util/Lzma/0000700000175000001440000000000014706260545016144 5ustar nabijaczleweliuserstmp41wklro_/C/Util/Lzma/LzmaUtil.c0000444000175000001440000001675114413071660020064 0ustar nabijaczleweliusers/* LzmaUtil.c -- Test application for LZMA compression 2023-03-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include #include #include "../../CpuArch.h" #include "../../Alloc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "../../LzFind.h" #include "../../LzmaDec.h" #include "../../LzmaEnc.h" static const char * const kCantReadMessage = "Cannot read input file"; static const char * const kCantWriteMessage = "Cannot write output file"; static const char * const kCantAllocateMessage = "Cannot allocate memory"; static const char * const kDataErrorMessage = "Data error"; static void Print(const char *s) { fputs(s, stdout); } static void PrintHelp(void) { Print( "\n" "LZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n" "\n" "Usage: lzma inputFile outputFile" "\n" " e: encode file" "\n" " d: decode file" "\n"); } static int PrintError(const char *message) { Print("\nError: "); Print(message); Print("\n"); return 1; } #define CONVERT_INT_TO_STR(charType, tempSize) \ unsigned char temp[tempSize]; unsigned i = 0; \ while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ *s++ = (charType)('0' + (unsigned)val); \ while (i != 0) { i--; *s++ = (charType)temp[i]; } \ *s = 0; \ return s; static char * Convert_unsigned_To_str(unsigned val, char *s) { CONVERT_INT_TO_STR(char, 32) } static void Print_unsigned(unsigned code) { char str[32]; Convert_unsigned_To_str(code, str); Print(str); } static int PrintError_WRes(const char *message, WRes wres) { PrintError(message); Print("\nSystem error code: "); Print_unsigned((unsigned)wres); #ifndef _WIN32 { const char *s = strerror(wres); if (s) { Print(" : "); Print(s); } } #endif Print("\n"); return 1; } static int PrintErrorNumber(SRes val) { Print("\n7-Zip error code: "); Print_unsigned((unsigned)val); Print("\n"); return 1; } static int PrintUserError(void) { return PrintError("Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, UInt64 unpackSize) { const int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)) inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || (thereIsSize && unpackSize == 0)) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ { size_t size = sizeof(header); RINOK(SeqInStream_ReadMax(inStream, header, &size)) if (size != sizeof(header)) return SZ_ERROR_INPUT_EOF; } unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_CONSTRUCT(&state) RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)) res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, UInt64 fileSize) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int Z7_CDECL main(int numArgs, const char *args[]) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; BoolInt useOutFile = False; LzFindPrepare(); FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); inStream.wres = 0; FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); outStream.wres = 0; if (numArgs == 1) { PrintHelp(); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(); /* { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError("Incorrect UInt32 or UInt64"); } */ { const WRes wres = InFile_Open(&inStream.file, args[2]); if (wres != 0) return PrintError_WRes("Cannot open input file", wres); } if (numArgs > 3) { WRes wres; useOutFile = True; wres = OutFile_Open(&outStream.file, args[3]); if (wres != 0) return PrintError_WRes("Cannot open output file", wres); } else if (encodeMode) PrintUserError(); if (encodeMode) { UInt64 fileSize; const WRes wres = File_GetLength(&inStream.file, &fileSize); if (wres != 0) return PrintError_WRes("Cannot get file length", wres); res = Encode(&outStream.vt, &inStream.vt, fileSize); } else { res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError_WRes(kCantWriteMessage, outStream.wres); else if (res == SZ_ERROR_READ) return PrintError_WRes(kCantReadMessage, inStream.wres); return PrintErrorNumber(res); } return 0; } tmp41wklro_/C/Util/Lzma/LzmaUtil.dsp0000444000175000001440000001312314413100700020402 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\7zVersion.h # End Source File # Begin Source File SOURCE=..\..\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\Alloc.c # End Source File # Begin Source File SOURCE=..\..\Alloc.h # End Source File # Begin Source File SOURCE=..\..\Compiler.h # End Source File # Begin Source File SOURCE=..\..\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\LzFind.c # End Source File # Begin Source File SOURCE=..\..\LzFind.h # End Source File # Begin Source File SOURCE=..\..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\LzFindOpt.c # End Source File # Begin Source File SOURCE=..\..\LzHash.h # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\..\Precomp.h # End Source File # Begin Source File SOURCE=.\Precomp.h # End Source File # Begin Source File SOURCE=..\..\Threads.c # End Source File # Begin Source File SOURCE=..\..\Threads.h # End Source File # End Target # End Project tmp41wklro_/C/Util/Lzma/LzmaUtil.dsw0000444000175000001440000000103310765174202020424 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/C/Util/Lzma/makefile0000444000175000001440000000073014137744326017656 0ustar nabijaczleweliusers# MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\CpuArch.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzFindOpt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../../$(*B).c $(COMPL_O2) tmp41wklro_/C/Util/Lzma/makefile.gcc0000444000175000001440000000051414137744375020415 0ustar nabijaczleweliusersPROG = 7lzma include ../../../CPP/7zip/LzmaDec_gcc.mak OBJS = \ $(LZMA_DEC_OPT_OBJS) \ $O/7zFile.o \ $O/7zStream.o \ $O/Alloc.o \ $O/CpuArch.o \ $O/LzFind.o \ $O/LzFindMt.o \ $O/LzFindOpt.o \ $O/LzmaDec.o \ $O/LzmaEnc.o \ $O/LzmaUtil.o \ $O/Threads.o \ include ../../7zip_gcc_c.mak tmp41wklro_/C/Util/Lzma/Precomp.h0000444000175000001440000000046614553671000017730 0ustar nabijaczleweliusers/* Precomp.h -- Precomp 2024-01-23 : Igor Pavlov : Public domain */ // #ifndef ZIP7_INC_PRECOMP_LOC_H // #define ZIP7_INC_PRECOMP_LOC_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Precomp.h" // #endif tmp41wklro_/C/Util/LzmaLib/0000700000175000001440000000000014706260545016573 5ustar nabijaczleweliuserstmp41wklro_/C/Util/LzmaLib/LzmaLib.def0000444000175000001440000000005510764732117020614 0ustar nabijaczleweliusersEXPORTS LzmaCompress LzmaUncompress tmp41wklro_/C/Util/LzmaLib/LzmaLib.dsp0000444000175000001440000001301614413017520020632 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # Begin Source File SOURCE=.\Precomp.h # End Source File # End Group # Begin Source File SOURCE=..\..\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\Alloc.c # End Source File # Begin Source File SOURCE=..\..\Alloc.h # End Source File # Begin Source File SOURCE=..\..\Compiler.h # End Source File # Begin Source File SOURCE=..\..\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\LzFind.c # End Source File # Begin Source File SOURCE=..\..\LzFind.h # End Source File # Begin Source File SOURCE=..\..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\LzFindOpt.c # End Source File # Begin Source File SOURCE=..\..\LzHash.h # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\..\LzmaLib.h # End Source File # Begin Source File SOURCE=..\..\Precomp.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\..\Threads.c # End Source File # Begin Source File SOURCE=..\..\Threads.h # End Source File # End Target # End Project tmp41wklro_/C/Util/LzmaLib/LzmaLib.dsw0000444000175000001440000000103110764742320020643 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/C/Util/LzmaLib/LzmaLibExports.c0000444000175000001440000000063014401145220021645 0ustar nabijaczleweliusers/* LzmaLibExports.c -- LZMA library DLL Entry point 2023-03-05 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "../../7zWindows.h" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved); BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { UNUSED_VAR(hInstance) UNUSED_VAR(dwReason) UNUSED_VAR(lpReserved) return TRUE; } tmp41wklro_/C/Util/LzmaLib/makefile0000444000175000001440000000165014577002440020277 0ustar nabijaczleweliusersMY_STATIC_LINK=1 SLIB = sLZMA.lib PROG = LZMA.dll SLIBPATH = $O\$(SLIB) DEF_FILE = LzmaLib.def CFLAGS = $(CFLAGS) \ LIB_OBJS = \ $O\LzmaLibExports.obj \ C_OBJS = \ $O\Alloc.obj \ $O\CpuArch.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzmaLib.obj \ $O\Threads.obj \ !include "../../../CPP/7zip/LzFindOpt.mak" !include "../../../CPP/7zip/LzmaDec.mak" OBJS = \ $O\Precomp.obj \ $(LIB_OBJS) \ $(C_OBJS) \ $(ASM_OBJS) \ $O\resource.res !include "../../../CPP/Build.mak" $(SLIBPATH): $O $(OBJS) lib -out:$(SLIBPATH) $(OBJS) $(LIBS) MAK_SINGLE_FILE = 1 $O\Precomp.obj: Precomp.c $(CCOMPL_PCH) !IFDEF MAK_SINGLE_FILE $(LIB_OBJS): $(*B).c $(CCOMPL_USE) $(C_OBJS): ../../$(*B).c $(CCOMPL_USE) !ELSE {.}.c{$O}.obj:: $(CCOMPLB_USE) {../../../C}.c{$O}.obj:: $(CCOMPLB_USE) !ENDIF !include "../../Asm_c.mak" tmp41wklro_/C/Util/LzmaLib/Precomp.c0000444000175000001440000000013512100022440020323 0ustar nabijaczleweliusers/* Precomp.c -- StdAfx 2013-01-21 : Igor Pavlov : Public domain */ #include "Precomp.h" tmp41wklro_/C/Util/LzmaLib/Precomp.h0000444000175000001440000000046614553671000020357 0ustar nabijaczleweliusers/* Precomp.h -- Precomp 2024-01-23 : Igor Pavlov : Public domain */ // #ifndef ZIP7_INC_PRECOMP_LOC_H // #define ZIP7_INC_PRECOMP_LOC_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Precomp.h" // #endif tmp41wklro_/C/Util/LzmaLib/resource.rc0000444000175000001440000000011611553072652020753 0ustar nabijaczleweliusers#include "../../7zVersion.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") tmp41wklro_/C/Util/SfxSetup/0000700000175000001440000000000014706260545017022 5ustar nabijaczleweliuserstmp41wklro_/C/Util/SfxSetup/makefile0000444000175000001440000000134514577002440020527 0ustar nabijaczleweliusersPROG = 7zS2.sfx MY_FIXED = 1 CFLAGS = $(CFLAGS) \ -DZ7_EXTRACT_ONLY \ C_OBJS = \ $O\7zAlloc.obj \ $O\7zArcIn.obj \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zFile.obj \ $O\7zDec.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ 7Z_OBJS = \ $O\SfxSetup.obj \ !include "../../../CPP/7zip/Crc.mak" # !include "../../../CPP/7zip/LzmaDec.mak" OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ $(ASM_OBJS) \ $O\resource.res !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O1) !include "../../Asm_c.mak" tmp41wklro_/C/Util/SfxSetup/makefile_con0000444000175000001440000000122714413017520021357 0ustar nabijaczleweliusersPROG = 7zS2con.sfx MY_FIXED = 1 CFLAGS = $(CFLAGS) -D_CONSOLE \ -DZ7_EXTRACT_ONLY \ C_OBJS = \ $O\7zAlloc.obj \ $O\7zArcIn.obj \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\7zCrcOpt.obj \ $O\7zFile.obj \ $O\7zDec.obj \ $O\7zStream.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ 7Z_OBJS = \ $O\SfxSetup.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O1) tmp41wklro_/C/Util/SfxSetup/Precomp.c0000444000175000001440000000013512100020406020552 0ustar nabijaczleweliusers/* Precomp.c -- StdAfx 2013-01-21 : Igor Pavlov : Public domain */ #include "Precomp.h" tmp41wklro_/C/Util/SfxSetup/Precomp.h0000444000175000001440000000046614553671000020606 0ustar nabijaczleweliusers/* Precomp.h -- Precomp 2024-01-23 : Igor Pavlov : Public domain */ // #ifndef ZIP7_INC_PRECOMP_LOC_H // #define ZIP7_INC_PRECOMP_LOC_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Precomp.h" // #endif tmp41wklro_/C/Util/SfxSetup/resource.rc0000444000175000001440000000015711553072614021205 0ustar nabijaczleweliusers#include "../../7zVersion.rc" MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") 1 ICON "setup.ico" tmp41wklro_/C/Util/SfxSetup/setup.ico0000444000175000001440000000206611453315434020664 0ustar nabijaczleweliusers è&(( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿƒ33333330{{{{{{{3·´G·DD·30{tK{D{{33·´G·´G·330{{D{{D{330··´GDD·330{DDK{{{330·······330{{{{{{{330ˆˆ€ƒ333333330ww€33?ÿÿÿÿÿ030ÿ÷€ƒ3?ÿÿÿÿÿó0ÿ÷€7÷ó?ÿÿÿÿÿó00ÿ÷€ƒ33333333ÿ÷€÷÷óÿÿÿÿÿÿó0ÿ÷€?7ˆˆÿøˆÿ3÷€ó‡ÿÿÿÿÿÿÿó÷€0‡ðÿÿDOÿð0÷€‡ÿöfOÿDD÷€‡ù±ÿÿnoÿüä÷€‡ù‘ÿÿfoÿüÄ÷€‡ÿÿÿÿÿÿÿÿÿ÷€‡ˆˆˆˆˆˆˆˆˆˆ‡€‡wwwwwwwwwww€‡DDDDDD@€‡DDDDDDGpwp€‡DDDDDDGpwp€‡DDDDDDDDDDD€‡wwwwwwwwwww€ˆˆˆˆˆˆˆˆˆˆˆˆ€ðÿðÿðÿðÿðð?ð?ð?ð?ðððàÀ€€Ààôüüüüüüüüüüüü( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿƒ3330{{{3···3{{{3ƒ333€3?ÿÿ0€ƒ÷3333€?ÿÿó?€3÷w÷3€ñfôO€ùæüO€ÿÿÿÿÿ€DDD€DDDpp€ˆˆˆˆˆ€ÀÀÀÀÀÀ€€Àààààààtmp41wklro_/C/Util/SfxSetup/SfxSetup.c0000444000175000001440000003671014554241020020752 0ustar nabijaczleweliusers/* SfxSetup.c - 7z SFX Setup 2024-01-24 : Igor Pavlov : Public domain */ #include "Precomp.h" #ifndef UNICODE #define UNICODE #endif #ifndef _UNICODE #define _UNICODE #endif #ifdef _CONSOLE #include #endif #include "../../7z.h" #include "../../7zAlloc.h" #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../CpuArch.h" #include "../../DllSecur.h" #define k_EXE_ExtIndex 2 #define kInputBufSize ((size_t)1 << 18) #define wcscat lstrcatW #define wcslen (size_t)lstrlenW #define wcscpy lstrcpyW // wcsncpy() and lstrcpynW() work differently. We don't use them. static const char * const kExts[] = { "bat" , "cmd" , "exe" , "inf" , "msi" #ifdef UNDER_CE , "cab" #endif , "html" , "htm" }; static const char * const kNames[] = { "setup" , "install" , "run" , "start" }; static unsigned FindExt(const wchar_t *s, unsigned *extLen) { unsigned len = (unsigned)wcslen(s); unsigned i; for (i = len; i > 0; i--) { if (s[i - 1] == '.') { *extLen = len - i; return i - 1; } } *extLen = 0; return len; } #define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c))) static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len) { unsigned i; for (i = 0; i < num; i++) { const char *item = items[i]; const unsigned itemLen = (unsigned)strlen(item); unsigned j; if (len != itemLen) continue; for (j = 0; j < len; j++) { const unsigned c = (Byte)item[j]; if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) break; } if (j == len) return i; } return i; } #ifdef _CONSOLE static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { UNUSED_VAR(ctrlType); return TRUE; } #endif #ifdef _CONSOLE static void PrintStr(const char *s) { fputs(s, stdout); } #endif static void PrintErrorMessage(const char *message) { #ifdef _CONSOLE PrintStr("\n7-Zip Error: "); PrintStr(message); PrintStr("\n"); #else #ifdef UNDER_CE WCHAR messageW[256 + 4]; unsigned i; for (i = 0; i < 256 && message[i] != 0; i++) messageW[i] = message[i]; messageW[i] = 0; MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR); #else MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR); #endif #endif } static WRes MyCreateDir(const WCHAR *name) { return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); } #ifdef UNDER_CE #define kBufferSize (1 << 13) #else #define kBufferSize (1 << 15) #endif #define kSignatureSearchLimit (1 << 22) static BoolInt FindSignature(CSzFile *stream, UInt64 *resPos) { Byte buf[kBufferSize]; size_t numPrevBytes = 0; *resPos = 0; for (;;) { size_t processed, pos; if (*resPos > kSignatureSearchLimit) return False; processed = kBufferSize - numPrevBytes; if (File_Read(stream, buf + numPrevBytes, &processed) != 0) return False; processed += numPrevBytes; if (processed < k7zStartHeaderSize || (processed == k7zStartHeaderSize && numPrevBytes != 0)) return False; processed -= k7zStartHeaderSize; for (pos = 0; pos <= processed; pos++) { for (; pos <= processed && buf[pos] != '7'; pos++); if (pos > processed) break; if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) { *resPos += pos; return True; } } *resPos += processed; numPrevBytes = k7zStartHeaderSize; memmove(buf, buf + processed, k7zStartHeaderSize); } } static BoolInt DoesFileOrDirExist(const WCHAR *path) { WIN32_FIND_DATAW fd; HANDLE handle; handle = FindFirstFileW(path, &fd); if (handle == INVALID_HANDLE_VALUE) return False; FindClose(handle); return True; } static WRes RemoveDirWithSubItems(WCHAR *path) { WIN32_FIND_DATAW fd; HANDLE handle; WRes res = 0; const size_t len = wcslen(path); wcscpy(path + len, L"*"); handle = FindFirstFileW(path, &fd); path[len] = L'\0'; if (handle == INVALID_HANDLE_VALUE) return GetLastError(); for (;;) { if (wcscmp(fd.cFileName, L".") != 0 && wcscmp(fd.cFileName, L"..") != 0) { wcscpy(path + len, fd.cFileName); if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { wcscat(path, WSTRING_PATH_SEPARATOR); res = RemoveDirWithSubItems(path); } else { SetFileAttributesW(path, 0); if (DeleteFileW(path) == 0) res = GetLastError(); } if (res != 0) break; } if (!FindNextFileW(handle, &fd)) { res = GetLastError(); if (res == ERROR_NO_MORE_FILES) res = 0; break; } } path[len] = L'\0'; FindClose(handle); if (res == 0) { if (!RemoveDirectoryW(path)) res = GetLastError(); } return res; } #ifdef _CONSOLE int Z7_CDECL main(void) #else int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, #ifdef UNDER_CE LPWSTR #else LPSTR #endif lpCmdLine, int nCmdShow) #endif { CFileInStream archiveStream; CLookToRead2 lookStream; CSzArEx db; SRes res = SZ_OK; ISzAlloc allocImp; ISzAlloc allocTempImp; WCHAR sfxPath[MAX_PATH + 2]; WCHAR path[MAX_PATH * 3 + 2]; #ifndef UNDER_CE WCHAR workCurDir[MAX_PATH + 32]; #endif size_t pathLen; DWORD winRes; const wchar_t *cmdLineParams; const char *errorMessage = NULL; BoolInt useShellExecute = True; DWORD exitCode = 0; LoadSecurityDlls(); #ifdef _CONSOLE SetConsoleCtrlHandler(HandlerRoutine, TRUE); #else UNUSED_VAR(hInstance) UNUSED_VAR(hPrevInstance) UNUSED_VAR(lpCmdLine) UNUSED_VAR(nCmdShow) #endif CrcGenerateTable(); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; FileInStream_CreateVTable(&archiveStream); LookToRead2_CreateVTable(&lookStream, False); lookStream.buf = NULL; winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); if (winRes == 0 || winRes > MAX_PATH) return 1; { cmdLineParams = GetCommandLineW(); #ifndef UNDER_CE { BoolInt quoteMode = False; for (;; cmdLineParams++) { const wchar_t c = *cmdLineParams; if (c == L'\"') quoteMode = !quoteMode; else if (c == 0 || (c == L' ' && !quoteMode)) break; } } #endif } { unsigned i; DWORD d; winRes = GetTempPathW(MAX_PATH, path); if (winRes == 0 || winRes > MAX_PATH) return 1; pathLen = wcslen(path); d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); for (i = 0;; i++, d += GetTickCount()) { if (i >= 100) { res = SZ_ERROR_FAIL; break; } wcscpy(path + pathLen, L"7z"); { wchar_t *s = path + wcslen(path); UInt32 value = d; unsigned k; for (k = 0; k < 8; k++) { const unsigned t = value & 0xF; value >>= 4; s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; } if (DoesFileOrDirExist(path)) continue; if (CreateDirectoryW(path, NULL)) { wcscat(path, WSTRING_PATH_SEPARATOR); pathLen = wcslen(path); break; } if (GetLastError() != ERROR_ALREADY_EXISTS) { res = SZ_ERROR_FAIL; break; } } #ifndef UNDER_CE wcscpy(workCurDir, path); #endif if (res != SZ_OK) errorMessage = "Can't create temp folder"; } if (res != SZ_OK) { if (!errorMessage) errorMessage = "Error"; PrintErrorMessage(errorMessage); return 1; } if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) { errorMessage = "can not open input file"; res = SZ_ERROR_FAIL; } else { UInt64 pos = 0; if (!FindSignature(&archiveStream.file, &pos)) res = SZ_ERROR_FAIL; else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) res = SZ_ERROR_FAIL; if (res != 0) errorMessage = "Can't find 7z archive"; } if (res == SZ_OK) { lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize); if (!lookStream.buf) res = SZ_ERROR_MEM; else { lookStream.bufSize = kInputBufSize; lookStream.realStream = &archiveStream.vt; LookToRead2_INIT(&lookStream) } } SzArEx_Init(&db); if (res == SZ_OK) { res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); } if (res == SZ_OK) { UInt32 executeFileIndex = (UInt32)(Int32)-1; UInt32 minPrice = 1 << 30; UInt32 i; UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; WCHAR *temp; if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH) { res = SZ_ERROR_FAIL; break; } temp = path + pathLen; SzArEx_GetFileNameUtf16(&db, i, (UInt16 *)temp); { res = SzArEx_Extract(&db, &lookStream.vt, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } { CSzFile outFile; size_t processedSize; size_t j; size_t nameStartPos = 0; for (j = 0; temp[j] != 0; j++) { if (temp[j] == '/') { temp[j] = 0; MyCreateDir(path); temp[j] = CHAR_PATH_SEPARATOR; nameStartPos = j + 1; } } if (SzArEx_IsDir(&db, i)) { MyCreateDir(path); continue; } else { unsigned extLen; const WCHAR *name = temp + nameStartPos; unsigned len = (unsigned)wcslen(name); const unsigned nameLen = FindExt(temp + nameStartPos, &extLen); const unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); const unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); const unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); if (minPrice > price) { minPrice = price; executeFileIndex = i; useShellExecute = (extPrice != k_EXE_ExtIndex); } if (DoesFileOrDirExist(path)) { errorMessage = "Duplicate file"; res = SZ_ERROR_FAIL; break; } if (OutFile_OpenW(&outFile, path)) { errorMessage = "Can't open output file"; res = SZ_ERROR_FAIL; break; } } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { errorMessage = "Can't write output file"; res = SZ_ERROR_FAIL; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.MTime, i)) { const CNtfsFileTime *t = db.MTime.Vals + i; FILETIME mTime; mTime.dwLowDateTime = t->Low; mTime.dwHighDateTime = t->High; SetFileTime(outFile.handle, NULL, NULL, &mTime); } #endif { const WRes res2 = File_Close(&outFile); if (res != SZ_OK) break; if (res2 != 0) { errorMessage = "Can't close output file"; res = SZ_ERROR_FAIL; break; } } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) SetFileAttributesW(path, db.Attribs.Vals[i]); #endif } } if (res == SZ_OK) { if (executeFileIndex == (UInt32)(Int32)-1) { errorMessage = "There is no file to execute"; res = SZ_ERROR_FAIL; } else { WCHAR *temp = path + pathLen; UInt32 j; SzArEx_GetFileNameUtf16(&db, executeFileIndex, (UInt16 *)temp); for (j = 0; temp[j] != 0; j++) if (temp[j] == '/') temp[j] = CHAR_PATH_SEPARATOR; } } ISzAlloc_Free(&allocImp, outBuffer); } SzArEx_Free(&db, &allocImp); ISzAlloc_Free(&allocImp, lookStream.buf); File_Close(&archiveStream.file); if (res == SZ_OK) { HANDLE hProcess = 0; #ifndef UNDER_CE WCHAR oldCurDir[MAX_PATH + 2]; oldCurDir[0] = 0; { const DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); if (needLen == 0 || needLen > MAX_PATH) oldCurDir[0] = 0; SetCurrentDirectory(workCurDir); } #endif if (useShellExecute) { SHELLEXECUTEINFO ei; UINT32 executeRes; BOOL success; memset(&ei, 0, sizeof(ei)); ei.cbSize = sizeof(ei); ei.lpFile = path; ei.fMask = SEE_MASK_NOCLOSEPROCESS #ifndef UNDER_CE | SEE_MASK_FLAG_DDEWAIT #endif /* | SEE_MASK_NO_CONSOLE */ ; if (wcslen(cmdLineParams) != 0) ei.lpParameters = cmdLineParams; ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */ success = ShellExecuteEx(&ei); executeRes = (UINT32)(UINT_PTR)ei.hInstApp; if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ res = SZ_ERROR_FAIL; else hProcess = ei.hProcess; } else { STARTUPINFOW si; PROCESS_INFORMATION pi; WCHAR cmdLine[MAX_PATH * 3]; wcscpy(cmdLine, path); wcscat(cmdLine, cmdLineParams); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) res = SZ_ERROR_FAIL; else { CloseHandle(pi.hThread); hProcess = pi.hProcess; } } if (hProcess != 0) { WaitForSingleObject(hProcess, INFINITE); if (!GetExitCodeProcess(hProcess, &exitCode)) exitCode = 1; CloseHandle(hProcess); } #ifndef UNDER_CE SetCurrentDirectory(oldCurDir); #endif } path[pathLen] = L'\0'; RemoveDirWithSubItems(path); if (res == SZ_OK) return (int)exitCode; { if (res == SZ_ERROR_UNSUPPORTED) errorMessage = "Decoder doesn't support this archive"; else if (res == SZ_ERROR_MEM) errorMessage = "Can't allocate required memory"; else if (res == SZ_ERROR_CRC) errorMessage = "CRC error"; else { if (!errorMessage) errorMessage = "ERROR"; } if (errorMessage) PrintErrorMessage(errorMessage); } return 1; } tmp41wklro_/C/Util/SfxSetup/SfxSetup.dsp0000444000175000001440000001347012724260125021320 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 CFG=SfxSetup - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "SfxSetup.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "SfxSetup - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 !ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "SfxSetup - Win32 Release" # Name "SfxSetup - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7z.h # End Source File # Begin Source File SOURCE=..\..\7zAlloc.c # End Source File # Begin Source File SOURCE=..\..\7zAlloc.h # End Source File # Begin Source File SOURCE=..\..\7zArcIn.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zCrcOpt.c # End Source File # Begin Source File SOURCE=..\..\7zDec.c # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.c # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\BraIA64.c # End Source File # Begin Source File SOURCE=..\..\CpuArch.c # End Source File # Begin Source File SOURCE=..\..\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\Delta.c # End Source File # Begin Source File SOURCE=..\..\Delta.h # End Source File # Begin Source File SOURCE=..\..\DllSecur.c # End Source File # Begin Source File SOURCE=..\..\DllSecur.h # End Source File # Begin Source File SOURCE=..\..\Lzma2Dec.c # End Source File # Begin Source File SOURCE=..\..\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\Precomp.c # ADD CPP /Yc"Precomp.h" # End Source File # Begin Source File SOURCE=.\Precomp.h # End Source File # End Group # Begin Source File SOURCE=.\SfxSetup.c # End Source File # End Target # End Project tmp41wklro_/C/Util/SfxSetup/SfxSetup.dsw0000444000175000001440000000103311453524721021322 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/C/var_clang.mak0000444000175000001440000000022714042243601016746 0ustar nabijaczleweliusersPLATFORM= O=b/c IS_X64= IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM= CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/var_clang_arm64.mak0000444000175000001440000000031014567602040017760 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/c_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= MY_ARCH= USE_ASM=1 ASM_FLAGS=-Wno-unused-macros CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/var_clang_x64.mak0000444000175000001440000000025014055220776017457 0ustar nabijaczleweliusersPLATFORM=x64 O=b/c_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/var_clang_x86.mak0000444000175000001440000000025414055220776017467 0ustar nabijaczleweliusersPLATFORM=x86 O=b/c_$(PLATFORM) IS_X64= IS_X86=1 IS_ARM64= CROSS_COMPILE= MY_ARCH=-m32 USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/var_gcc.mak0000444000175000001440000000024314042243561016421 0ustar nabijaczleweliusersPLATFORM= O=b/g IS_X64= IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM= CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ # -march=armv8-a+crc+crypto tmp41wklro_/C/var_gcc_arm64.mak0000444000175000001440000000030714042243001017420 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/g_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= MY_ARCH=-mtune=cortex-a53 USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ # -march=armv8-a+crc+crypto tmp41wklro_/C/var_gcc_x64.mak0000444000175000001440000000022514042243020017110 0ustar nabijaczleweliusersPLATFORM=x64 O=b/g_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ tmp41wklro_/C/var_gcc_x86.mak0000444000175000001440000000023114055220776017132 0ustar nabijaczleweliusersPLATFORM=x86 O=b/g_$(PLATFORM) IS_X64= IS_X86=1 IS_ARM64= CROSS_COMPILE= MY_ARCH=-m32 USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ tmp41wklro_/C/var_mac_arm64.mak0000444000175000001440000000026514042243072017437 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/m_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= MY_ARCH=-arch arm64 USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/var_mac_x64.mak0000444000175000001440000000026314042243132017122 0ustar nabijaczleweliusersPLATFORM=x64 O=b/m_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH=-arch x86_64 USE_ASM= CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/C/warn_clang.mak0000444000175000001440000000005314425357320017133 0ustar nabijaczleweliusersCFLAGS_WARN = -Weverything -Wfatal-errors tmp41wklro_/C/warn_clang_mac.mak0000444000175000001440000000011214424455320017745 0ustar nabijaczleweliusersCFLAGS_WARN = -Weverything -Wfatal-errors -Wno-poison-system-directories tmp41wklro_/C/warn_gcc.mak0000444000175000001440000000177514055220776016622 0ustar nabijaczleweliusersCFLAGS_WARN_GCC_4_5 = \ CFLAGS_WARN_GCC_6 = \ -Waddress \ -Waggressive-loop-optimizations \ -Wattributes \ -Wbool-compare \ -Wcast-align \ -Wcomment \ -Wdiv-by-zero \ -Wduplicated-cond \ -Wformat-contains-nul \ -Winit-self \ -Wint-to-pointer-cast \ -Wunused \ -Wunused-macros \ # -Wno-strict-aliasing CFLAGS_WARN_GCC_9 = \ -Waddress \ -Waddress-of-packed-member \ -Waggressive-loop-optimizations \ -Wattributes \ -Wbool-compare \ -Wbool-operation \ -Wcast-align \ -Wcast-align=strict \ -Wcomment \ -Wdangling-else \ -Wdiv-by-zero \ -Wduplicated-branches \ -Wduplicated-cond \ -Wformat-contains-nul \ -Wimplicit-fallthrough=5 \ -Winit-self \ -Wint-in-bool-context \ -Wint-to-pointer-cast \ -Wunused \ -Wunused-macros \ -Wconversion \ # -Wno-sign-conversion \ CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ -Wno-strict-aliasing \ CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) \ # $(CFLAGS_WARN_GCC_PPMD_UNALIGNED) tmp41wklro_/C/Xz.c0000444000175000001440000000377114570276360015112 0ustar nabijaczleweliusers/* Xz.c - Xz 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "7zCrc.h" #include "CpuArch.h" #include "Xz.h" #include "XzCrc64.h" const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; /* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */ unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) { unsigned i = 0; do { buf[i++] = (Byte)((v & 0x7F) | 0x80); v >>= 7; } while (v != 0); buf[(size_t)i - 1] &= 0x7F; return i; } void Xz_Construct(CXzStream *p) { p->numBlocks = 0; p->blocks = NULL; p->flags = 0; } void Xz_Free(CXzStream *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->blocks); p->numBlocks = 0; p->blocks = NULL; } unsigned XzFlags_GetCheckSize(CXzStreamFlags f) { unsigned t = XzFlags_GetCheckType(f); return (t == 0) ? 0 : ((unsigned)4 << ((t - 1) / 3)); } void XzCheck_Init(CXzCheck *p, unsigned mode) { p->mode = mode; switch (mode) { case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; default: break; } } void XzCheck_Update(CXzCheck *p, const void *data, size_t size) { switch (p->mode) { case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; default: break; } } int XzCheck_Final(CXzCheck *p, Byte *digest) { switch (p->mode) { case XZ_CHECK_CRC32: SetUi32(digest, CRC_GET_DIGEST(p->crc)) break; case XZ_CHECK_CRC64: { int i; UInt64 v = CRC64_GET_DIGEST(p->crc64); for (i = 0; i < 8; i++, v >>= 8) digest[i] = (Byte)(v & 0xFF); break; } case XZ_CHECK_SHA256: Sha256_Final(&p->sha, digest); break; default: return 0; } return 1; } tmp41wklro_/C/Xz.h0000444000175000001440000004040614554735340015113 0ustar nabijaczleweliusers/* Xz.h - Xz interface 2024-01-26 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_XZ_H #define ZIP7_INC_XZ_H #include "Sha256.h" #include "Delta.h" EXTERN_C_BEGIN #define XZ_ID_Subblock 1 #define XZ_ID_Delta 3 #define XZ_ID_X86 4 #define XZ_ID_PPC 5 #define XZ_ID_IA64 6 #define XZ_ID_ARM 7 #define XZ_ID_ARMT 8 #define XZ_ID_SPARC 9 #define XZ_ID_ARM64 0xa #define XZ_ID_RISCV 0xb #define XZ_ID_LZMA2 0x21 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); unsigned Xz_WriteVarInt(Byte *buf, UInt64 v); /* ---------- xz block ---------- */ #define XZ_BLOCK_HEADER_SIZE_MAX 1024 #define XZ_NUM_FILTERS_MAX 4 #define XZ_BF_NUM_FILTERS_MASK 3 #define XZ_BF_PACK_SIZE (1 << 6) #define XZ_BF_UNPACK_SIZE (1 << 7) #define XZ_FILTER_PROPS_SIZE_MAX 20 typedef struct { UInt64 id; UInt32 propsSize; Byte props[XZ_FILTER_PROPS_SIZE_MAX]; } CXzFilter; typedef struct { UInt64 packSize; UInt64 unpackSize; Byte flags; CXzFilter filters[XZ_NUM_FILTERS_MAX]; } CXzBlock; #define XzBlock_GetNumFilters(p) (((unsigned)(p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) #define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) #define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) #define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0) SRes XzBlock_Parse(CXzBlock *p, const Byte *header); SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes); /* ---------- xz stream ---------- */ #define XZ_SIG_SIZE 6 #define XZ_FOOTER_SIG_SIZE 2 extern const Byte XZ_SIG[XZ_SIG_SIZE]; /* extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; */ #define XZ_FOOTER_SIG_0 'Y' #define XZ_FOOTER_SIG_1 'Z' #define XZ_STREAM_FLAGS_SIZE 2 #define XZ_STREAM_CRC_SIZE 4 #define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE) #define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4) #define XZ_CHECK_MASK 0xF #define XZ_CHECK_NO 0 #define XZ_CHECK_CRC32 1 #define XZ_CHECK_CRC64 4 #define XZ_CHECK_SHA256 10 typedef struct { unsigned mode; UInt32 crc; UInt64 crc64; CSha256 sha; } CXzCheck; void XzCheck_Init(CXzCheck *p, unsigned mode); void XzCheck_Update(CXzCheck *p, const void *data, size_t size); int XzCheck_Final(CXzCheck *p, Byte *digest); typedef UInt16 CXzStreamFlags; #define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK) #define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK) #define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32) unsigned XzFlags_GetCheckSize(CXzStreamFlags f); SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf); SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream); typedef struct { UInt64 unpackSize; UInt64 totalSize; } CXzBlockSizes; typedef struct { CXzStreamFlags flags; // Byte _pad[6]; size_t numBlocks; CXzBlockSizes *blocks; UInt64 startOffset; } CXzStream; void Xz_Construct(CXzStream *p); void Xz_Free(CXzStream *p, ISzAllocPtr alloc); #define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) UInt64 Xz_GetUnpackSize(const CXzStream *p); UInt64 Xz_GetPackSize(const CXzStream *p); typedef struct { size_t num; size_t numAllocated; CXzStream *streams; } CXzs; void Xzs_Construct(CXzs *p); void Xzs_Free(CXzs *p, ISzAllocPtr alloc); SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc); UInt64 Xzs_GetNumBlocks(const CXzs *p); UInt64 Xzs_GetUnpackSize(const CXzs *p); // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder typedef enum { CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ CODER_STATUS_NOT_FINISHED, /* stream was not finished */ CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ } ECoderStatus; // ECoderFinishMode values are identical to ELzmaFinishMode typedef enum { CODER_FINISH_ANY, /* finish at any point */ CODER_FINISH_END /* block must be finished at the end */ } ECoderFinishMode; typedef struct { void *p; // state object; void (*Free)(void *p, ISzAllocPtr alloc); SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc); void (*Init)(void *p); SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, // int *wasFinished, ECoderStatus *status); SizeT (*Filter)(void *p, Byte *data, SizeT size); } IStateCoder; typedef struct { UInt32 methodId; UInt32 delta; UInt32 ip; UInt32 X86_State; Byte delta_State[DELTA_STATE_SIZE]; } CXzBcFilterStateBase; typedef SizeT (*Xz_Func_BcFilterStateBase_Filter)(CXzBcFilterStateBase *p, Byte *data, SizeT size); SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc); #define MIXCODER_NUM_FILTERS_MAX 4 typedef struct { ISzAllocPtr alloc; Byte *buf; unsigned numCoders; Byte *outBuf; size_t outBufSize; size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode) BoolInt wasFinished; SRes res; ECoderStatus status; // BoolInt SingleBufMode; int finished[MIXCODER_NUM_FILTERS_MAX - 1]; size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; SRes results[MIXCODER_NUM_FILTERS_MAX]; IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; } CMixCoder; typedef enum { XZ_STATE_STREAM_HEADER, XZ_STATE_STREAM_INDEX, XZ_STATE_STREAM_INDEX_CRC, XZ_STATE_STREAM_FOOTER, XZ_STATE_STREAM_PADDING, XZ_STATE_BLOCK_HEADER, XZ_STATE_BLOCK, XZ_STATE_BLOCK_FOOTER } EXzState; typedef struct { EXzState state; unsigned pos; unsigned alignPos; unsigned indexPreSize; CXzStreamFlags streamFlags; unsigned blockHeaderSize; UInt64 packSize; UInt64 unpackSize; UInt64 numBlocks; // number of finished blocks in current stream UInt64 indexSize; UInt64 indexPos; UInt64 padSize; UInt64 numStartedStreams; UInt64 numFinishedStreams; UInt64 numTotalBlocks; UInt32 crc; CMixCoder decoder; CXzBlock block; CXzCheck check; CSha256 sha; BoolInt parseMode; BoolInt headerParsedOk; BoolInt decodeToStreamSignature; unsigned decodeOnlyOneBlock; Byte *outBuf; size_t outBufSize; size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked Byte shaDigest[SHA256_DIGEST_SIZE]; Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; } CXzUnpacker; /* alloc : aligned for cache line allocation is better */ void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc); void XzUnpacker_Init(CXzUnpacker *p); void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize); void XzUnpacker_Free(CXzUnpacker *p); /* XzUnpacker The sequence for decoding functions: { XzUnpacker_Construct() [Decoding_Calls] XzUnpacker_Free() } [Decoding_Calls] There are 3 types of interfaces for [Decoding_Calls] calls: Interface-1 : Partial output buffers: { XzUnpacker_Init() for() { XzUnpacker_Code(); } XzUnpacker_IsStreamWasFinished() } Interface-2 : Direct output buffer: Use it, if you know exact size of decoded data, and you need whole xz unpacked data in one output buffer. xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode. { XzUnpacker_Init() XzUnpacker_SetOutBufMode(); // to set output buffer and size for() { XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code() } XzUnpacker_IsStreamWasFinished() } Interface-3 : Direct output buffer : One call full decoding It unpacks whole input buffer to output buffer in one call. It uses Interface-2 internally. { XzUnpacker_CodeFull() XzUnpacker_IsStreamWasFinished() } */ /* finishMode: It has meaning only if the decoding reaches output limit (*destLen). CODER_FINISH_ANY - use smallest number of input bytes CODER_FINISH_END - read EndOfStream marker after decoding Returns: SZ_OK status: CODER_STATUS_NOT_FINISHED, CODER_STATUS_NEEDS_MORE_INPUT - the decoder can return it in two cases: 1) it needs more input data to finish current xz stream 2) xz stream was finished successfully. But the decoder supports multiple concatented xz streams. So it expects more input data for new xz streams. Call XzUnpacker_IsStreamWasFinished() to check that latest xz stream was finished successfully. SZ_ERROR_MEM - Memory allocation error SZ_ERROR_DATA - Data error SZ_ERROR_UNSUPPORTED - Unsupported method or method properties SZ_ERROR_CRC - CRC error // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: - xz Stream Signature failure - CRC32 of xz Stream Header is failed - The size of Stream padding is not multiple of four bytes. It's possible to get that error, if xz stream was finished and the stream contains some another data. In that case you can call XzUnpacker_GetExtraSize() function to get real size of xz stream. */ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcFinished, ECoderFinishMode finishMode, ECoderStatus *status); SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status); /* If you decode full xz stream(s), then you can call XzUnpacker_IsStreamWasFinished() after successful XzUnpacker_CodeFull() or after last call of XzUnpacker_Code(). */ BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p); /* XzUnpacker_GetExtraSize() returns then number of unconfirmed bytes, if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state. These bytes can be some data after xz archive, or it can be start of new xz stream. Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of xz stream in two cases, if XzUnpacker_Code() returns: res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT res == SZ_ERROR_NO_ARCHIVE */ UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p); /* for random block decoding: XzUnpacker_Init(); set CXzUnpacker::streamFlags XzUnpacker_PrepareToRandomBlockDecoding() loop { XzUnpacker_Code() XzUnpacker_IsBlockFinished() } */ void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p); BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p); #define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags)) /* ---- Single-Thread and Multi-Thread xz Decoding with Input/Output Streams ---- */ /* if (CXzDecMtProps::numThreads > 1), the decoder can try to use Multi-Threading. The decoder analyses xz block header, and if there are pack size and unpack size values stored in xz block header, the decoder reads compressed data of block to internal buffers, and then it can start parallel decoding, if there are another blocks. The decoder can switch back to Single-Thread decoding after some conditions. The sequence of calls for xz decoding with in/out Streams: { XzDecMt_Create() XzDecMtProps_Init(XzDecMtProps) to set default values of properties // then you can change some XzDecMtProps parameters with required values // here you can set the number of threads and (memUseMax) - the maximum Memory usage for multithreading decoding. for() { XzDecMt_Decode() // one call per one file } XzDecMt_Destroy() } */ typedef struct { size_t inBufSize_ST; // size of input buffer for Single-Thread decoding size_t outStep_ST; // size of output buffer for Single-Thread decoding BoolInt ignoreErrors; // if set to 1, the decoder can ignore some errors and it skips broken parts of data. #ifndef Z7_ST unsigned numThreads; // the number of threads for Multi-Thread decoding. if (umThreads == 1) it will use Single-thread decoding size_t inBufSize_MT; // size of small input data buffers for Multi-Thread decoding. Big number of such small buffers can be created size_t memUseMax; // the limit of total memory usage for Multi-Thread decoding. // it's recommended to set (memUseMax) manually to value that is smaller of total size of RAM in computer. #endif } CXzDecMtProps; void XzDecMtProps_Init(CXzDecMtProps *p); typedef struct CXzDecMt CXzDecMt; typedef CXzDecMt * CXzDecMtHandle; // Z7_DECLARE_HANDLE(CXzDecMtHandle) /* alloc : XzDecMt uses CAlignOffsetAlloc internally for addresses allocated by (alloc). allocMid : for big allocations, aligned allocation is better */ CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); void XzDecMt_Destroy(CXzDecMtHandle p); typedef struct { Byte UnpackSize_Defined; Byte NumStreams_Defined; Byte NumBlocks_Defined; Byte DataAfterEnd; // there are some additional data after good xz streams, and that data is not new xz stream. Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data UInt64 InSize; // pack size processed. That value doesn't include the data after // end of xz stream, if that data was not correct UInt64 OutSize; UInt64 NumStreams; UInt64 NumBlocks; SRes DecodeRes; // the error code of xz streams data decoding SRes ReadRes; // error code from ISeqInStream:Read() SRes ProgressRes; // error code from ICompressProgress:Progress() SRes CombinedRes; // Combined result error code that shows main rusult // = S_OK, if there is no error. // but check also (DataAfterEnd) that can show additional minor errors. SRes CombinedRes_Type; // = SZ_ERROR_READ, if error from ISeqInStream // = SZ_ERROR_PROGRESS, if error from ICompressProgress // = SZ_ERROR_WRITE, if error from ISeqOutStream // = SZ_ERROR_* codes for decoding } CXzStatInfo; void XzStatInfo_Clear(CXzStatInfo *p); /* XzDecMt_Decode() SRes: it's combined decoding result. It also is equal to stat->CombinedRes. SZ_OK - no error check also output value in (stat->DataAfterEnd) that can show additional possible error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_NO_ARCHIVE - is not xz archive SZ_ERROR_ARCHIVE - Headers error SZ_ERROR_DATA - Data Error SZ_ERROR_UNSUPPORTED - Unsupported method or method properties SZ_ERROR_CRC - CRC Error SZ_ERROR_INPUT_EOF - it needs more input data SZ_ERROR_WRITE - ISeqOutStream error (SZ_ERROR_READ) - ISeqInStream errors (SZ_ERROR_PROGRESS) - ICompressProgress errors // SZ_ERROR_THREAD - error in multi-threading functions MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function */ SRes XzDecMt_Decode(CXzDecMtHandle p, const CXzDecMtProps *props, const UInt64 *outDataSize, // NULL means undefined int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished ISeqOutStreamPtr outStream, // Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, // const Byte *inData, size_t inDataSize, CXzStatInfo *stat, // out: decoding results and statistics int *isMT, // out: 0 means that ST (Single-Thread) version was used // 1 means that MT (Multi-Thread) version was used ICompressProgressPtr progress); EXTERN_C_END #endif tmp41wklro_/C/XzCrc64.c0000444000175000001440000000715114534564440015707 0ustar nabijaczleweliusers/* XzCrc64.c -- CRC64 calculation 2023-12-08 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "XzCrc64.h" #include "CpuArch.h" #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) // for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu // #define Z7_CRC64_DEBUG_BE #ifdef Z7_CRC64_DEBUG_BE #undef MY_CPU_LE #define MY_CPU_BE #endif #ifdef Z7_CRC64_NUM_TABLES #define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES #else #define Z7_CRC64_NUM_TABLES_USE 12 #endif #if Z7_CRC64_NUM_TABLES_USE < 1 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES #endif #if Z7_CRC64_NUM_TABLES_USE != 1 #ifndef MY_CPU_BE #define FUNC_NAME_LE_2(s) XzCrc64UpdateT ## s #define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s) #define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC64_NUM_TABLES_USE) UInt64 Z7_FASTCALL FUNC_NAME_LE (UInt64 v, const void *data, size_t size, const UInt64 *table); #endif #ifndef MY_CPU_LE #define FUNC_NAME_BE_2(s) XzCrc64UpdateBeT ## s #define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s) #define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC64_NUM_TABLES_USE) UInt64 Z7_FASTCALL FUNC_NAME_BE (UInt64 v, const void *data, size_t size, const UInt64 *table); #endif #if defined(MY_CPU_LE) #define FUNC_REF FUNC_NAME_LE #elif defined(MY_CPU_BE) #define FUNC_REF FUNC_NAME_BE #else #define FUNC_REF g_Crc64Update static UInt64 (Z7_FASTCALL *FUNC_REF)(UInt64 v, const void *data, size_t size, const UInt64 *table); #endif #endif MY_ALIGN(64) static UInt64 g_Crc64Table[256 * Z7_CRC64_NUM_TABLES_USE]; UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size) { #if Z7_CRC64_NUM_TABLES_USE == 1 #define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) const UInt64 *table = g_Crc64Table; const Byte *p = (const Byte *)data; const Byte *lim = p + size; for (; p != lim; p++) v = CRC64_UPDATE_BYTE_2(v, *p); return v; #undef CRC64_UPDATE_BYTE_2 #else return FUNC_REF (v, data, size, g_Crc64Table); #endif } Z7_NO_INLINE void Z7_FASTCALL Crc64GenerateTable(void) { unsigned i; for (i = 0; i < 256; i++) { UInt64 r = i; unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); g_Crc64Table[i] = r; } #if Z7_CRC64_NUM_TABLES_USE != 1 #if 1 || 1 && defined(MY_CPU_X86) // low register count for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i++) { const UInt64 r0 = g_Crc64Table[(size_t)i]; g_Crc64Table[(size_t)i + 256] = g_Crc64Table[(Byte)r0] ^ (r0 >> 8); } #else for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i += 2) { UInt64 r0 = g_Crc64Table[(size_t)(i) ]; UInt64 r1 = g_Crc64Table[(size_t)(i) + 1]; r0 = g_Crc64Table[(Byte)r0] ^ (r0 >> 8); r1 = g_Crc64Table[(Byte)r1] ^ (r1 >> 8); g_Crc64Table[(size_t)i + 256 ] = r0; g_Crc64Table[(size_t)i + 256 + 1] = r1; } #endif #ifndef MY_CPU_LE { #ifndef MY_CPU_BE UInt32 k = 1; if (*(const Byte *)&k == 1) FUNC_REF = FUNC_NAME_LE; else #endif { #ifndef MY_CPU_BE FUNC_REF = FUNC_NAME_BE; #endif for (i = 0; i < 256 * Z7_CRC64_NUM_TABLES_USE; i++) { const UInt64 x = g_Crc64Table[i]; g_Crc64Table[i] = Z7_BSWAP64(x); } } } #endif // ndef MY_CPU_LE #endif // Z7_CRC64_NUM_TABLES_USE != 1 } #undef kCrc64Poly #undef Z7_CRC64_NUM_TABLES_USE #undef FUNC_REF #undef FUNC_NAME_LE_2 #undef FUNC_NAME_LE_1 #undef FUNC_NAME_LE #undef FUNC_NAME_BE_2 #undef FUNC_NAME_BE_1 #undef FUNC_NAME_BE tmp41wklro_/C/XzCrc64.h0000444000175000001440000000122514534564440015710 0ustar nabijaczleweliusers/* XzCrc64.h -- CRC64 calculation 2023-12-08 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_XZ_CRC64_H #define ZIP7_INC_XZ_CRC64_H #include #include "7zTypes.h" EXTERN_C_BEGIN // extern UInt64 g_Crc64Table[]; void Z7_FASTCALL Crc64GenerateTable(void); #define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) #define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) // #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size); // UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size); EXTERN_C_END #endif tmp41wklro_/C/XzCrc64Opt.c0000444000175000001440000001702214534546400016364 0ustar nabijaczleweliusers/* XzCrc64Opt.c -- CRC64 calculation (optimized functions) 2023-12-08 : Igor Pavlov : Public domain */ #include "Precomp.h" #include "CpuArch.h" #if !defined(Z7_CRC64_NUM_TABLES) || Z7_CRC64_NUM_TABLES > 1 // for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu // #define Z7_CRC64_DEBUG_BE #ifdef Z7_CRC64_DEBUG_BE #undef MY_CPU_LE #define MY_CPU_BE #endif #if defined(MY_CPU_64BIT) #define Z7_CRC64_USE_64BIT #endif // the value Z7_CRC64_NUM_TABLES_USE must be defined to same value as in XzCrc64.c #ifdef Z7_CRC64_NUM_TABLES #define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES #else #define Z7_CRC64_NUM_TABLES_USE 12 #endif #if Z7_CRC64_NUM_TABLES_USE % 4 || \ Z7_CRC64_NUM_TABLES_USE < 4 || \ Z7_CRC64_NUM_TABLES_USE > 4 * 4 #error Stop_Compiling_Bad_CRC64_NUM_TABLES #endif #ifndef MY_CPU_BE #define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0) #define Q64LE(n, d) \ ( (table + ((n) * 8 + 7) * 0x100)[((d) ) & 0xFF] \ ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 3 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 4 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 5 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 6 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 0) * 0x100)[((d) >> 7 * 8)] ) #define R64(a) *((const UInt64 *)(const void *)p + (a)) #else #define Q32LE(n, d) \ ( (table + ((n) * 4 + 3) * 0x100)[((d) ) & 0xFF] \ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] ) #define R32(a) *((const UInt32 *)(const void *)p + (a)) #endif #define CRC64_FUNC_PRE_LE2(step) \ UInt64 Z7_FASTCALL XzCrc64UpdateT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table) #define CRC64_FUNC_PRE_LE(step) \ CRC64_FUNC_PRE_LE2(step); \ CRC64_FUNC_PRE_LE2(step) CRC64_FUNC_PRE_LE(Z7_CRC64_NUM_TABLES_USE) { const Byte *p = (const Byte *)data; const Byte *lim; for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC64_UPDATE_BYTE_2(v, *p); lim = p + size; if (size >= Z7_CRC64_NUM_TABLES_USE) { lim -= Z7_CRC64_NUM_TABLES_USE; do { #if Z7_CRC64_NUM_TABLES_USE == 4 const UInt32 d = (UInt32)v ^ R32(0); v = (v >> 32) ^ Q32LE(0, d); #elif Z7_CRC64_NUM_TABLES_USE == 8 #ifdef Z7_CRC64_USE_64BIT v ^= R64(0); v = Q64LE(0, v); #else UInt32 v0, v1; v0 = (UInt32)v ^ R32(0); v1 = (UInt32)(v >> 32) ^ R32(1); v = Q32LE(1, v0) ^ Q32LE(0, v1); #endif #elif Z7_CRC64_NUM_TABLES_USE == 12 UInt32 w; UInt32 v0, v1; v0 = (UInt32)v ^ R32(0); v1 = (UInt32)(v >> 32) ^ R32(1); w = R32(2); v = Q32LE(0, w); v ^= Q32LE(2, v0) ^ Q32LE(1, v1); #elif Z7_CRC64_NUM_TABLES_USE == 16 #ifdef Z7_CRC64_USE_64BIT UInt64 w; UInt64 x; w = R64(1); x = Q64LE(0, w); v ^= R64(0); v = x ^ Q64LE(1, v); #else UInt32 v0, v1; UInt32 r0, r1; v0 = (UInt32)v ^ R32(0); v1 = (UInt32)(v >> 32) ^ R32(1); r0 = R32(2); r1 = R32(3); v = Q32LE(1, r0) ^ Q32LE(0, r1); v ^= Q32LE(3, v0) ^ Q32LE(2, v1); #endif #else #error Stop_Compiling_Bad_CRC64_NUM_TABLES #endif p += Z7_CRC64_NUM_TABLES_USE; } while (p <= lim); lim += Z7_CRC64_NUM_TABLES_USE; } for (; p < lim; p++) v = CRC64_UPDATE_BYTE_2(v, *p); return v; } #undef CRC64_UPDATE_BYTE_2 #undef R32 #undef R64 #undef Q32LE #undef Q64LE #undef CRC64_FUNC_PRE_LE #undef CRC64_FUNC_PRE_LE2 #endif #ifndef MY_CPU_LE #define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 56) ^ (b)] ^ ((crc) << 8)) #if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0) #define Q64BE(n, d) \ ( (table + ((n) * 8 + 0) * 0x100)[(Byte)(d)] \ ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 3 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 4 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 5 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 6 * 8) & 0xFF] \ ^ (table + ((n) * 8 + 7) * 0x100)[((d) >> 7 * 8)] ) #ifdef Z7_CRC64_DEBUG_BE #define R64BE(a) GetBe64a((const UInt64 *)(const void *)p + (a)) #else #define R64BE(a) *((const UInt64 *)(const void *)p + (a)) #endif #else #define Q32BE(n, d) \ ( (table + ((n) * 4 + 0) * 0x100)[(Byte)(d)] \ ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \ ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] ) #ifdef Z7_CRC64_DEBUG_BE #define R32BE(a) GetBe32a((const UInt32 *)(const void *)p + (a)) #else #define R32BE(a) *((const UInt32 *)(const void *)p + (a)) #endif #endif #define CRC64_FUNC_PRE_BE2(step) \ UInt64 Z7_FASTCALL XzCrc64UpdateBeT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table) #define CRC64_FUNC_PRE_BE(step) \ CRC64_FUNC_PRE_BE2(step); \ CRC64_FUNC_PRE_BE2(step) CRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE) { const Byte *p = (const Byte *)data; const Byte *lim; v = Z7_BSWAP64(v); for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++) v = CRC64_UPDATE_BYTE_2_BE(v, *p); lim = p + size; if (size >= Z7_CRC64_NUM_TABLES_USE) { lim -= Z7_CRC64_NUM_TABLES_USE; do { #if Z7_CRC64_NUM_TABLES_USE == 4 const UInt32 d = (UInt32)(v >> 32) ^ R32BE(0); v = (v << 32) ^ Q32BE(0, d); #elif Z7_CRC64_NUM_TABLES_USE == 12 const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0); const UInt32 d0 = (UInt32)(v ) ^ R32BE(1); const UInt32 w = R32BE(2); v = Q32BE(0, w); v ^= Q32BE(2, d1) ^ Q32BE(1, d0); #elif Z7_CRC64_NUM_TABLES_USE == 8 #ifdef Z7_CRC64_USE_64BIT v ^= R64BE(0); v = Q64BE(0, v); #else const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0); const UInt32 d0 = (UInt32)(v ) ^ R32BE(1); v = Q32BE(1, d1) ^ Q32BE(0, d0); #endif #elif Z7_CRC64_NUM_TABLES_USE == 16 #ifdef Z7_CRC64_USE_64BIT const UInt64 w = R64BE(1); v ^= R64BE(0); v = Q64BE(0, w) ^ Q64BE(1, v); #else const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0); const UInt32 d0 = (UInt32)(v ) ^ R32BE(1); const UInt32 w1 = R32BE(2); const UInt32 w0 = R32BE(3); v = Q32BE(1, w1) ^ Q32BE(0, w0); v ^= Q32BE(3, d1) ^ Q32BE(2, d0); #endif #elif #error Stop_Compiling_Bad_CRC64_NUM_TABLES #endif p += Z7_CRC64_NUM_TABLES_USE; } while (p <= lim); lim += Z7_CRC64_NUM_TABLES_USE; } for (; p < lim; p++) v = CRC64_UPDATE_BYTE_2_BE(v, *p); return Z7_BSWAP64(v); } #undef CRC64_UPDATE_BYTE_2_BE #undef R32BE #undef R64BE #undef Q32BE #undef Q64BE #undef CRC64_FUNC_PRE_BE #undef CRC64_FUNC_PRE_BE2 #endif #undef Z7_CRC64_NUM_TABLES_USE #endif tmp41wklro_/C/XzDec.c0000444000175000001440000021474614570267340015532 0ustar nabijaczleweliusers/* XzDec.c -- Xz Decode 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" // #include // #define XZ_DUMP /* #define XZ_DUMP */ #ifdef XZ_DUMP #include #endif // #define SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO #include #endif #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif #define PRF_STR(s) PRF(printf("\n" s "\n")) #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) #include #include #include "7zCrc.h" #include "Alloc.h" #include "Bra.h" #include "CpuArch.h" #include "Delta.h" #include "Lzma2Dec.h" // #define USE_SUBBLOCK #ifdef USE_SUBBLOCK #include "Bcj3Dec.c" #include "SbDec.h" #endif #include "Xz.h" #define XZ_CHECK_SIZE_MAX 64 #define CODER_BUF_SIZE ((size_t)1 << 17) unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) { unsigned i, limit; *value = 0; limit = (maxSize > 9) ? 9 : (unsigned)maxSize; for (i = 0; i < limit;) { Byte b = p[i]; *value |= (UInt64)(b & 0x7F) << (7 * i++); if ((b & 0x80) == 0) return (b == 0 && i != 1) ? 0 : i; } return 0; } /* ---------- XzBcFilterState ---------- */ #define BRA_BUF_SIZE (1 << 14) typedef struct { size_t bufPos; size_t bufConv; size_t bufTotal; Byte *buf; // must be aligned for 4 bytes Xz_Func_BcFilterStateBase_Filter filter_func; // int encodeMode; CXzBcFilterStateBase base; // Byte buf[BRA_BUF_SIZE]; } CXzBcFilterState; static void XzBcFilterState_Free(void *pp, ISzAllocPtr alloc) { if (pp) { CXzBcFilterState *p = ((CXzBcFilterState *)pp); ISzAlloc_Free(alloc, p->buf); ISzAlloc_Free(alloc, pp); } } static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) { CXzBcFilterStateBase *p = &((CXzBcFilterState *)pp)->base; UNUSED_VAR(alloc) p->ip = 0; if (p->methodId == XZ_ID_Delta) { if (propSize != 1) return SZ_ERROR_UNSUPPORTED; p->delta = (UInt32)props[0] + 1; } else { if (propSize == 4) { const UInt32 v = GetUi32(props); switch (p->methodId) { case XZ_ID_PPC: case XZ_ID_ARM: case XZ_ID_SPARC: case XZ_ID_ARM64: if (v & 3) return SZ_ERROR_UNSUPPORTED; break; case XZ_ID_ARMT: case XZ_ID_RISCV: if (v & 1) return SZ_ERROR_UNSUPPORTED; break; case XZ_ID_IA64: if (v & 0xf) return SZ_ERROR_UNSUPPORTED; break; default: break; } p->ip = v; } else if (propSize != 0) return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } static void XzBcFilterState_Init(void *pp) { CXzBcFilterState *p = ((CXzBcFilterState *)pp); p->bufPos = p->bufConv = p->bufTotal = 0; p->base.X86_State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; if (p->base.methodId == XZ_ID_Delta) Delta_Init(p->base.delta_State); } static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] = { Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC), Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64), Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM), Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT), Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC), Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64), Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV) }; static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size) { switch (p->methodId) { case XZ_ID_Delta: Delta_Decode(p->delta_State, p->delta, data, size); break; case XZ_ID_X86: size = (SizeT)(z7_BranchConvSt_X86_Dec(data, size, p->ip, &p->X86_State) - data); break; default: if (p->methodId >= XZ_ID_PPC) { const UInt32 i = p->methodId - XZ_ID_PPC; if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Dec)) size = (SizeT)(g_Funcs_BranchConv_RISC_Dec[i](data, size, p->ip) - data); } break; } p->ip += (UInt32)size; return size; } static SizeT XzBcFilterState_Filter(void *pp, Byte *data, SizeT size) { CXzBcFilterState *p = ((CXzBcFilterState *)pp); return p->filter_func(&p->base, data, size); } static SRes XzBcFilterState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, // int *wasFinished ECoderStatus *status) { CXzBcFilterState *p = ((CXzBcFilterState *)pp); SizeT destRem = *destLen; SizeT srcRem = *srcLen; UNUSED_VAR(finishMode) *destLen = 0; *srcLen = 0; // *wasFinished = False; *status = CODER_STATUS_NOT_FINISHED; while (destRem != 0) { { size_t size = p->bufConv - p->bufPos; if (size) { if (size > destRem) size = destRem; memcpy(dest, p->buf + p->bufPos, size); p->bufPos += size; *destLen += size; dest += size; destRem -= size; continue; } } p->bufTotal -= p->bufPos; memmove(p->buf, p->buf + p->bufPos, p->bufTotal); p->bufPos = 0; p->bufConv = 0; { size_t size = BRA_BUF_SIZE - p->bufTotal; if (size > srcRem) size = srcRem; memcpy(p->buf + p->bufTotal, src, size); *srcLen += size; src += size; srcRem -= size; p->bufTotal += size; } if (p->bufTotal == 0) break; p->bufConv = p->filter_func(&p->base, p->buf, p->bufTotal); if (p->bufConv == 0) { if (!srcWasFinished) break; p->bufConv = p->bufTotal; } } if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) { *status = CODER_STATUS_FINISHED_WITH_MARK; // *wasFinished = 1; } return SZ_OK; } #define XZ_IS_SUPPORTED_FILTER_ID(id) \ ((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV) SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc) { CXzBcFilterState *decoder; if (!XZ_IS_SUPPORTED_FILTER_ID(id)) return SZ_ERROR_UNSUPPORTED; decoder = (CXzBcFilterState *)p->p; if (!decoder) { decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState)); if (!decoder) return SZ_ERROR_MEM; decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE); if (!decoder->buf) { ISzAlloc_Free(alloc, decoder); return SZ_ERROR_MEM; } p->p = decoder; p->Free = XzBcFilterState_Free; p->SetProps = XzBcFilterState_SetProps; p->Init = XzBcFilterState_Init; p->Code2 = XzBcFilterState_Code2; p->Filter = XzBcFilterState_Filter; decoder->filter_func = func; } decoder->base.methodId = (UInt32)id; // decoder->encodeMode = encodeMode; return SZ_OK; } /* ---------- SbState ---------- */ #ifdef USE_SUBBLOCK static void SbState_Free(void *pp, ISzAllocPtr alloc) { CSbDec *p = (CSbDec *)pp; SbDec_Free(p); ISzAlloc_Free(alloc, pp); } static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) { UNUSED_VAR(pp) UNUSED_VAR(props) UNUSED_VAR(alloc) return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; } static void SbState_Init(void *pp) { SbDec_Init((CSbDec *)pp); } static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, // int *wasFinished ECoderStatus *status) { CSbDec *p = (CSbDec *)pp; SRes res; UNUSED_VAR(srcWasFinished) p->dest = dest; p->destLen = *destLen; p->src = src; p->srcLen = *srcLen; p->finish = finishMode; /* change it */ res = SbDec_Decode((CSbDec *)pp); *destLen -= p->destLen; *srcLen -= p->srcLen; // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ *status = (*destLen == 0 && *srcLen == 0) ? CODER_STATUS_FINISHED_WITH_MARK : CODER_STATUS_NOT_FINISHED; return res; } static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc) { CSbDec *decoder = (CSbDec *)p->p; if (!decoder) { decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec)); if (!decoder) return SZ_ERROR_MEM; p->p = decoder; p->Free = SbState_Free; p->SetProps = SbState_SetProps; p->Init = SbState_Init; p->Code2 = SbState_Code2; p->Filter = NULL; } SbDec_Construct(decoder); SbDec_SetAlloc(decoder, alloc); return SZ_OK; } #endif /* ---------- Lzma2 ---------- */ typedef struct { CLzma2Dec decoder; BoolInt outBufMode; } CLzma2Dec_Spec; static void Lzma2State_Free(void *pp, ISzAllocPtr alloc) { CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; if (p->outBufMode) Lzma2Dec_FreeProbs(&p->decoder, alloc); else Lzma2Dec_Free(&p->decoder, alloc); ISzAlloc_Free(alloc, pp); } static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) { if (propSize != 1) return SZ_ERROR_UNSUPPORTED; { CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; if (p->outBufMode) return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc); else return Lzma2Dec_Allocate(&p->decoder, props[0], alloc); } } static void Lzma2State_Init(void *pp) { Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder); } /* if (outBufMode), then (dest) is not used. Use NULL. Data is unpacked to (spec->decoder.decoder.dic) output buffer. */ static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, // int *wasFinished, ECoderStatus *status) { CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp; ELzmaStatus status2; /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ SRes res; UNUSED_VAR(srcWasFinished) if (spec->outBufMode) { SizeT dicPos = spec->decoder.decoder.dicPos; SizeT dicLimit = dicPos + *destLen; res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2); *destLen = spec->decoder.decoder.dicPos - dicPos; } else res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2); // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK); // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder *status = (ECoderStatus)status2; return res; } static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc) { CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; if (!spec) { spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec)); if (!spec) return SZ_ERROR_MEM; p->p = spec; p->Free = Lzma2State_Free; p->SetProps = Lzma2State_SetProps; p->Init = Lzma2State_Init; p->Code2 = Lzma2State_Code2; p->Filter = NULL; Lzma2Dec_CONSTRUCT(&spec->decoder) } spec->outBufMode = False; if (outBuf) { spec->outBufMode = True; spec->decoder.decoder.dic = outBuf; spec->decoder.decoder.dicBufSize = outBufSize; } return SZ_OK; } static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize) { CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf)) return SZ_ERROR_FAIL; if (outBuf) { spec->decoder.decoder.dic = outBuf; spec->decoder.decoder.dicBufSize = outBufSize; } return SZ_OK; } static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc) { unsigned i; p->alloc = alloc; p->buf = NULL; p->numCoders = 0; p->outBufSize = 0; p->outBuf = NULL; // p->SingleBufMode = False; for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) p->coders[i].p = NULL; } static void MixCoder_Free(CMixCoder *p) { unsigned i; p->numCoders = 0; for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) { IStateCoder *sc = &p->coders[i]; if (sc->p) { sc->Free(sc->p, p->alloc); sc->p = NULL; } } if (p->buf) { ISzAlloc_Free(p->alloc, p->buf); p->buf = NULL; /* 9.31: the BUG was fixed */ } } static void MixCoder_Init(CMixCoder *p) { unsigned i; for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++) { p->size[i] = 0; p->pos[i] = 0; p->finished[i] = 0; } for (i = 0; i < p->numCoders; i++) { IStateCoder *coder = &p->coders[i]; coder->Init(coder->p); p->results[i] = SZ_OK; } p->outWritten = 0; p->wasFinished = False; p->res = SZ_OK; p->status = CODER_STATUS_NOT_SPECIFIED; } static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) { IStateCoder *sc = &p->coders[coderIndex]; p->ids[coderIndex] = methodId; if (methodId == XZ_ID_LZMA2) return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); #ifdef USE_SUBBLOCK if (methodId == XZ_ID_Subblock) return SbState_SetFromMethod(sc, p->alloc); #endif if (coderIndex == 0) return SZ_ERROR_UNSUPPORTED; return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId, XzBcFilterStateBase_Filter_Dec, p->alloc); } static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) { IStateCoder *sc = &p->coders[coderIndex]; if (methodId == XZ_ID_LZMA2) return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize); return SZ_ERROR_UNSUPPORTED; } /* if (destFinish) - then unpack data block is finished at (*destLen) position, and we can return data that were not processed by filter output (status) can be : CODER_STATUS_NOT_FINISHED CODER_STATUS_FINISHED_WITH_MARK CODER_STATUS_NEEDS_MORE_INPUT - not implemented still */ static SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, int destFinish, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode) { SizeT destLenOrig = *destLen; SizeT srcLenOrig = *srcLen; *destLen = 0; *srcLen = 0; if (p->wasFinished) return p->res; p->status = CODER_STATUS_NOT_FINISHED; // if (p->SingleBufMode) if (p->outBuf) { SRes res; SizeT destLen2, srcLen2; int wasFinished; PRF_STR("------- MixCoder Single ----------") srcLen2 = srcLenOrig; destLen2 = destLenOrig; { IStateCoder *coder = &p->coders[0]; res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, // &wasFinished, &p->status); wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); } p->res = res; /* if (wasFinished) p->status = CODER_STATUS_FINISHED_WITH_MARK; else { if (res == SZ_OK) if (destLen2 != destLenOrig) p->status = CODER_STATUS_NEEDS_MORE_INPUT; } */ *srcLen = srcLen2; src += srcLen2; p->outWritten += destLen2; if (res != SZ_OK || srcWasFinished || wasFinished) p->wasFinished = True; if (p->numCoders == 1) *destLen = destLen2; else if (p->wasFinished) { unsigned i; size_t processed = p->outWritten; for (i = 1; i < p->numCoders; i++) { IStateCoder *coder = &p->coders[i]; processed = coder->Filter(coder->p, p->outBuf, processed); if (wasFinished || (destFinish && p->outWritten == destLenOrig)) processed = p->outWritten; PRF_STR_INT("filter", i) } *destLen = processed; } return res; } PRF_STR("standard mix") if (p->numCoders != 1) { if (!p->buf) { p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); if (!p->buf) return SZ_ERROR_MEM; } finishMode = CODER_FINISH_ANY; } for (;;) { BoolInt processed = False; BoolInt allFinished = True; SRes resMain = SZ_OK; unsigned i; p->status = CODER_STATUS_NOT_FINISHED; /* if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) break; */ for (i = 0; i < p->numCoders; i++) { SRes res; IStateCoder *coder = &p->coders[i]; Byte *dest2; SizeT destLen2, srcLen2; // destLen2_Orig; const Byte *src2; int srcFinished2; int encodingWasFinished; ECoderStatus status2; if (i == 0) { src2 = src; srcLen2 = srcLenOrig - *srcLen; srcFinished2 = srcWasFinished; } else { size_t k = i - 1; src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; srcLen2 = p->size[k] - p->pos[k]; srcFinished2 = p->finished[k]; } if (i == p->numCoders - 1) { dest2 = dest; destLen2 = destLenOrig - *destLen; } else { if (p->pos[i] != p->size[i]) continue; dest2 = p->buf + (CODER_BUF_SIZE * i); destLen2 = CODER_BUF_SIZE; } // destLen2_Orig = destLen2; if (p->results[i] != SZ_OK) { if (resMain == SZ_OK) resMain = p->results[i]; continue; } res = coder->Code2(coder->p, dest2, &destLen2, src2, &srcLen2, srcFinished2, finishMode, // &encodingWasFinished, &status2); if (res != SZ_OK) { p->results[i] = res; if (resMain == SZ_OK) resMain = res; } encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); if (!encodingWasFinished) { allFinished = False; if (p->numCoders == 1 && res == SZ_OK) p->status = status2; } if (i == 0) { *srcLen += srcLen2; src += srcLen2; } else p->pos[(size_t)i - 1] += srcLen2; if (i == p->numCoders - 1) { *destLen += destLen2; dest += destLen2; } else { p->size[i] = destLen2; p->pos[i] = 0; p->finished[i] = encodingWasFinished; } if (destLen2 != 0 || srcLen2 != 0) processed = True; } if (!processed) { if (allFinished) p->status = CODER_STATUS_FINISHED_WITH_MARK; return resMain; } } } SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) { *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) return SZ_ERROR_NO_ARCHIVE; return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; } static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) { return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) && GetUi32(buf) == CrcCalc(buf + 4, 6) && flags == GetBe16(buf + 8) && buf[10] == XZ_FOOTER_SIG_0 && buf[11] == XZ_FOOTER_SIG_1; } #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ if (s == 0) return SZ_ERROR_ARCHIVE; \ pos += s; } static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p) { const unsigned numFilters = XzBlock_GetNumFilters(p) - 1; unsigned i; { const CXzFilter *f = &p->filters[numFilters]; if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) return False; } for (i = 0; i < numFilters; i++) { const CXzFilter *f = &p->filters[i]; if (f->id == XZ_ID_Delta) { if (f->propsSize != 1) return False; } else if (!XZ_IS_SUPPORTED_FILTER_ID(f->id) || (f->propsSize != 0 && f->propsSize != 4)) return False; } return True; } SRes XzBlock_Parse(CXzBlock *p, const Byte *header) { unsigned pos; unsigned numFilters, i; unsigned headerSize = (unsigned)header[0] << 2; /* (headerSize != 0) : another code checks */ if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) return SZ_ERROR_ARCHIVE; pos = 1; p->flags = header[pos++]; p->packSize = (UInt64)(Int64)-1; if (XzBlock_HasPackSize(p)) { READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize) if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) return SZ_ERROR_ARCHIVE; } p->unpackSize = (UInt64)(Int64)-1; if (XzBlock_HasUnpackSize(p)) { READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize) } numFilters = XzBlock_GetNumFilters(p); for (i = 0; i < numFilters; i++) { CXzFilter *filter = p->filters + i; UInt64 size; READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id) READ_VARINT_AND_CHECK(header, pos, headerSize, &size) if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) return SZ_ERROR_ARCHIVE; filter->propsSize = (UInt32)size; memcpy(filter->props, header + pos, (size_t)size); pos += (unsigned)size; #ifdef XZ_DUMP printf("\nf[%u] = %2X: ", i, (unsigned)filter->id); { unsigned i; for (i = 0; i < size; i++) printf(" %2X", filter->props[i]); } #endif } if (XzBlock_HasUnsupportedFlags(p)) return SZ_ERROR_UNSUPPORTED; while (pos < headerSize) if (header[pos++] != 0) return SZ_ERROR_ARCHIVE; return SZ_OK; } static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) { unsigned i; BoolInt needReInit = True; unsigned numFilters = XzBlock_GetNumFilters(block); if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) { needReInit = False; for (i = 0; i < numFilters; i++) if (p->ids[i] != block->filters[numFilters - 1 - i].id) { needReInit = True; break; } } // p->SingleBufMode = (outBuf != NULL); p->outBuf = outBuf; p->outBufSize = outBufSize; // p->SingleBufMode = False; // outBuf = NULL; if (needReInit) { MixCoder_Free(p); for (i = 0; i < numFilters; i++) { RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)) } p->numCoders = numFilters; } else { RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)) } for (i = 0; i < numFilters; i++) { const CXzFilter *f = &block->filters[numFilters - 1 - i]; IStateCoder *sc = &p->coders[i]; RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)) } MixCoder_Init(p); return SZ_OK; } void XzUnpacker_Init(CXzUnpacker *p) { p->state = XZ_STATE_STREAM_HEADER; p->pos = 0; p->numStartedStreams = 0; p->numFinishedStreams = 0; p->numTotalBlocks = 0; p->padSize = 0; p->decodeOnlyOneBlock = 0; p->parseMode = False; p->decodeToStreamSignature = False; // p->outBuf = NULL; // p->outBufSize = 0; p->outDataWritten = 0; } void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) { p->outBuf = outBuf; p->outBufSize = outBufSize; } void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc) { MixCoder_Construct(&p->decoder, alloc); p->outBuf = NULL; p->outBufSize = 0; XzUnpacker_Init(p); } void XzUnpacker_Free(CXzUnpacker *p) { MixCoder_Free(&p->decoder); } void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p) { p->indexSize = 0; p->numBlocks = 0; Sha256_Init(&p->sha); p->state = XZ_STATE_BLOCK_HEADER; p->pos = 0; p->decodeOnlyOneBlock = 1; } static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize) { Byte temp[32]; unsigned num = Xz_WriteVarInt(temp, packSize); num += Xz_WriteVarInt(temp + num, unpackSize); Sha256_Update(&p->sha, temp, num); p->indexSize += num; p->numBlocks++; } SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcFinished, ECoderFinishMode finishMode, ECoderStatus *status) { SizeT destLenOrig = *destLen; SizeT srcLenOrig = *srcLen; *destLen = 0; *srcLen = 0; *status = CODER_STATUS_NOT_SPECIFIED; for (;;) { SizeT srcRem; if (p->state == XZ_STATE_BLOCK) { SizeT destLen2 = destLenOrig - *destLen; SizeT srcLen2 = srcLenOrig - *srcLen; SRes res; ECoderFinishMode finishMode2 = finishMode; BoolInt srcFinished2 = (BoolInt)srcFinished; BoolInt destFinish = False; if (p->block.packSize != (UInt64)(Int64)-1) { UInt64 rem = p->block.packSize - p->packSize; if (srcLen2 >= rem) { srcFinished2 = True; srcLen2 = (SizeT)rem; } if (rem == 0 && p->block.unpackSize == p->unpackSize) return SZ_ERROR_DATA; } if (p->block.unpackSize != (UInt64)(Int64)-1) { UInt64 rem = p->block.unpackSize - p->unpackSize; if (destLen2 >= rem) { destFinish = True; finishMode2 = CODER_FINISH_END; destLen2 = (SizeT)rem; } } /* if (srcLen2 == 0 && destLen2 == 0) { *status = CODER_STATUS_NOT_FINISHED; return SZ_OK; } */ { res = MixCoder_Code(&p->decoder, (p->outBuf ? NULL : dest), &destLen2, destFinish, src, &srcLen2, srcFinished2, finishMode2); *status = p->decoder.status; XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); if (!p->outBuf) dest += destLen2; p->outDataWritten += destLen2; } (*srcLen) += srcLen2; src += srcLen2; p->packSize += srcLen2; (*destLen) += destLen2; p->unpackSize += destLen2; RINOK(res) if (*status != CODER_STATUS_FINISHED_WITH_MARK) { if (p->block.packSize == p->packSize && *status == CODER_STATUS_NEEDS_MORE_INPUT) { PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT") *status = CODER_STATUS_NOT_SPECIFIED; return SZ_ERROR_DATA; } return SZ_OK; } { XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); p->state = XZ_STATE_BLOCK_FOOTER; p->pos = 0; p->alignPos = 0; *status = CODER_STATUS_NOT_SPECIFIED; if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) { PRF_STR("ERROR: block.size mismatch") return SZ_ERROR_DATA; } } // continue; } srcRem = srcLenOrig - *srcLen; // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) { *status = CODER_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } switch ((int)p->state) { case XZ_STATE_STREAM_HEADER: { if (p->pos < XZ_STREAM_HEADER_SIZE) { if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) return SZ_ERROR_NO_ARCHIVE; if (p->decodeToStreamSignature) return SZ_OK; p->buf[p->pos++] = *src++; (*srcLen)++; } else { RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)) p->numStartedStreams++; p->indexSize = 0; p->numBlocks = 0; Sha256_Init(&p->sha); p->state = XZ_STATE_BLOCK_HEADER; p->pos = 0; } break; } case XZ_STATE_BLOCK_HEADER: { if (p->pos == 0) { p->buf[p->pos++] = *src++; (*srcLen)++; if (p->buf[0] == 0) { if (p->decodeOnlyOneBlock) return SZ_ERROR_DATA; p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); p->indexPos = p->indexPreSize; p->indexSize += p->indexPreSize; Sha256_Final(&p->sha, p->shaDigest); Sha256_Init(&p->sha); p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); p->state = XZ_STATE_STREAM_INDEX; break; } p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4; break; } if (p->pos != p->blockHeaderSize) { unsigned cur = p->blockHeaderSize - p->pos; if (cur > srcRem) cur = (unsigned)srcRem; memcpy(p->buf + p->pos, src, cur); p->pos += cur; (*srcLen) += cur; src += cur; } else { RINOK(XzBlock_Parse(&p->block, p->buf)) if (!XzBlock_AreSupportedFilters(&p->block)) return SZ_ERROR_UNSUPPORTED; p->numTotalBlocks++; p->state = XZ_STATE_BLOCK; p->packSize = 0; p->unpackSize = 0; XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); if (p->parseMode) { p->headerParsedOk = True; return SZ_OK; } RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)) } break; } case XZ_STATE_BLOCK_FOOTER: { if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) { if (srcRem == 0) { *status = CODER_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } (*srcLen)++; p->alignPos++; if (*src++ != 0) return SZ_ERROR_CRC; } else { const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags); unsigned cur = checkSize - p->pos; if (cur != 0) { if (srcRem == 0) { *status = CODER_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (cur > srcRem) cur = (unsigned)srcRem; memcpy(p->buf + p->pos, src, cur); p->pos += cur; (*srcLen) += cur; src += cur; if (checkSize != p->pos) break; } { Byte digest[XZ_CHECK_SIZE_MAX]; p->state = XZ_STATE_BLOCK_HEADER; p->pos = 0; if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) return SZ_ERROR_CRC; if (p->decodeOnlyOneBlock) { *status = CODER_STATUS_FINISHED_WITH_MARK; return SZ_OK; } } } break; } case XZ_STATE_STREAM_INDEX: { if (p->pos < p->indexPreSize) { (*srcLen)++; if (*src++ != p->buf[p->pos++]) return SZ_ERROR_CRC; } else { if (p->indexPos < p->indexSize) { UInt64 cur = p->indexSize - p->indexPos; if (srcRem > cur) srcRem = (SizeT)cur; p->crc = CrcUpdate(p->crc, src, srcRem); Sha256_Update(&p->sha, src, srcRem); (*srcLen) += srcRem; src += srcRem; p->indexPos += srcRem; } else if ((p->indexPos & 3) != 0) { Byte b = *src++; p->crc = CRC_UPDATE_BYTE(p->crc, b); (*srcLen)++; p->indexPos++; p->indexSize++; if (b != 0) return SZ_ERROR_CRC; } else { Byte digest[SHA256_DIGEST_SIZE]; p->state = XZ_STATE_STREAM_INDEX_CRC; p->indexSize += 4; p->pos = 0; Sha256_Final(&p->sha, digest); if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) return SZ_ERROR_CRC; } } break; } case XZ_STATE_STREAM_INDEX_CRC: { if (p->pos < 4) { (*srcLen)++; p->buf[p->pos++] = *src++; } else { const Byte *ptr = p->buf; p->state = XZ_STATE_STREAM_FOOTER; p->pos = 0; if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr)) return SZ_ERROR_CRC; } break; } case XZ_STATE_STREAM_FOOTER: { unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos; if (cur > srcRem) cur = (unsigned)srcRem; memcpy(p->buf + p->pos, src, cur); p->pos += cur; (*srcLen) += cur; src += cur; if (p->pos == XZ_STREAM_FOOTER_SIZE) { p->state = XZ_STATE_STREAM_PADDING; p->numFinishedStreams++; p->padSize = 0; if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) return SZ_ERROR_CRC; } break; } case XZ_STATE_STREAM_PADDING: { if (*src != 0) { if (((UInt32)p->padSize & 3) != 0) return SZ_ERROR_NO_ARCHIVE; p->pos = 0; p->state = XZ_STATE_STREAM_HEADER; } else { (*srcLen)++; src++; p->padSize++; } break; } case XZ_STATE_BLOCK: break; /* to disable GCC warning */ default: return SZ_ERROR_FAIL; } } /* if (p->state == XZ_STATE_FINISHED) *status = CODER_STATUS_FINISHED_WITH_MARK; return SZ_OK; */ } SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status) { XzUnpacker_Init(p); XzUnpacker_SetOutBuf(p, dest, *destLen); return XzUnpacker_Code(p, NULL, destLen, src, srcLen, True, finishMode, status); } BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p) { return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); } BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) { return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); } UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p) { UInt64 num = 0; if (p->state == XZ_STATE_STREAM_PADDING) num = p->padSize; else if (p->state == XZ_STATE_STREAM_HEADER) num = p->padSize + p->pos; return num; } #ifndef Z7_ST #include "MtDec.h" #endif void XzDecMtProps_Init(CXzDecMtProps *p) { p->inBufSize_ST = 1 << 18; p->outStep_ST = 1 << 20; p->ignoreErrors = False; #ifndef Z7_ST p->numThreads = 1; p->inBufSize_MT = 1 << 18; p->memUseMax = sizeof(size_t) << 28; #endif } #ifndef Z7_ST /* ---------- CXzDecMtThread ---------- */ typedef struct { Byte *outBuf; size_t outBufSize; size_t outPreSize; size_t inPreSize; size_t inPreHeaderSize; size_t blockPackSize_for_Index; // including block header and checksum. size_t blockPackTotal; // including stream header, block header and checksum. size_t inCodeSize; size_t outCodeSize; ECoderStatus status; SRes codeRes; BoolInt skipMode; // BoolInt finishedWithMark; EMtDecParseState parseState; BoolInt parsing_Truncated; BoolInt atBlockHeader; CXzStreamFlags streamFlags; // UInt64 numFinishedStreams UInt64 numStreams; UInt64 numTotalBlocks; UInt64 numBlocks; BoolInt dec_created; CXzUnpacker dec; Byte mtPad[1 << 7]; } CXzDecMtThread; #endif /* ---------- CXzDecMt ---------- */ struct CXzDecMt { CAlignOffsetAlloc alignOffsetAlloc; ISzAllocPtr allocMid; CXzDecMtProps props; size_t unpackBlockMaxSize; ISeqInStreamPtr inStream; ISeqOutStreamPtr outStream; ICompressProgressPtr progress; BoolInt finishMode; BoolInt outSize_Defined; UInt64 outSize; UInt64 outProcessed; UInt64 inProcessed; UInt64 readProcessed; BoolInt readWasFinished; SRes readRes; SRes writeRes; Byte *outBuf; size_t outBufSize; Byte *inBuf; size_t inBufSize; CXzUnpacker dec; ECoderStatus status; SRes codeRes; #ifndef Z7_ST BoolInt mainDecoderWasCalled; // int statErrorDefined; int finishedDecoderIndex; // global values that are used in Parse stage CXzStreamFlags streamFlags; // UInt64 numFinishedStreams UInt64 numStreams; UInt64 numTotalBlocks; UInt64 numBlocks; // UInt64 numBadBlocks; SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage // it can be = SZ_ERROR_INPUT_EOF // it can be = SZ_ERROR_DATA, in some another cases BoolInt isBlockHeaderState_Parse; BoolInt isBlockHeaderState_Write; UInt64 outProcessed_Parse; BoolInt parsing_Truncated; BoolInt mtc_WasConstructed; CMtDec mtc; CXzDecMtThread coders[MTDEC_THREADS_MAX]; #endif }; CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) { CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt)); if (!p) return NULL; AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); p->alignOffsetAlloc.baseAlloc = alloc; p->alignOffsetAlloc.numAlignBits = 7; p->alignOffsetAlloc.offset = 0; p->allocMid = allocMid; p->outBuf = NULL; p->outBufSize = 0; p->inBuf = NULL; p->inBufSize = 0; XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); p->unpackBlockMaxSize = 0; XzDecMtProps_Init(&p->props); #ifndef Z7_ST p->mtc_WasConstructed = False; { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CXzDecMtThread *coder = &p->coders[i]; coder->dec_created = False; coder->outBuf = NULL; coder->outBufSize = 0; } } #endif return (CXzDecMtHandle)p; } #ifndef Z7_ST static void XzDecMt_FreeOutBufs(CXzDecMt *p) { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CXzDecMtThread *coder = &p->coders[i]; if (coder->outBuf) { ISzAlloc_Free(p->allocMid, coder->outBuf); coder->outBuf = NULL; coder->outBufSize = 0; } } p->unpackBlockMaxSize = 0; } #endif static void XzDecMt_FreeSt(CXzDecMt *p) { XzUnpacker_Free(&p->dec); if (p->outBuf) { ISzAlloc_Free(p->allocMid, p->outBuf); p->outBuf = NULL; } p->outBufSize = 0; if (p->inBuf) { ISzAlloc_Free(p->allocMid, p->inBuf); p->inBuf = NULL; } p->inBufSize = 0; } // #define GET_CXzDecMt_p CXzDecMt *p = pp; void XzDecMt_Destroy(CXzDecMtHandle p) { // GET_CXzDecMt_p XzDecMt_FreeSt(p); #ifndef Z7_ST if (p->mtc_WasConstructed) { MtDec_Destruct(&p->mtc); p->mtc_WasConstructed = False; } { unsigned i; for (i = 0; i < MTDEC_THREADS_MAX; i++) { CXzDecMtThread *t = &p->coders[i]; if (t->dec_created) { // we don't need to free dict here XzUnpacker_Free(&t->dec); t->dec_created = False; } } } XzDecMt_FreeOutBufs(p); #endif ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p); } #ifndef Z7_ST static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) { CXzDecMt *me = (CXzDecMt *)obj; CXzDecMtThread *coder = &me->coders[coderIndex]; size_t srcSize = cc->srcSize; cc->srcSize = 0; cc->outPos = 0; cc->state = MTDEC_PARSE_CONTINUE; cc->canCreateNewThread = True; if (cc->startCall) { coder->outPreSize = 0; coder->inPreSize = 0; coder->inPreHeaderSize = 0; coder->parseState = MTDEC_PARSE_CONTINUE; coder->parsing_Truncated = False; coder->skipMode = False; coder->codeRes = SZ_OK; coder->status = CODER_STATUS_NOT_SPECIFIED; coder->inCodeSize = 0; coder->outCodeSize = 0; coder->numStreams = me->numStreams; coder->numTotalBlocks = me->numTotalBlocks; coder->numBlocks = me->numBlocks; if (!coder->dec_created) { XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); coder->dec_created = True; } XzUnpacker_Init(&coder->dec); if (me->isBlockHeaderState_Parse) { coder->dec.streamFlags = me->streamFlags; coder->atBlockHeader = True; XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); } else { coder->atBlockHeader = False; me->isBlockHeaderState_Parse = True; } coder->dec.numStartedStreams = me->numStreams; coder->dec.numTotalBlocks = me->numTotalBlocks; coder->dec.numBlocks = me->numBlocks; } while (!coder->skipMode) { ECoderStatus status; SRes res; size_t srcSize2 = srcSize; size_t destSize = (size_t)0 - 1; coder->dec.parseMode = True; coder->dec.headerParsedOk = False; PRF_STR_INT("Parse", srcSize2) res = XzUnpacker_Code(&coder->dec, NULL, &destSize, cc->src, &srcSize2, cc->srcFinished, CODER_FINISH_END, &status); // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); coder->codeRes = res; coder->status = status; cc->srcSize += srcSize2; srcSize -= srcSize2; coder->inPreHeaderSize += srcSize2; coder->inPreSize = coder->inPreHeaderSize; if (res != SZ_OK) { cc->state = coder->parseState = MTDEC_PARSE_END; /* if (res == SZ_ERROR_MEM) return res; return SZ_OK; */ return; // res; } if (coder->dec.headerParsedOk) { const CXzBlock *block = &coder->dec.block; if (XzBlock_HasUnpackSize(block) // && block->unpackSize <= me->props.outBlockMax && XzBlock_HasPackSize(block)) { { if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) { cc->state = MTDEC_PARSE_OVERFLOW; return; // SZ_OK; } } { const UInt64 packSize = block->packSize; const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; // if (blockPackSum <= me->props.inBlockMax) // unpackBlockMaxSize { coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); coder->blockPackTotal = (size_t)blockPackSum; coder->outPreSize = (size_t)block->unpackSize; coder->streamFlags = coder->dec.streamFlags; me->streamFlags = coder->dec.streamFlags; coder->skipMode = True; break; } } } } else // if (coder->inPreSize <= me->props.inBlockMax) { if (!cc->srcFinished) return; // SZ_OK; cc->state = coder->parseState = MTDEC_PARSE_END; return; // SZ_OK; } cc->state = MTDEC_PARSE_OVERFLOW; return; // SZ_OK; } // ---------- skipMode ---------- { UInt64 rem = coder->blockPackTotal - coder->inPreSize; size_t cur = srcSize; if (cur > rem) cur = (size_t)rem; cc->srcSize += cur; coder->inPreSize += cur; srcSize -= cur; if (coder->inPreSize == coder->blockPackTotal) { if (srcSize == 0) { if (!cc->srcFinished) return; // SZ_OK; cc->state = MTDEC_PARSE_END; } else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block cc->state = MTDEC_PARSE_END; else { cc->state = MTDEC_PARSE_NEW; { size_t blockMax = me->unpackBlockMaxSize; if (blockMax < coder->outPreSize) blockMax = coder->outPreSize; { UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; if (me->props.memUseMax < required) cc->canCreateNewThread = False; } } if (me->outSize_Defined) { // next block can be zero size const UInt64 rem2 = me->outSize - me->outProcessed_Parse; if (rem2 < coder->outPreSize) { coder->parsing_Truncated = True; cc->state = MTDEC_PARSE_END; } me->outProcessed_Parse += coder->outPreSize; } } } else if (cc->srcFinished) cc->state = MTDEC_PARSE_END; else return; // SZ_OK; coder->parseState = cc->state; cc->outPos = coder->outPreSize; me->numStreams = coder->dec.numStartedStreams; me->numTotalBlocks = coder->dec.numTotalBlocks; me->numBlocks = coder->dec.numBlocks + 1; return; // SZ_OK; } } static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) { CXzDecMt *me = (CXzDecMt *)pp; CXzDecMtThread *coder = &me->coders[coderIndex]; Byte *dest; if (!coder->dec.headerParsedOk) return SZ_OK; dest = coder->outBuf; if (!dest || coder->outBufSize < coder->outPreSize) { if (dest) { ISzAlloc_Free(me->allocMid, dest); coder->outBuf = NULL; coder->outBufSize = 0; } { size_t outPreSize = coder->outPreSize; if (outPreSize == 0) outPreSize = 1; dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); } if (!dest) return SZ_ERROR_MEM; coder->outBuf = dest; coder->outBufSize = coder->outPreSize; if (coder->outBufSize > me->unpackBlockMaxSize) me->unpackBlockMaxSize = coder->outBufSize; } // return SZ_ERROR_MEM; XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); { SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); // res = SZ_ERROR_UNSUPPORTED; // to test coder->codeRes = res; if (res != SZ_OK) { // if (res == SZ_ERROR_MEM) return res; if (me->props.ignoreErrors && res != SZ_ERROR_MEM) return SZ_OK; return res; } } return SZ_OK; } static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, const Byte *src, size_t srcSize, int srcFinished, // int finished, int blockFinished, UInt64 *inCodePos, UInt64 *outCodePos, int *stop) { CXzDecMt *me = (CXzDecMt *)pp; CXzDecMtThread *coder = &me->coders[coderIndex]; *inCodePos = coder->inCodeSize; *outCodePos = coder->outCodeSize; *stop = True; if (srcSize > coder->inPreSize - coder->inCodeSize) return SZ_ERROR_FAIL; if (coder->inCodeSize < coder->inPreHeaderSize) { size_t step = coder->inPreHeaderSize - coder->inCodeSize; if (step > srcSize) step = srcSize; src += step; srcSize -= step; coder->inCodeSize += step; *inCodePos = coder->inCodeSize; if (coder->inCodeSize < coder->inPreHeaderSize) { *stop = False; return SZ_OK; } } if (!coder->dec.headerParsedOk) return SZ_OK; if (!coder->outBuf) return SZ_OK; if (coder->codeRes == SZ_OK) { ECoderStatus status; SRes res; size_t srcProcessed = srcSize; size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); res = XzUnpacker_Code(&coder->dec, NULL, &outSizeCur, src, &srcProcessed, srcFinished, // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, CODER_FINISH_END, &status); // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); coder->codeRes = res; coder->status = status; coder->inCodeSize += srcProcessed; coder->outCodeSize = coder->dec.outDataWritten; *inCodePos = coder->inCodeSize; *outCodePos = coder->outCodeSize; if (res == SZ_OK) { if (srcProcessed == srcSize) *stop = False; return SZ_OK; } } if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) { *inCodePos = coder->inPreSize; *outCodePos = coder->outPreSize; return SZ_OK; } return coder->codeRes; } #define XZDECMT_STREAM_WRITE_STEP (1 << 24) static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, BoolInt needWriteToStream, const Byte *src, size_t srcSize, BoolInt isCross, // int srcFinished, BoolInt *needContinue, BoolInt *canRecode) { CXzDecMt *me = (CXzDecMt *)pp; const CXzDecMtThread *coder = &me->coders[coderIndex]; // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); *needContinue = False; *canRecode = True; if (!needWriteToStream) return SZ_OK; if (!coder->dec.headerParsedOk || !coder->outBuf) { if (me->finishedDecoderIndex < 0) me->finishedDecoderIndex = (int)coderIndex; return SZ_OK; } if (me->finishedDecoderIndex >= 0) return SZ_OK; me->mtc.inProcessed += coder->inCodeSize; *canRecode = False; { SRes res; size_t size = coder->outCodeSize; Byte *data = coder->outBuf; // we use in me->dec: sha, numBlocks, indexSize if (!me->isBlockHeaderState_Write) { XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); me->dec.decodeOnlyOneBlock = False; me->dec.numStartedStreams = coder->dec.numStartedStreams; me->dec.streamFlags = coder->streamFlags; me->isBlockHeaderState_Write = True; } me->dec.numTotalBlocks = coder->dec.numTotalBlocks; XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); if (coder->outPreSize != size) { if (me->props.ignoreErrors) { memset(data + size, 0, coder->outPreSize - size); size = coder->outPreSize; } // me->numBadBlocks++; if (me->mainErrorCode == SZ_OK) { if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) me->mainErrorCode = SZ_ERROR_INPUT_EOF; else me->mainErrorCode = SZ_ERROR_DATA; } } if (me->writeRes != SZ_OK) return me->writeRes; res = SZ_OK; { if (me->outSize_Defined) { const UInt64 rem = me->outSize - me->outProcessed; if (size > rem) size = (SizeT)rem; } for (;;) { size_t cur = size; size_t written; if (cur > XZDECMT_STREAM_WRITE_STEP) cur = XZDECMT_STREAM_WRITE_STEP; written = ISeqOutStream_Write(me->outStream, data, cur); // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); me->outProcessed += written; if (written != cur) { me->writeRes = SZ_ERROR_WRITE; res = me->writeRes; break; } data += cur; size -= cur; // PRF_STR_INT("Written size =", size) if (size == 0) break; res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); if (res != SZ_OK) break; } } if (coder->codeRes != SZ_OK) if (!me->props.ignoreErrors) { me->finishedDecoderIndex = (int)coderIndex; return res; } RINOK(res) if (coder->inPreSize != coder->inCodeSize || coder->blockPackTotal != coder->inCodeSize) { me->finishedDecoderIndex = (int)coderIndex; return SZ_OK; } if (coder->parseState != MTDEC_PARSE_END) { *needContinue = True; return SZ_OK; } } // (coder->state == MTDEC_PARSE_END) means that there are no other working threads // so we can use mtc variables without lock PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed) me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; { CXzUnpacker *dec = &me->dec; PRF_STR_INT("PostSingle", srcSize) { size_t srcProcessed = srcSize; ECoderStatus status; size_t outSizeCur = 0; SRes res; // dec->decodeOnlyOneBlock = False; dec->decodeToStreamSignature = True; me->mainDecoderWasCalled = True; if (coder->parsing_Truncated) { me->parsing_Truncated = True; return SZ_OK; } /* We have processed all xz-blocks of stream, And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where (src) is a pointer to xz-Index structure. We finish reading of current xz-Stream, including Zero padding after xz-Stream. We exit, if we reach extra byte (first byte of new-Stream or another data). But we don't update input stream pointer for that new extra byte. If extra byte is not correct first byte of xz-signature, we have SZ_ERROR_NO_ARCHIVE error here. */ res = XzUnpacker_Code(dec, NULL, &outSizeCur, src, &srcProcessed, me->mtc.readWasFinished, // srcFinished CODER_FINISH_END, // CODER_FINISH_ANY, &status); // res = SZ_ERROR_ARCHIVE; // for failure test me->status = status; me->codeRes = res; if (isCross) me->mtc.crossStart += srcProcessed; me->mtc.inProcessed += srcProcessed; me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; srcSize -= srcProcessed; src += srcProcessed; if (res != SZ_OK) { return SZ_OK; // return res; } if (dec->state == XZ_STATE_STREAM_HEADER) { *needContinue = True; me->isBlockHeaderState_Parse = False; me->isBlockHeaderState_Write = False; if (!isCross) { Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); if (!crossBuf) return SZ_ERROR_MEM; if (srcSize != 0) memcpy(crossBuf, src, srcSize); me->mtc.crossStart = 0; me->mtc.crossEnd = srcSize; } PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd) return SZ_OK; } if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0) { return SZ_ERROR_FAIL; } if (me->mtc.readWasFinished) { return SZ_OK; } } { size_t inPos; size_t inLim; // const Byte *inData; UInt64 inProgressPrev = me->mtc.inProcessed; // XzDecMt_Prepare_InBuf_ST(p); Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); if (!crossBuf) return SZ_ERROR_MEM; inPos = 0; inLim = 0; // inData = crossBuf; for (;;) { SizeT inProcessed; SizeT outProcessed; ECoderStatus status; SRes res; if (inPos == inLim) { if (!me->mtc.readWasFinished) { inPos = 0; inLim = me->mtc.inBufSize; me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim); me->mtc.readProcessed += inLim; if (inLim == 0 || me->mtc.readRes != SZ_OK) me->mtc.readWasFinished = True; } } inProcessed = inLim - inPos; outProcessed = 0; res = XzUnpacker_Code(dec, NULL, &outProcessed, crossBuf + inPos, &inProcessed, (inProcessed == 0), // srcFinished CODER_FINISH_END, &status); me->codeRes = res; me->status = status; inPos += inProcessed; me->mtc.inProcessed += inProcessed; me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; if (res != SZ_OK) { return SZ_OK; // return res; } if (dec->state == XZ_STATE_STREAM_HEADER) { *needContinue = True; me->mtc.crossStart = inPos; me->mtc.crossEnd = inLim; me->isBlockHeaderState_Parse = False; me->isBlockHeaderState_Write = False; return SZ_OK; } if (status != CODER_STATUS_NEEDS_MORE_INPUT) return SZ_ERROR_FAIL; if (me->mtc.progress) { UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; if (inDelta >= (1 << 22)) { RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)) inProgressPrev = me->mtc.inProcessed; } } if (me->mtc.readWasFinished) return SZ_OK; } } } } #endif void XzStatInfo_Clear(CXzStatInfo *p) { p->InSize = 0; p->OutSize = 0; p->NumStreams = 0; p->NumBlocks = 0; p->UnpackSize_Defined = False; p->NumStreams_Defined = False; p->NumBlocks_Defined = False; p->DataAfterEnd = False; p->DecodingTruncated = False; p->DecodeRes = SZ_OK; p->ReadRes = SZ_OK; p->ProgressRes = SZ_OK; p->CombinedRes = SZ_OK; p->CombinedRes_Type = SZ_OK; } /* XzDecMt_Decode_ST() can return SZ_OK or the following errors - SZ_ERROR_MEM for memory allocation error - error from XzUnpacker_Code() function - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case - ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS. But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors. ISeqInStream::Read() result is set to p->readRes. also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. */ static SRes XzDecMt_Decode_ST(CXzDecMt *p #ifndef Z7_ST , BoolInt tMode #endif , CXzStatInfo *stat) { size_t outPos; size_t inPos, inLim; const Byte *inData; UInt64 inPrev, outPrev; CXzUnpacker *dec; #ifndef Z7_ST if (tMode) { XzDecMt_FreeOutBufs(p); tMode = (BoolInt)MtDec_PrepareRead(&p->mtc); } #endif if (!p->outBuf || p->outBufSize != p->props.outStep_ST) { ISzAlloc_Free(p->allocMid, p->outBuf); p->outBufSize = 0; p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); if (!p->outBuf) return SZ_ERROR_MEM; p->outBufSize = p->props.outStep_ST; } if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) { ISzAlloc_Free(p->allocMid, p->inBuf); p->inBufSize = 0; p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); if (!p->inBuf) return SZ_ERROR_MEM; p->inBufSize = p->props.inBufSize_ST; } dec = &p->dec; dec->decodeToStreamSignature = False; // dec->decodeOnlyOneBlock = False; XzUnpacker_SetOutBuf(dec, NULL, 0); inPrev = p->inProcessed; outPrev = p->outProcessed; inPos = 0; inLim = 0; inData = NULL; outPos = 0; for (;;) { SizeT outSize; BoolInt finished; ECoderFinishMode finishMode; SizeT inProcessed; ECoderStatus status; SRes res; SizeT outProcessed; if (inPos == inLim) { #ifndef Z7_ST if (tMode) { inData = MtDec_Read(&p->mtc, &inLim); inPos = 0; if (inData) continue; tMode = False; inLim = 0; } #endif if (!p->readWasFinished) { inPos = 0; inLim = p->inBufSize; inData = p->inBuf; p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim); p->readProcessed += inLim; if (inLim == 0 || p->readRes != SZ_OK) p->readWasFinished = True; } } outSize = p->props.outStep_ST - outPos; finishMode = CODER_FINISH_ANY; if (p->outSize_Defined) { const UInt64 rem = p->outSize - p->outProcessed; if (outSize >= rem) { outSize = (SizeT)rem; if (p->finishMode) finishMode = CODER_FINISH_END; } } inProcessed = inLim - inPos; outProcessed = outSize; res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, inData + inPos, &inProcessed, (inPos == inLim), // srcFinished finishMode, &status); p->codeRes = res; p->status = status; inPos += inProcessed; outPos += outProcessed; p->inProcessed += inProcessed; p->outProcessed += outProcessed; finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); if (finished || outProcessed >= outSize) if (outPos != 0) { const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); // p->outProcessed += written; // 21.01: BUG fixed if (written != outPos) { stat->CombinedRes_Type = SZ_ERROR_WRITE; return SZ_ERROR_WRITE; } outPos = 0; } if (p->progress && res == SZ_OK) { if (p->inProcessed - inPrev >= (1 << 22) || p->outProcessed - outPrev >= (1 << 22)) { res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); if (res != SZ_OK) { stat->CombinedRes_Type = SZ_ERROR_PROGRESS; stat->ProgressRes = res; return res; } inPrev = p->inProcessed; outPrev = p->outProcessed; } } if (finished) { // p->codeRes is preliminary error from XzUnpacker_Code. // and it can be corrected later as final result // so we return SZ_OK here instead of (res); return SZ_OK; // return res; } } } /* XzStatInfo_SetStat() transforms CXzUnpacker return code and status to combined CXzStatInfo results. it can convert SZ_OK to SZ_ERROR_INPUT_EOF it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1) */ static void XzStatInfo_SetStat(const CXzUnpacker *dec, int finishMode, // UInt64 readProcessed, UInt64 inProcessed, SRes res, // it's result from CXzUnpacker unpacker ECoderStatus status, BoolInt decodingTruncated, CXzStatInfo *stat) { UInt64 extraSize; stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); stat->InSize = inProcessed; stat->NumStreams = dec->numStartedStreams; stat->NumBlocks = dec->numTotalBlocks; stat->UnpackSize_Defined = True; stat->NumStreams_Defined = True; stat->NumBlocks_Defined = True; extraSize = XzUnpacker_GetExtraSize(dec); if (res == SZ_OK) { if (status == CODER_STATUS_NEEDS_MORE_INPUT) { // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams // any extra data is part of correct data extraSize = 0; // if xz stream was not finished, then we need more data if (!XzUnpacker_IsStreamWasFinished(dec)) res = SZ_ERROR_INPUT_EOF; } else { // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding // so he we have (status == CODER_STATUS_NOT_FINISHED) // if (status != CODER_STATUS_FINISHED_WITH_MARK) if (!decodingTruncated || finishMode) res = SZ_ERROR_DATA; } } else if (res == SZ_ERROR_NO_ARCHIVE) { /* SZ_ERROR_NO_ARCHIVE is possible for 2 states: XZ_STATE_STREAM_HEADER - if bad signature or bad CRC XZ_STATE_STREAM_PADDING - if non-zero padding data extraSize and inProcessed don't include "bad" byte */ // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error if (inProcessed != extraSize) // if there were good xz streams before error { // if (extraSize != 0 || readProcessed != inProcessed) { // he we suppose that all xz streams were finsihed OK, and we have // some extra data after all streams stat->DataAfterEnd = True; res = SZ_OK; } } } if (stat->DecodeRes == SZ_OK) stat->DecodeRes = res; stat->InSize -= extraSize; } SRes XzDecMt_Decode(CXzDecMtHandle p, const CXzDecMtProps *props, const UInt64 *outDataSize, int finishMode, ISeqOutStreamPtr outStream, // Byte *outBuf, size_t *outBufSize, ISeqInStreamPtr inStream, // const Byte *inData, size_t inDataSize, CXzStatInfo *stat, int *isMT, ICompressProgressPtr progress) { // GET_CXzDecMt_p #ifndef Z7_ST BoolInt tMode; #endif XzStatInfo_Clear(stat); p->props = *props; p->inStream = inStream; p->outStream = outStream; p->progress = progress; // p->stat = stat; p->outSize = 0; p->outSize_Defined = False; if (outDataSize) { p->outSize_Defined = True; p->outSize = *outDataSize; } p->finishMode = (BoolInt)finishMode; // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test p->writeRes = SZ_OK; p->outProcessed = 0; p->inProcessed = 0; p->readProcessed = 0; p->readWasFinished = False; p->readRes = SZ_OK; p->codeRes = SZ_OK; p->status = CODER_STATUS_NOT_SPECIFIED; XzUnpacker_Init(&p->dec); *isMT = False; /* p->outBuf = NULL; p->outBufSize = 0; if (!outStream) { p->outBuf = outBuf; p->outBufSize = *outBufSize; *outBufSize = 0; } */ #ifndef Z7_ST p->isBlockHeaderState_Parse = False; p->isBlockHeaderState_Write = False; // p->numBadBlocks = 0; p->mainErrorCode = SZ_OK; p->mainDecoderWasCalled = False; tMode = False; if (p->props.numThreads > 1) { IMtDecCallback2 vt; BoolInt needContinue; SRes res; // we just free ST buffers here // but we still keep state variables, that was set in XzUnpacker_Init() XzDecMt_FreeSt(p); p->outProcessed_Parse = 0; p->parsing_Truncated = False; p->numStreams = 0; p->numTotalBlocks = 0; p->numBlocks = 0; p->finishedDecoderIndex = -1; if (!p->mtc_WasConstructed) { p->mtc_WasConstructed = True; MtDec_Construct(&p->mtc); } p->mtc.mtCallback = &vt; p->mtc.mtCallbackObject = p; p->mtc.progress = progress; p->mtc.inStream = inStream; p->mtc.alloc = &p->alignOffsetAlloc.vt; // p->mtc.inData = inData; // p->mtc.inDataSize = inDataSize; p->mtc.inBufSize = p->props.inBufSize_MT; // p->mtc.inBlockMax = p->props.inBlockMax; p->mtc.numThreadsMax = p->props.numThreads; *isMT = True; vt.Parse = XzDecMt_Callback_Parse; vt.PreCode = XzDecMt_Callback_PreCode; vt.Code = XzDecMt_Callback_Code; vt.Write = XzDecMt_Callback_Write; res = MtDec_Code(&p->mtc); stat->InSize = p->mtc.inProcessed; p->inProcessed = p->mtc.inProcessed; p->readRes = p->mtc.readRes; p->readWasFinished = p->mtc.readWasFinished; p->readProcessed = p->mtc.readProcessed; tMode = True; needContinue = False; if (res == SZ_OK) { if (p->mtc.mtProgress.res != SZ_OK) { res = p->mtc.mtProgress.res; stat->ProgressRes = res; stat->CombinedRes_Type = SZ_ERROR_PROGRESS; } else needContinue = p->mtc.needContinue; } if (!needContinue) { { SRes codeRes; BoolInt truncated = False; ECoderStatus status; const CXzUnpacker *dec; stat->OutSize = p->outProcessed; if (p->finishedDecoderIndex >= 0) { const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; codeRes = coder->codeRes; dec = &coder->dec; status = coder->status; } else if (p->mainDecoderWasCalled) { codeRes = p->codeRes; dec = &p->dec; status = p->status; truncated = p->parsing_Truncated; } else return SZ_ERROR_FAIL; if (p->mainErrorCode != SZ_OK) stat->DecodeRes = p->mainErrorCode; XzStatInfo_SetStat(dec, p->finishMode, // p->mtc.readProcessed, p->mtc.inProcessed, codeRes, status, truncated, stat); } if (res == SZ_OK) { stat->ReadRes = p->mtc.readRes; if (p->writeRes != SZ_OK) { res = p->writeRes; stat->CombinedRes_Type = SZ_ERROR_WRITE; } else if (p->mtc.readRes != SZ_OK // && p->mtc.inProcessed == p->mtc.readProcessed && stat->DecodeRes == SZ_ERROR_INPUT_EOF) { res = p->mtc.readRes; stat->CombinedRes_Type = SZ_ERROR_READ; } else if (stat->DecodeRes != SZ_OK) res = stat->DecodeRes; } stat->CombinedRes = res; if (stat->CombinedRes_Type == SZ_OK) stat->CombinedRes_Type = res; return res; } PRF_STR("----- decoding ST -----") } #endif *isMT = False; { SRes res = XzDecMt_Decode_ST(p #ifndef Z7_ST , tMode #endif , stat ); #ifndef Z7_ST // we must set error code from MT decoding at first if (p->mainErrorCode != SZ_OK) stat->DecodeRes = p->mainErrorCode; #endif XzStatInfo_SetStat(&p->dec, p->finishMode, // p->readProcessed, p->inProcessed, p->codeRes, p->status, False, // truncated stat); stat->ReadRes = p->readRes; if (res == SZ_OK) { if (p->readRes != SZ_OK // && p->inProcessed == p->readProcessed && stat->DecodeRes == SZ_ERROR_INPUT_EOF) { // we set read error as combined error, only if that error was the reason // of decoding problem res = p->readRes; stat->CombinedRes_Type = SZ_ERROR_READ; } else if (stat->DecodeRes != SZ_OK) res = stat->DecodeRes; } stat->CombinedRes = res; if (stat->CombinedRes_Type == SZ_OK) stat->CombinedRes_Type = res; return res; } } #undef PRF #undef PRF_STR #undef PRF_STR_INT_2 tmp41wklro_/C/XzEnc.c0000444000175000001440000010350514570267340015532 0ustar nabijaczleweliusers/* XzEnc.c -- Xz Encode 2024-03-01 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include #include "7zCrc.h" #include "Bra.h" #include "CpuArch.h" #ifdef USE_SUBBLOCK #include "Bcj3Enc.c" #include "SbFind.c" #include "SbEnc.c" #endif #include "XzEnc.h" // #define Z7_ST #ifndef Z7_ST #include "MtCoder.h" #else #define MTCODER_THREADS_MAX 1 #define MTCODER_BLOCKS_MAX 1 #endif #define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) #define XZ_CHECK_SIZE_MAX 64 /* max pack size for LZMA2 block + pad4 + check_size: */ #define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + XZ_CHECK_SIZE_MAX) #define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) // #define XzBlock_ClearFlags(p) (p)->flags = 0; #define XzBlock_ClearFlags_SetNumFilters(p, n) (p)->flags = (Byte)((n) - 1); #define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; #define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; static SRes WriteBytes(ISeqOutStreamPtr s, const void *buf, size_t size) { return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; } static SRes WriteBytes_UpdateCrc(ISeqOutStreamPtr s, const void *buf, size_t size, UInt32 *crc) { *crc = CrcUpdate(*crc, buf, size); return WriteBytes(s, buf, size); } static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStreamPtr s) { UInt32 crc; Byte header[XZ_STREAM_HEADER_SIZE]; memcpy(header, XZ_SIG, XZ_SIG_SIZE); header[XZ_SIG_SIZE] = (Byte)(f >> 8); header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF); crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE); SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc) return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); } static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStreamPtr s) { Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; unsigned pos = 1; unsigned numFilters, i; header[pos++] = p->flags; if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); numFilters = XzBlock_GetNumFilters(p); for (i = 0; i < numFilters; i++) { const CXzFilter *f = &p->filters[i]; pos += Xz_WriteVarInt(header + pos, f->id); pos += Xz_WriteVarInt(header + pos, f->propsSize); memcpy(header + pos, f->props, f->propsSize); pos += f->propsSize; } while ((pos & 3) != 0) header[pos++] = 0; header[0] = (Byte)(pos >> 2); SetUi32(header + pos, CrcCalc(header, pos)) return WriteBytes(s, header, pos + 4); } typedef struct { size_t numBlocks; size_t size; size_t allocated; Byte *blocks; } CXzEncIndex; static void XzEncIndex_Construct(CXzEncIndex *p) { p->numBlocks = 0; p->size = 0; p->allocated = 0; p->blocks = NULL; } static void XzEncIndex_Init(CXzEncIndex *p) { p->numBlocks = 0; p->size = 0; } static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc) { if (p->blocks) { ISzAlloc_Free(alloc, p->blocks); p->blocks = NULL; } p->numBlocks = 0; p->size = 0; p->allocated = 0; } static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc) { Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize); if (!blocks) return SZ_ERROR_MEM; if (p->size != 0) memcpy(blocks, p->blocks, p->size); if (p->blocks) ISzAlloc_Free(alloc, p->blocks); p->blocks = blocks; p->allocated = newSize; return SZ_OK; } static SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) { UInt64 pos; { Byte buf[32]; unsigned pos2 = Xz_WriteVarInt(buf, totalSize); pos2 += Xz_WriteVarInt(buf + pos2, unpackSize); pos = numBlocks * pos2; } if (pos <= p->allocated - p->size) return SZ_OK; { UInt64 newSize64 = p->size + pos; size_t newSize = (size_t)newSize64; if (newSize != newSize64) return SZ_ERROR_MEM; return XzEncIndex_ReAlloc(p, newSize, alloc); } } static SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) { Byte buf[32]; unsigned pos = Xz_WriteVarInt(buf, totalSize); pos += Xz_WriteVarInt(buf + pos, unpackSize); if (pos > p->allocated - p->size) { size_t newSize = p->allocated * 2 + 16 * 2; if (newSize < p->size + pos) return SZ_ERROR_MEM; RINOK(XzEncIndex_ReAlloc(p, newSize, alloc)) } memcpy(p->blocks + p->size, buf, pos); p->size += pos; p->numBlocks++; return SZ_OK; } static SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStreamPtr s) { Byte buf[32]; UInt64 globalPos; UInt32 crc = CRC_INIT_VAL; unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); globalPos = pos; buf[0] = 0; RINOK(WriteBytes_UpdateCrc(s, buf, pos, &crc)) RINOK(WriteBytes_UpdateCrc(s, p->blocks, p->size, &crc)) globalPos += p->size; pos = XZ_GET_PAD_SIZE(globalPos); buf[1] = 0; buf[2] = 0; buf[3] = 0; globalPos += pos; crc = CrcUpdate(crc, buf + 4 - pos, pos); SetUi32(buf + 4, CRC_GET_DIGEST(crc)) SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2)) buf[8 + 8] = (Byte)(flags >> 8); buf[8 + 9] = (Byte)(flags & 0xFF); SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6)) buf[8 + 10] = XZ_FOOTER_SIG_0; buf[8 + 11] = XZ_FOOTER_SIG_1; return WriteBytes(s, buf + 4 - pos, pos + 4 + 12); } /* ---------- CSeqCheckInStream ---------- */ typedef struct { ISeqInStream vt; ISeqInStreamPtr realStream; const Byte *data; UInt64 limit; UInt64 processed; int realStreamFinished; CXzCheck check; } CSeqCheckInStream; static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode) { p->limit = (UInt64)(Int64)-1; p->processed = 0; p->realStreamFinished = 0; XzCheck_Init(&p->check, checkMode); } static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) { XzCheck_Final(&p->check, digest); } static SRes SeqCheckInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqCheckInStream) size_t size2 = *size; SRes res = SZ_OK; if (p->limit != (UInt64)(Int64)-1) { UInt64 rem = p->limit - p->processed; if (size2 > rem) size2 = (size_t)rem; } if (size2 != 0) { if (p->realStream) { res = ISeqInStream_Read(p->realStream, data, &size2); p->realStreamFinished = (size2 == 0) ? 1 : 0; } else memcpy(data, p->data + (size_t)p->processed, size2); XzCheck_Update(&p->check, data, size2); p->processed += size2; } *size = size2; return res; } /* ---------- CSeqSizeOutStream ---------- */ typedef struct { ISeqOutStream vt; ISeqOutStreamPtr realStream; Byte *outBuf; size_t outBufLimit; UInt64 processed; } CSeqSizeOutStream; static size_t SeqSizeOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqSizeOutStream) if (p->realStream) size = ISeqOutStream_Write(p->realStream, data, size); else { if (size > p->outBufLimit - (size_t)p->processed) return 0; memcpy(p->outBuf + (size_t)p->processed, data, size); } p->processed += size; return size; } /* ---------- CSeqInFilter ---------- */ #define FILTER_BUF_SIZE (1 << 20) typedef struct { ISeqInStream vt; ISeqInStreamPtr realStream; IStateCoder StateCoder; Byte *buf; size_t curPos; size_t endPos; int srcWasFinished; } CSeqInFilter; static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] = { Z7_BRANCH_CONV_ENC_2 (BranchConv_PPC), Z7_BRANCH_CONV_ENC_2 (BranchConv_IA64), Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM), Z7_BRANCH_CONV_ENC_2 (BranchConv_ARMT), Z7_BRANCH_CONV_ENC_2 (BranchConv_SPARC), Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM64), Z7_BRANCH_CONV_ENC_2 (BranchConv_RISCV) }; static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size) { switch (p->methodId) { case XZ_ID_Delta: Delta_Encode(p->delta_State, p->delta, data, size); break; case XZ_ID_X86: size = (SizeT)(z7_BranchConvSt_X86_Enc(data, size, p->ip, &p->X86_State) - data); break; default: if (p->methodId >= XZ_ID_PPC) { const UInt32 i = p->methodId - XZ_ID_PPC; if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Enc)) size = (SizeT)(g_Funcs_BranchConv_RISC_Enc[i](data, size, p->ip) - data); } break; } p->ip += (UInt32)size; return size; } static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc) { if (!p->buf) { p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE); if (!p->buf) return SZ_ERROR_MEM; } p->curPos = p->endPos = 0; p->srcWasFinished = 0; RINOK(Xz_StateCoder_Bc_SetFromMethod_Func(&p->StateCoder, props->id, XzBcFilterStateBase_Filter_Enc, alloc)) RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc)) p->StateCoder.Init(p->StateCoder.p); return SZ_OK; } static SRes SeqInFilter_Read(ISeqInStreamPtr pp, void *data, size_t *size) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInFilter) const size_t sizeOriginal = *size; if (sizeOriginal == 0) return SZ_OK; *size = 0; for (;;) { if (!p->srcWasFinished && p->curPos == p->endPos) { p->curPos = 0; p->endPos = FILTER_BUF_SIZE; RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos)) if (p->endPos == 0) p->srcWasFinished = 1; } { SizeT srcLen = p->endPos - p->curPos; ECoderStatus status; SRes res; *size = sizeOriginal; res = p->StateCoder.Code2(p->StateCoder.p, (Byte *)data, size, p->buf + p->curPos, &srcLen, p->srcWasFinished, CODER_FINISH_ANY, &status); p->curPos += srcLen; if (*size != 0 || srcLen == 0 || res != SZ_OK) return res; } } } static void SeqInFilter_Construct(CSeqInFilter *p) { p->buf = NULL; p->StateCoder.p = NULL; p->vt.Read = SeqInFilter_Read; } static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) { if (p->StateCoder.p) { p->StateCoder.Free(p->StateCoder.p, alloc); p->StateCoder.p = NULL; } if (p->buf) { ISzAlloc_Free(alloc, p->buf); p->buf = NULL; } } /* ---------- CSbEncInStream ---------- */ #ifdef USE_SUBBLOCK typedef struct { ISeqInStream vt; ISeqInStreamPtr inStream; CSbEnc enc; } CSbEncInStream; static SRes SbEncInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size) { CSbEncInStream *p = Z7_CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt); size_t sizeOriginal = *size; if (sizeOriginal == 0) return SZ_OK; for (;;) { if (p->enc.needRead && !p->enc.readWasFinished) { size_t processed = p->enc.needReadSizeMax; RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)) p->enc.readPos += processed; if (processed == 0) { p->enc.readWasFinished = True; p->enc.isFinalFinished = True; } p->enc.needRead = False; } *size = sizeOriginal; RINOK(SbEnc_Read(&p->enc, data, size)) if (*size != 0 || !p->enc.needRead) return SZ_OK; } } void SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc) { SbEnc_Construct(&p->enc, alloc); p->vt.Read = SbEncInStream_Read; } SRes SbEncInStream_Init(CSbEncInStream *p) { return SbEnc_Init(&p->enc); } void SbEncInStream_Free(CSbEncInStream *p) { SbEnc_Free(&p->enc); } #endif /* ---------- CXzProps ---------- */ void XzFilterProps_Init(CXzFilterProps *p) { p->id = 0; p->delta = 0; p->ip = 0; p->ipDefined = False; } void XzProps_Init(CXzProps *p) { p->checkId = XZ_CHECK_CRC32; p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO; p->numBlockThreads_Reduced = -1; p->numBlockThreads_Max = -1; p->numTotalThreads = -1; p->reduceSize = (UInt64)(Int64)-1; p->forceWriteSizesInHeader = 0; // p->forceWriteSizesInHeader = 1; XzFilterProps_Init(&p->filterProps); Lzma2EncProps_Init(&p->lzma2Props); } static void XzEncProps_Normalize_Fixed(CXzProps *p) { UInt64 fileSize; int t1, t1n, t2, t2r, t3; { CLzma2EncProps tp = p->lzma2Props; if (tp.numTotalThreads <= 0) tp.numTotalThreads = p->numTotalThreads; Lzma2EncProps_Normalize(&tp); t1n = tp.numTotalThreads; } t1 = p->lzma2Props.numTotalThreads; t2 = p->numBlockThreads_Max; t3 = p->numTotalThreads; if (t2 > MTCODER_THREADS_MAX) t2 = MTCODER_THREADS_MAX; if (t3 <= 0) { if (t2 <= 0) t2 = 1; t3 = t1n * t2; } else if (t2 <= 0) { t2 = t3 / t1n; if (t2 == 0) { t1 = 1; t2 = t3; } if (t2 > MTCODER_THREADS_MAX) t2 = MTCODER_THREADS_MAX; } else if (t1 <= 0) { t1 = t3 / t2; if (t1 == 0) t1 = 1; } else t3 = t1n * t2; p->lzma2Props.numTotalThreads = t1; t2r = t2; fileSize = p->reduceSize; if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) p->lzma2Props.lzmaProps.reduceSize = p->blockSize; Lzma2EncProps_Normalize(&p->lzma2Props); t1 = p->lzma2Props.numTotalThreads; { if (t2 > 1 && fileSize != (UInt64)(Int64)-1) { UInt64 numBlocks = fileSize / p->blockSize; if (numBlocks * p->blockSize != fileSize) numBlocks++; if (numBlocks < (unsigned)t2) { t2r = (int)numBlocks; if (t2r == 0) t2r = 1; t3 = t1 * t2r; } } } p->numBlockThreads_Max = t2; p->numBlockThreads_Reduced = t2r; p->numTotalThreads = t3; } static void XzProps_Normalize(CXzProps *p) { /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties. Lzma2Enc_SetProps() will normalize lzma2Props later. */ if (p->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID) { p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; p->numBlockThreads_Reduced = 1; p->numBlockThreads_Max = 1; if (p->lzma2Props.numTotalThreads <= 0) p->lzma2Props.numTotalThreads = p->numTotalThreads; return; } else { CLzma2EncProps *lzma2 = &p->lzma2Props; if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) { // xz-auto p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) { // if (xz-auto && lzma2-solid) - we use solid for both p->blockSize = XZ_PROPS_BLOCK_SIZE_SOLID; p->numBlockThreads_Reduced = 1; p->numBlockThreads_Max = 1; if (p->lzma2Props.numTotalThreads <= 0) p->lzma2Props.numTotalThreads = p->numTotalThreads; } else { // if (xz-auto && (lzma2-auto || lzma2-fixed_) // we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block CLzma2EncProps tp = p->lzma2Props; if (tp.numTotalThreads <= 0) tp.numTotalThreads = p->numTotalThreads; Lzma2EncProps_Normalize(&tp); p->blockSize = tp.blockSize; // fixed or solid p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced; p->numBlockThreads_Max = tp.numBlockThreads_Max; if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) lzma2->lzmaProps.reduceSize = tp.blockSize; lzma2->numBlockThreads_Reduced = 1; lzma2->numBlockThreads_Max = 1; return; } } else { // xz-fixed // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; { UInt64 r = p->reduceSize; if (r > p->blockSize || r == (UInt64)(Int64)-1) r = p->blockSize; lzma2->lzmaProps.reduceSize = r; } if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO) lzma2->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID) lzma2->blockSize = p->blockSize; XzEncProps_Normalize_Fixed(p); } } } /* ---------- CLzma2WithFilters ---------- */ typedef struct { CLzma2EncHandle lzma2; CSeqInFilter filter; #ifdef USE_SUBBLOCK CSbEncInStream sb; #endif } CLzma2WithFilters; static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) { p->lzma2 = NULL; SeqInFilter_Construct(&p->filter); #ifdef USE_SUBBLOCK SbEncInStream_Construct(&p->sb, alloc); #endif } static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc) { if (!p->lzma2) { p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc); if (!p->lzma2) return SZ_ERROR_MEM; } return SZ_OK; } static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) { #ifdef USE_SUBBLOCK SbEncInStream_Free(&p->sb); #endif SeqInFilter_Free(&p->filter, alloc); if (p->lzma2) { Lzma2Enc_Destroy(p->lzma2); p->lzma2 = NULL; } } typedef struct { UInt64 unpackSize; UInt64 totalSize; size_t headerSize; } CXzEncBlockInfo; static SRes Xz_CompressBlock( CLzma2WithFilters *lzmaf, ISeqOutStreamPtr outStream, Byte *outBufHeader, Byte *outBufData, size_t outBufDataLimit, ISeqInStreamPtr inStream, // UInt64 expectedSize, const Byte *inBuf, // used if (!inStream) size_t inBufSize, // used if (!inStream), it's block size, props->blockSize is ignored const CXzProps *props, ICompressProgressPtr progress, int *inStreamFinished, /* only for inStream version */ CXzEncBlockInfo *blockSizes, ISzAllocPtr alloc, ISzAllocPtr allocBig) { CSeqCheckInStream checkInStream; CSeqSizeOutStream seqSizeOutStream; CXzBlock block; unsigned filterIndex = 0; CXzFilter *filter = NULL; const CXzFilterProps *fp = &props->filterProps; if (fp->id == 0) fp = NULL; *inStreamFinished = False; RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig)) RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props)) // XzBlock_ClearFlags(&block) XzBlock_ClearFlags_SetNumFilters(&block, 1 + (fp ? 1 : 0)) if (fp) { filter = &block.filters[filterIndex++]; filter->id = fp->id; filter->propsSize = 0; if (fp->id == XZ_ID_Delta) { filter->props[0] = (Byte)(fp->delta - 1); filter->propsSize = 1; } else if (fp->ipDefined) { Byte *ptr = filter->props; SetUi32(ptr, fp->ip) filter->propsSize = 4; } } { CXzFilter *f = &block.filters[filterIndex++]; f->id = XZ_ID_LZMA2; f->propsSize = 1; f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); } seqSizeOutStream.vt.Write = SeqSizeOutStream_Write; seqSizeOutStream.realStream = outStream; seqSizeOutStream.outBuf = outBufData; seqSizeOutStream.outBufLimit = outBufDataLimit; seqSizeOutStream.processed = 0; /* if (expectedSize != (UInt64)(Int64)-1) { block.unpackSize = expectedSize; if (props->blockSize != (UInt64)(Int64)-1) if (expectedSize > props->blockSize) block.unpackSize = props->blockSize; XzBlock_SetHasUnpackSize(&block) } */ if (outStream) { RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)) } checkInStream.vt.Read = SeqCheckInStream_Read; SeqCheckInStream_Init(&checkInStream, props->checkId); checkInStream.realStream = inStream; checkInStream.data = inBuf; checkInStream.limit = props->blockSize; if (!inStream) checkInStream.limit = inBufSize; if (fp) { #ifdef USE_SUBBLOCK if (fp->id == XZ_ID_Subblock) { lzmaf->sb.inStream = &checkInStream.vt; RINOK(SbEncInStream_Init(&lzmaf->sb)) } else #endif { lzmaf->filter.realStream = &checkInStream.vt; RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc)) } } { SRes res; Byte *outBuf = NULL; size_t outSize = 0; BoolInt useStream = (fp || inStream); // useStream = True; if (!useStream) { XzCheck_Update(&checkInStream.check, inBuf, inBufSize); checkInStream.processed = inBufSize; } if (!outStream) { outBuf = seqSizeOutStream.outBuf; // + (size_t)seqSizeOutStream.processed; outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed; } res = Lzma2Enc_Encode2(lzmaf->lzma2, outBuf ? NULL : &seqSizeOutStream.vt, outBuf, outBuf ? &outSize : NULL, useStream ? (fp ? ( #ifdef USE_SUBBLOCK (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt: #endif &lzmaf->filter.vt) : &checkInStream.vt) : NULL, useStream ? NULL : inBuf, useStream ? 0 : inBufSize, progress); if (outBuf) seqSizeOutStream.processed += outSize; RINOK(res) blockSizes->unpackSize = checkInStream.processed; } { Byte buf[4 + XZ_CHECK_SIZE_MAX]; const unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); const UInt64 packSize = seqSizeOutStream.processed; buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0; SeqCheckInStream_GetDigest(&checkInStream, buf + 4); RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))) blockSizes->totalSize = seqSizeOutStream.processed - padSize; if (!outStream) { seqSizeOutStream.outBuf = outBufHeader; seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX; seqSizeOutStream.processed = 0; block.unpackSize = blockSizes->unpackSize; XzBlock_SetHasUnpackSize(&block) block.packSize = packSize; XzBlock_SetHasPackSize(&block) RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)) blockSizes->headerSize = (size_t)seqSizeOutStream.processed; blockSizes->totalSize += seqSizeOutStream.processed; } } if (inStream) *inStreamFinished = checkInStream.realStreamFinished; else { *inStreamFinished = False; if (checkInStream.processed != inBufSize) return SZ_ERROR_FAIL; } return SZ_OK; } typedef struct { ICompressProgress vt; ICompressProgressPtr progress; UInt64 inOffset; UInt64 outOffset; } CCompressProgress_XzEncOffset; static SRes CompressProgress_XzEncOffset_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) { const CCompressProgress_XzEncOffset *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CCompressProgress_XzEncOffset, vt); inSize += p->inOffset; outSize += p->outOffset; return ICompressProgress_Progress(p->progress, inSize, outSize); } struct CXzEnc { ISzAllocPtr alloc; ISzAllocPtr allocBig; CXzProps xzProps; UInt64 expectedDataSize; CXzEncIndex xzIndex; CLzma2WithFilters lzmaf_Items[MTCODER_THREADS_MAX]; size_t outBufSize; /* size of allocated outBufs[i] */ Byte *outBufs[MTCODER_BLOCKS_MAX]; #ifndef Z7_ST unsigned checkType; ISeqOutStreamPtr outStream; BoolInt mtCoder_WasConstructed; CMtCoder mtCoder; CXzEncBlockInfo EncBlocks[MTCODER_BLOCKS_MAX]; #endif }; static void XzEnc_Construct(CXzEnc *p) { unsigned i; XzEncIndex_Construct(&p->xzIndex); for (i = 0; i < MTCODER_THREADS_MAX; i++) Lzma2WithFilters_Construct(&p->lzmaf_Items[i]); #ifndef Z7_ST p->mtCoder_WasConstructed = False; { for (i = 0; i < MTCODER_BLOCKS_MAX; i++) p->outBufs[i] = NULL; p->outBufSize = 0; } #endif } static void XzEnc_FreeOutBufs(CXzEnc *p) { unsigned i; for (i = 0; i < MTCODER_BLOCKS_MAX; i++) if (p->outBufs[i]) { ISzAlloc_Free(p->alloc, p->outBufs[i]); p->outBufs[i] = NULL; } p->outBufSize = 0; } static void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc) { unsigned i; XzEncIndex_Free(&p->xzIndex, alloc); for (i = 0; i < MTCODER_THREADS_MAX; i++) Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc); #ifndef Z7_ST if (p->mtCoder_WasConstructed) { MtCoder_Destruct(&p->mtCoder); p->mtCoder_WasConstructed = False; } XzEnc_FreeOutBufs(p); #endif } CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) { CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc)); if (!p) return NULL; XzEnc_Construct(p); XzProps_Init(&p->xzProps); XzProps_Normalize(&p->xzProps); p->expectedDataSize = (UInt64)(Int64)-1; p->alloc = alloc; p->allocBig = allocBig; return (CXzEncHandle)p; } // #define GET_CXzEnc_p CXzEnc *p = (CXzEnc *)(void *)pp; void XzEnc_Destroy(CXzEncHandle p) { // GET_CXzEnc_p XzEnc_Free(p, p->alloc); ISzAlloc_Free(p->alloc, p); } SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props) { // GET_CXzEnc_p p->xzProps = *props; XzProps_Normalize(&p->xzProps); return SZ_OK; } void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize) { // GET_CXzEnc_p p->expectedDataSize = expectedDataSiize; } #ifndef Z7_ST static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, const Byte *src, size_t srcSize, int finished) { CXzEnc *me = (CXzEnc *)pp; SRes res; CMtProgressThunk progressThunk; Byte *dest; UNUSED_VAR(finished) { CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; bInfo->totalSize = 0; bInfo->unpackSize = 0; bInfo->headerSize = 0; // v23.02: we don't compress empty blocks // also we must ignore that empty block in XzEnc_MtCallback_Write() if (srcSize == 0) return SZ_OK; } dest = me->outBufs[outBufIndex]; if (!dest) { dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); if (!dest) return SZ_ERROR_MEM; me->outBufs[outBufIndex] = dest; } MtProgressThunk_CreateVTable(&progressThunk); progressThunk.mtProgress = &me->mtCoder.mtProgress; MtProgressThunk_INIT(&progressThunk) { CXzEncBlockInfo blockSizes; int inStreamFinished; res = Xz_CompressBlock( &me->lzmaf_Items[coderIndex], NULL, dest, dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX, NULL, // srcSize, // expectedSize src, srcSize, &me->xzProps, &progressThunk.vt, &inStreamFinished, &blockSizes, me->alloc, me->allocBig); if (res == SZ_OK) me->EncBlocks[outBufIndex] = blockSizes; return res; } } static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) { CXzEnc *me = (CXzEnc *)pp; const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; // v23.02: we don't write empty blocks // note: if (bInfo->unpackSize == 0) then there is no compressed data of block if (bInfo->unpackSize == 0) return SZ_OK; { const Byte *data = me->outBufs[outBufIndex]; RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)) { const UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)) } return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc); } } #endif SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress) { // GET_CXzEnc_p const CXzProps *props = &p->xzProps; XzEncIndex_Init(&p->xzIndex); { UInt64 numBlocks = 1; UInt64 blockSize = props->blockSize; if (blockSize != XZ_PROPS_BLOCK_SIZE_SOLID && props->reduceSize != (UInt64)(Int64)-1) { numBlocks = props->reduceSize / blockSize; if (numBlocks * blockSize != props->reduceSize) numBlocks++; } else blockSize = (UInt64)1 << 62; RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc)) } RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream)) #ifndef Z7_ST if (props->numBlockThreads_Reduced > 1) { IMtCoderCallback2 vt; if (!p->mtCoder_WasConstructed) { p->mtCoder_WasConstructed = True; MtCoder_Construct(&p->mtCoder); } vt.Code = XzEnc_MtCallback_Code; vt.Write = XzEnc_MtCallback_Write; p->checkType = props->checkId; p->xzProps = *props; p->outStream = outStream; p->mtCoder.allocBig = p->allocBig; p->mtCoder.progress = progress; p->mtCoder.inStream = inStream; p->mtCoder.inData = NULL; p->mtCoder.inDataSize = 0; p->mtCoder.mtCallback = &vt; p->mtCoder.mtCallbackObject = p; if ( props->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID || props->blockSize == XZ_PROPS_BLOCK_SIZE_AUTO) return SZ_ERROR_FAIL; p->mtCoder.blockSize = (size_t)props->blockSize; if (p->mtCoder.blockSize != props->blockSize) return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ { size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize); if (destBlockSize < p->mtCoder.blockSize) return SZ_ERROR_PARAM; if (p->outBufSize != destBlockSize) XzEnc_FreeOutBufs(p); p->outBufSize = destBlockSize; } p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max; p->mtCoder.expectedDataSize = p->expectedDataSize; RINOK(MtCoder_Code(&p->mtCoder)) } else #endif { int writeStartSizes; CCompressProgress_XzEncOffset progress2; Byte *bufData = NULL; size_t bufSize = 0; progress2.vt.Progress = CompressProgress_XzEncOffset_Progress; progress2.inOffset = 0; progress2.outOffset = 0; progress2.progress = progress; writeStartSizes = 0; if (props->blockSize != XZ_PROPS_BLOCK_SIZE_SOLID) { writeStartSizes = (props->forceWriteSizesInHeader > 0); if (writeStartSizes) { size_t t2; size_t t = (size_t)props->blockSize; if (t != props->blockSize) return SZ_ERROR_PARAM; t = XZ_GET_MAX_BLOCK_PACK_SIZE(t); if (t < props->blockSize) return SZ_ERROR_PARAM; t2 = XZ_BLOCK_HEADER_SIZE_MAX + t; if (!p->outBufs[0] || t2 != p->outBufSize) { XzEnc_FreeOutBufs(p); p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2); if (!p->outBufs[0]) return SZ_ERROR_MEM; p->outBufSize = t2; } bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX; bufSize = t; } } for (;;) { CXzEncBlockInfo blockSizes; int inStreamFinished; /* UInt64 rem = (UInt64)(Int64)-1; if (props->reduceSize != (UInt64)(Int64)-1 && props->reduceSize >= progress2.inOffset) rem = props->reduceSize - progress2.inOffset; */ blockSizes.headerSize = 0; // for GCC RINOK(Xz_CompressBlock( &p->lzmaf_Items[0], writeStartSizes ? NULL : outStream, writeStartSizes ? p->outBufs[0] : NULL, bufData, bufSize, inStream, // rem, NULL, 0, props, progress ? &progress2.vt : NULL, &inStreamFinished, &blockSizes, p->alloc, p->allocBig)) { UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize); if (writeStartSizes) { RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize)) RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize)) } RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc)) progress2.inOffset += blockSizes.unpackSize; progress2.outOffset += totalPackFull; } if (inStreamFinished) break; } } return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream); } #include "Alloc.h" SRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, const CXzProps *props, ICompressProgressPtr progress) { SRes res; CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc); if (!xz) return SZ_ERROR_MEM; res = XzEnc_SetProps(xz, props); if (res == SZ_OK) res = XzEnc_Encode(xz, outStream, inStream, progress); XzEnc_Destroy(xz); return res; } SRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream) { SRes res; CXzEncIndex xzIndex; XzEncIndex_Construct(&xzIndex); res = Xz_WriteHeader((CXzStreamFlags)0, outStream); if (res == SZ_OK) res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream); XzEncIndex_Free(&xzIndex, NULL); // g_Alloc return res; } tmp41wklro_/C/XzEnc.h0000444000175000001440000000266514415733200015533 0ustar nabijaczleweliusers/* XzEnc.h -- Xz Encode 2023-04-13 : Igor Pavlov : Public domain */ #ifndef ZIP7_INC_XZ_ENC_H #define ZIP7_INC_XZ_ENC_H #include "Lzma2Enc.h" #include "Xz.h" EXTERN_C_BEGIN #define XZ_PROPS_BLOCK_SIZE_AUTO LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO #define XZ_PROPS_BLOCK_SIZE_SOLID LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID typedef struct { UInt32 id; UInt32 delta; UInt32 ip; int ipDefined; } CXzFilterProps; void XzFilterProps_Init(CXzFilterProps *p); typedef struct { CLzma2EncProps lzma2Props; CXzFilterProps filterProps; unsigned checkId; UInt64 blockSize; int numBlockThreads_Reduced; int numBlockThreads_Max; int numTotalThreads; int forceWriteSizesInHeader; UInt64 reduceSize; } CXzProps; void XzProps_Init(CXzProps *p); typedef struct CXzEnc CXzEnc; typedef CXzEnc * CXzEncHandle; // Z7_DECLARE_HANDLE(CXzEncHandle) CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); void XzEnc_Destroy(CXzEncHandle p); SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props); void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize); SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress); SRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, const CXzProps *props, ICompressProgressPtr progress); SRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream); EXTERN_C_END #endif tmp41wklro_/C/XzIn.c0000444000175000001440000002175214476344520015377 0ustar nabijaczleweliusers/* XzIn.c - Xz input 2023-09-07 : Igor Pavlov : Public domain */ #include "Precomp.h" #include #include "7zCrc.h" #include "CpuArch.h" #include "Xz.h" /* #define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0) */ #define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1) SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream) { Byte sig[XZ_STREAM_HEADER_SIZE]; size_t processedSize = XZ_STREAM_HEADER_SIZE; RINOK(SeqInStream_ReadMax(inStream, sig, &processedSize)) if (processedSize != XZ_STREAM_HEADER_SIZE || memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) return SZ_ERROR_NO_ARCHIVE; return Xz_ParseHeader(p, sig); } #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ if (s == 0) return SZ_ERROR_ARCHIVE; \ pos += s; } SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes) { Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; unsigned headerSize; *headerSizeRes = 0; RINOK(SeqInStream_ReadByte(inStream, &header[0])) headerSize = header[0]; if (headerSize == 0) { *headerSizeRes = 1; *isIndex = True; return SZ_OK; } *isIndex = False; headerSize = (headerSize << 2) + 4; *headerSizeRes = (UInt32)headerSize; { size_t processedSize = headerSize - 1; RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize)) if (processedSize != headerSize - 1) return SZ_ERROR_INPUT_EOF; } return XzBlock_Parse(p, header); } #define ADD_SIZE_CHECK(size, val) \ { const UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } UInt64 Xz_GetUnpackSize(const CXzStream *p) { UInt64 size = 0; size_t i; for (i = 0; i < p->numBlocks; i++) { ADD_SIZE_CHECK(size, p->blocks[i].unpackSize) } return size; } UInt64 Xz_GetPackSize(const CXzStream *p) { UInt64 size = 0; size_t i; for (i = 0; i < p->numBlocks; i++) { ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3) } return size; } /* SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStreamPtr inStream) { return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); } */ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) { size_t numBlocks, pos = 1; UInt32 crc; if (size < 5 || buf[0] != 0) return SZ_ERROR_ARCHIVE; size -= 4; crc = CrcCalc(buf, size); if (crc != GetUi32(buf + size)) return SZ_ERROR_ARCHIVE; { UInt64 numBlocks64; READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64) numBlocks = (size_t)numBlocks64; if (numBlocks != numBlocks64 || numBlocks * 2 > size) return SZ_ERROR_ARCHIVE; } Xz_Free(p, alloc); if (numBlocks != 0) { size_t i; p->numBlocks = numBlocks; p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); if (!p->blocks) return SZ_ERROR_MEM; for (i = 0; i < numBlocks; i++) { CXzBlockSizes *block = &p->blocks[i]; READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize) READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize) if (block->totalSize == 0) return SZ_ERROR_ARCHIVE; } } while ((pos & 3) != 0) if (buf[pos++] != 0) return SZ_ERROR_ARCHIVE; return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; } static SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc) { SRes res; size_t size; Byte *buf; if (indexSize > ((UInt32)1 << 31)) return SZ_ERROR_UNSUPPORTED; size = (size_t)indexSize; if (size != indexSize) return SZ_ERROR_UNSUPPORTED; buf = (Byte *)ISzAlloc_Alloc(alloc, size); if (!buf) return SZ_ERROR_MEM; res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); if (res == SZ_OK) res = Xz_ReadIndex2(p, buf, size, alloc); ISzAlloc_Free(alloc, buf); return res; } static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size) { RINOK(LookInStream_SeekTo(stream, offset)) return LookInStream_Read(stream, buf, size); /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ } static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc) { UInt64 indexSize; Byte buf[XZ_STREAM_FOOTER_SIZE]; UInt64 pos = (UInt64)*startOffset; if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; pos -= XZ_STREAM_FOOTER_SIZE; RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) if (!XZ_FOOTER_SIG_CHECK(buf + 10)) { UInt32 total = 0; pos += XZ_STREAM_FOOTER_SIZE; for (;;) { size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte temp[TEMP_BUF_SIZE]; i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; pos -= i; RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)) total += (UInt32)i; for (; i != 0; i--) if (temp[i - 1] != 0) break; if (i != 0) { if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; pos += i; break; } if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; } if (pos < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; pos -= XZ_STREAM_FOOTER_SIZE; RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) if (!XZ_FOOTER_SIG_CHECK(buf + 10)) return SZ_ERROR_NO_ARCHIVE; } p->flags = (CXzStreamFlags)GetBe16(buf + 8); if (!XzFlags_IsSupported(p->flags)) return SZ_ERROR_UNSUPPORTED; { /* to eliminate GCC 6.3 warning: dereferencing type-punned pointer will break strict-aliasing rules */ const Byte *buf_ptr = buf; if (GetUi32(buf_ptr) != CrcCalc(buf + 4, 6)) return SZ_ERROR_ARCHIVE; } indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; if (pos < indexSize) return SZ_ERROR_ARCHIVE; pos -= indexSize; RINOK(LookInStream_SeekTo(stream, pos)) RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)) { UInt64 totalSize = Xz_GetPackSize(p); if (totalSize == XZ_SIZE_OVERFLOW || totalSize >= ((UInt64)1 << 63) || pos < totalSize + XZ_STREAM_HEADER_SIZE) return SZ_ERROR_ARCHIVE; pos -= (totalSize + XZ_STREAM_HEADER_SIZE); RINOK(LookInStream_SeekTo(stream, pos)) *startOffset = (Int64)pos; } { CXzStreamFlags headerFlags; CSecToRead secToRead; SecToRead_CreateVTable(&secToRead); secToRead.realStream = stream; RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)) return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; } } /* ---------- Xz Streams ---------- */ void Xzs_Construct(CXzs *p) { p->num = p->numAllocated = 0; p->streams = 0; } void Xzs_Free(CXzs *p, ISzAllocPtr alloc) { size_t i; for (i = 0; i < p->num; i++) Xz_Free(&p->streams[i], alloc); ISzAlloc_Free(alloc, p->streams); p->num = p->numAllocated = 0; p->streams = 0; } UInt64 Xzs_GetNumBlocks(const CXzs *p) { UInt64 num = 0; size_t i; for (i = 0; i < p->num; i++) num += p->streams[i].numBlocks; return num; } UInt64 Xzs_GetUnpackSize(const CXzs *p) { UInt64 size = 0; size_t i; for (i = 0; i < p->num; i++) { ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i])) } return size; } /* UInt64 Xzs_GetPackSize(const CXzs *p) { UInt64 size = 0; size_t i; for (i = 0; i < p->num; i++) { ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i])) } return size; } */ SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc) { Int64 endOffset = 0; RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)) *startOffset = endOffset; for (;;) { CXzStream st; SRes res; Xz_Construct(&st); res = Xz_ReadBackward(&st, stream, startOffset, alloc); st.startOffset = (UInt64)*startOffset; RINOK(res) if (p->num == p->numAllocated) { const size_t newNum = p->num + p->num / 4 + 1; void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); if (!data) return SZ_ERROR_MEM; p->numAllocated = newNum; if (p->num != 0) memcpy(data, p->streams, p->num * sizeof(CXzStream)); ISzAlloc_Free(alloc, p->streams); p->streams = (CXzStream *)data; } p->streams[p->num++] = st; if (*startOffset == 0) break; RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset)) if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK) return SZ_ERROR_PROGRESS; } return SZ_OK; } tmp41wklro_/CPP/0000700000175000001440000000000014706260545014564 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/0000700000175000001440000000000014706260545015455 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/7zip.mak0000444000175000001440000001023114555655400017045 0ustar nabijaczleweliusersOBJS = \ $O\StdAfx.obj \ $(CURRENT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(WIN_CTRL_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AGENT_OBJS) \ $(CONSOLE_OBJS) \ $(EXPLORER_OBJS) \ $(FM_OBJS) \ $(GUI_OBJS) \ $(AR_COMMON_OBJS) \ $(AR_OBJS) \ $(7Z_OBJS) \ $(CAB_OBJS) \ $(CHM_OBJS) \ $(COM_OBJS) \ $(ISO_OBJS) \ $(NSIS_OBJS) \ $(RAR_OBJS) \ $(TAR_OBJS) \ $(UDF_OBJS) \ $(WIM_OBJS) \ $(ZIP_OBJS) \ $(COMPRESS_OBJS) \ $(CRYPTO_OBJS) \ $(C_OBJS) \ $(ASM_OBJS) \ $O\resource.res \ !include "../../../Build.mak" # MAK_SINGLE_FILE = 1 !IFDEF MAK_SINGLE_FILE !IFDEF CURRENT_OBJS $(CURRENT_OBJS): ./$(*B).cpp $(COMPL) !ENDIF !IFDEF COMMON_OBJS $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) !ENDIF !IFDEF WIN_OBJS $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) !ENDIF !IFDEF WIN_CTRL_OBJS $(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp $(COMPL) !ENDIF !IFDEF 7ZIP_COMMON_OBJS $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) !ENDIF !IFDEF AR_OBJS $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) !ENDIF !IFDEF AR_COMMON_OBJS $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) !ENDIF !IFDEF 7Z_OBJS $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) !ENDIF !IFDEF CAB_OBJS $(CAB_OBJS): ../../Archive/Cab/$(*B).cpp $(COMPL) !ENDIF !IFDEF CHM_OBJS $(CHM_OBJS): ../../Archive/Chm/$(*B).cpp $(COMPL) !ENDIF !IFDEF COM_OBJS $(COM_OBJS): ../../Archive/Com/$(*B).cpp $(COMPL) !ENDIF !IFDEF ISO_OBJS $(ISO_OBJS): ../../Archive/Iso/$(*B).cpp $(COMPL) !ENDIF !IFDEF NSIS_OBJS $(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp $(COMPL) !ENDIF !IFDEF RAR_OBJS $(RAR_OBJS): ../../Archive/Rar/$(*B).cpp $(COMPL) !ENDIF !IFDEF TAR_OBJS $(TAR_OBJS): ../../Archive/Tar/$(*B).cpp $(COMPL) !ENDIF !IFDEF UDF_OBJS $(UDF_OBJS): ../../Archive/Udf/$(*B).cpp $(COMPL) !ENDIF !IFDEF WIM_OBJS $(WIM_OBJS): ../../Archive/Wim/$(*B).cpp $(COMPL) !ENDIF !IFDEF ZIP_OBJS $(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp $(COMPL) $(ZIP_FLAGS) !ENDIF !IFDEF COMPRESS_OBJS $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) !ENDIF !IFDEF CRYPTO_OBJS $(CRYPTO_OBJS): ../../Crypto/$(*B).cpp $(COMPL_O2) !ENDIF !IFDEF UI_COMMON_OBJS $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) !ENDIF !IFDEF AGENT_OBJS $(AGENT_OBJS): ../../UI/Agent/$(*B).cpp $(COMPL) !ENDIF !IFDEF CONSOLE_OBJS $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(CONSOLE_VARIANT_FLAGS) !ENDIF !IFDEF EXPLORER_OBJS $(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp $(COMPL) !ENDIF !IFDEF FM_OBJS $(FM_OBJS): ../../UI/FileManager/$(*B).cpp $(COMPL) !ENDIF !IFDEF GUI_OBJS $(GUI_OBJS): ../../UI/GUI/$(*B).cpp $(COMPL) !ENDIF !IFDEF C_OBJS $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !ENDIF !ELSE {.}.cpp{$O}.obj:: $(COMPLB) {../../../Common}.cpp{$O}.obj:: $(COMPLB) {../../../Windows}.cpp{$O}.obj:: $(COMPLB) {../../../Windows/Control}.cpp{$O}.obj:: $(COMPLB) {../../Common}.cpp{$O}.obj:: $(COMPLB) {../../UI/Common}.cpp{$O}.obj:: $(COMPLB) {../../UI/Agent}.cpp{$O}.obj:: $(COMPLB) {../../UI/Console}.cpp{$O}.obj:: $(COMPLB) $(CONSOLE_VARIANT_FLAGS) {../../UI/Explorer}.cpp{$O}.obj:: $(COMPLB) {../../UI/FileManager}.cpp{$O}.obj:: $(COMPLB) {../../UI/GUI}.cpp{$O}.obj:: $(COMPLB) {../../Archive}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Common}.cpp{$O}.obj:: $(COMPLB) {../../Archive/7z}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Cab}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Chm}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Com}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Iso}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Nsis}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Rar}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Tar}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Udf}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Wim}.cpp{$O}.obj:: $(COMPLB) {../../Archive/Zip}.cpp{$O}.obj:: $(COMPLB) $(ZIP_FLAGS) {../../Compress}.cpp{$O}.obj:: $(COMPLB_O2) {../../Crypto}.cpp{$O}.obj:: $(COMPLB_O2) {../../../../C}.c{$O}.obj:: $(CCOMPLB) !ENDIF !include "Asm.mak" tmp41wklro_/CPP/7zip/7zip_gcc.mak0000444000175000001440000011710214633515600017660 0ustar nabijaczleweliusers# USE_CLANG=1 # USE_ASM = 1 # IS_X64 = 1 # MY_ARCH = # USE_ASM= # USE_JWASM=1 MY_ARCH_2 = $(MY_ARCH) MY_ASM = asmc ifdef USE_JWASM MY_ASM = jwasm endif ifndef RC RC=windres.exe --target=pe-x86-64 RC=windres.exe -F pe-i386 RC=windres.exe endif PROGPATH = $(O)/$(PROG) PROGPATH_STATIC = $(O)/$(PROG)s ifneq ($(CC), xlc) CFLAGS_WARN_WALL = -Werror -Wall -Wextra endif # for object file # -Wa,-aln=test.s # -save-temps FLAGS_BASE = -mbranch-protection=standard -march=armv8.5-a FLAGS_BASE = -mbranch-protection=standard FLAGS_BASE = # FLAGS_BASE = -DZ7_NO_UNICODE CFLAGS_BASE_LIST = -c #DEBUG_BUILD=1 ifdef DEBUG_BUILD CFLAGS_DEBUG = -g else CFLAGS_DEBUG = -DNDEBUG ifneq ($(CC), $(CROSS_COMPILE)clang) LFLAGS_STRIP = -s endif endif # CFLAGS_BASE_LIST = -S CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ $(CFLAGS_DEBUG) -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ -fPIC FLAGS_FLTO = -ffunction-sections FLAGS_FLTO = -flto FLAGS_FLTO = $(FLAGS_BASE) # -DZ7_AFFINITY_DISABLE ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif ifdef IS_MINGW LDFLAGS_STATIC_2 = -static else ifndef DEF_FILE ifndef IS_NOT_STANDALONE ifndef MY_DYNAMIC_LINK ifneq ($(CC), clang) LDFLAGS_STATIC_2 = # -static # -static-libstdc++ -static-libgcc endif endif endif endif endif LDFLAGS_STATIC = $(CFLAGS_DEBUG) $(LDFLAGS_STATIC_2) $(LDFLAGS_STATIC_3) ifndef O ifdef IS_MINGW O=_o else O=_o endif endif ifdef DEF_FILE ifdef IS_MINGW SHARED_EXT=.dll LDFLAGS = -shared -DEF $(DEF_FILE) $(LDFLAGS_STATIC) else SHARED_EXT=.so LDFLAGS = -shared -fPIC $(LDFLAGS_STATIC) CC_SHARED=-fPIC endif else LDFLAGS = $(LDFLAGS_STATIC) # -z force-bti # -s is not required for clang, do we need it for GCC ??? #-static -static-libgcc -static-libstdc++ ifdef IS_MINGW SHARED_EXT=.exe else SHARED_EXT= endif endif PROGPATH = $(O)/$(PROG)$(SHARED_EXT) PROGPATH_STATIC = $(O)/$(PROG)s$(SHARED_EXT) ifdef IS_MINGW ifdef MSYSTEM RM = rm -f MY_MKDIR=mkdir -p DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) LIB_HTMLHELP=-lhtmlhelp else RM = del MY_MKDIR=mkdir DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll endif LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP) LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files # CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE # -Wno-delete-non-virtual-dtor else RM = rm -f MY_MKDIR=mkdir -p DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) # CFLAGS_BASE := $(CFLAGS_BASE) -DZ7_ST # CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE # LOCAL_LIBS=-lpthread # LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl LIB2 = -lpthread LIB2 = -lpthread -ldl endif CFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(FLAGS_FLTO) $(CC_SHARED) -o $@ ifdef IS_MINGW ifdef IS_X64 AFLAGS_ABI = -win64 else AFLAGS_ABI = -coff -DABI_CDECL # -DABI_CDECL # -DABI_LINUX # -DABI_CDECL endif AFLAGS = -nologo $(AFLAGS_ABI) -Fo$(O)/$(basename $(/dev/null && echo -z noexecstack || echo) endif endif LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(LFLAGS_NOEXECSTACK) $(OBJS) $(MY_LIBS) $(LIB2) # -s : GCC : Remove all symbol table and relocation information from the executable. # -s : CLANG : unsupported # -s $(PROGPATH): $(OBJS) $(CXX) -o $(PROGPATH) $(LFLAGS_ALL) $(PROGPATH_STATIC): $(OBJS) $(CXX) -static -o $(PROGPATH_STATIC) $(LFLAGS_ALL) # -s strips debug sections from executable in GCC ifndef NO_DEFAULT_RES $O/resource.o: resource.rc $(RC) $(RFLAGS) resource.rc $@ # windres.exe : in old version mingw: # $(RFLAGS) resource.rc $O/resource.o # windres.exe : in new version mingw: # $(RC) $(RFLAGS) resource.rc -FO $@ endif $O/LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CXXFLAGS) $< $O/CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CXXFLAGS) $< $O/CRC.o: ../../../Common/CRC.cpp $(CXX) $(CXXFLAGS) $< $O/CrcReg.o: ../../../Common/CrcReg.cpp $(CXX) $(CXXFLAGS) $< $O/DynLimBuf.o: ../../../Common/DynLimBuf.cpp $(CXX) $(CXXFLAGS) $< $O/IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CXXFLAGS) $< $O/Lang.o: ../../../Common/Lang.cpp $(CXX) $(CXXFLAGS) $< $O/ListFileUtils.o: ../../../Common/ListFileUtils.cpp $(CXX) $(CXXFLAGS) $< $O/LzFindPrepare.o: ../../../Common/LzFindPrepare.cpp $(CXX) $(CXXFLAGS) $< $O/MyMap.o: ../../../Common/MyMap.cpp $(CXX) $(CXXFLAGS) $< $O/MyString.o: ../../../Common/MyString.cpp $(CXX) $(CXXFLAGS) $< $O/MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CXXFLAGS) $< $O/MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CXXFLAGS) $< $O/MyWindows2.o: ../../../Common/MyWindows2.cpp $(CXX) $(CXXFLAGS) $< $O/MyXml.o: ../../../Common/MyXml.cpp $(CXX) $(CXXFLAGS) $< $O/NewHandler.o: ../../../Common/NewHandler.cpp $(CXX) $(CXXFLAGS) $< $O/Random.o: ../../../Common/Random.cpp $(CXX) $(CXXFLAGS) $< $O/Sha1Prepare.o: ../../../Common/Sha1Prepare.cpp $(CXX) $(CXXFLAGS) $< $O/Sha1Reg.o: ../../../Common/Sha1Reg.cpp $(CXX) $(CXXFLAGS) $< $O/Sha256Prepare.o: ../../../Common/Sha256Prepare.cpp $(CXX) $(CXXFLAGS) $< $O/Sha256Reg.o: ../../../Common/Sha256Reg.cpp $(CXX) $(CXXFLAGS) $< $O/StdInStream.o: ../../../Common/StdInStream.cpp $(CXX) $(CXXFLAGS) $< $O/StdOutStream.o: ../../../Common/StdOutStream.cpp $(CXX) $(CXXFLAGS) $< $O/StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CXXFLAGS) $< $O/StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CXXFLAGS) $< $O/TextConfig.o: ../../../Common/TextConfig.cpp $(CXX) $(CXXFLAGS) $< $O/UTFConvert.o: ../../../Common/UTFConvert.cpp $(CXX) $(CXXFLAGS) $< $O/Wildcard.o: ../../../Common/Wildcard.cpp $(CXX) $(CXXFLAGS) $< $O/XzCrc64Init.o: ../../../Common/XzCrc64Init.cpp $(CXX) $(CXXFLAGS) $< $O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp $(CXX) $(CXXFLAGS) $< $O/Xxh64Reg.o: ../../../Common/Xxh64Reg.cpp $(CXX) $(CXXFLAGS) $< $O/Clipboard.o: ../../../Windows/Clipboard.cpp $(CXX) $(CXXFLAGS) $< $O/COM.o: ../../../Windows/COM.cpp $(CXX) $(CXXFLAGS) $< $O/CommonDialog.o: ../../../Windows/CommonDialog.cpp $(CXX) $(CXXFLAGS) $< $O/Console.o: ../../../Windows/Console.cpp $(CXX) $(CXXFLAGS) $< $O/DLL.o: ../../../Windows/DLL.cpp $(CXX) $(CXXFLAGS) $< $O/ErrorMsg.o: ../../../Windows/ErrorMsg.cpp $(CXX) $(CXXFLAGS) $< $O/FileDir.o: ../../../Windows/FileDir.cpp $(CXX) $(CXXFLAGS) $< $O/FileFind.o: ../../../Windows/FileFind.cpp $(CXX) $(CXXFLAGS) $< $O/FileIO.o: ../../../Windows/FileIO.cpp $(CXX) $(CXXFLAGS) $< $O/FileLink.o: ../../../Windows/FileLink.cpp $(CXX) $(CXXFLAGS) $< $O/FileMapping.o: ../../../Windows/FileMapping.cpp $(CXX) $(CXXFLAGS) $< $O/FileName.o: ../../../Windows/FileName.cpp $(CXX) $(CXXFLAGS) $< $O/FileSystem.o: ../../../Windows/FileSystem.cpp $(CXX) $(CXXFLAGS) $< $O/MemoryGlobal.o: ../../../Windows/MemoryGlobal.cpp $(CXX) $(CXXFLAGS) $< $O/MemoryLock.o: ../../../Windows/MemoryLock.cpp $(CXX) $(CXXFLAGS) $< $O/Menu.o: ../../../Windows/Menu.cpp $(CXX) $(CXXFLAGS) $< $O/NationalTime.o: ../../../Windows/NationalTime.cpp $(CXX) $(CXXFLAGS) $< $O/Net.o: ../../../Windows/Net.cpp $(CXX) $(CXXFLAGS) $< $O/ProcessMessages.o: ../../../Windows/ProcessMessages.cpp $(CXX) $(CXXFLAGS) $< $O/ProcessUtils.o: ../../../Windows/ProcessUtils.cpp $(CXX) $(CXXFLAGS) $< $O/PropVariant.o: ../../../Windows/PropVariant.cpp $(CXX) $(CXXFLAGS) $< $O/PropVariantConv.o: ../../../Windows/PropVariantConv.cpp $(CXX) $(CXXFLAGS) $< $O/PropVariantUtils.o: ../../../Windows/PropVariantUtils.cpp $(CXX) $(CXXFLAGS) $< $O/Registry.o: ../../../Windows/Registry.cpp $(CXX) $(CXXFLAGS) $< $O/ResourceString.o: ../../../Windows/ResourceString.cpp $(CXX) $(CXXFLAGS) $< $O/SecurityUtils.o: ../../../Windows/SecurityUtils.cpp $(CXX) $(CXXFLAGS) $< $O/Shell.o: ../../../Windows/Shell.cpp $(CXX) $(CXXFLAGS) $< $O/Synchronization.o: ../../../Windows/Synchronization.cpp $(CXX) $(CXXFLAGS) $< $O/System.o: ../../../Windows/System.cpp $(CXX) $(CXXFLAGS) $< $O/SystemInfo.o: ../../../Windows/SystemInfo.cpp $(CXX) $(CXXFLAGS) $< $O/TimeUtils.o: ../../../Windows/TimeUtils.cpp $(CXX) $(CXXFLAGS) $< $O/Window.o: ../../../Windows/Window.cpp $(CXX) $(CXXFLAGS) $< $O/ComboBox.o: ../../../Windows/Control/ComboBox.cpp $(CXX) $(CXXFLAGS) $< $O/Dialog.o: ../../../Windows/Control/Dialog.cpp $(CXX) $(CXXFLAGS) $< $O/ImageList.o: ../../../Windows/Control/ImageList.cpp $(CXX) $(CXXFLAGS) $< $O/ListView.o: ../../../Windows/Control/ListView.cpp $(CXX) $(CXXFLAGS) $< $O/PropertyPage.o: ../../../Windows/Control/PropertyPage.cpp $(CXX) $(CXXFLAGS) $< $O/Window2.o: ../../../Windows/Control/Window2.cpp $(CXX) $(CXXFLAGS) $< $O/CreateCoder.o: ../../Common/CreateCoder.cpp $(CXX) $(CXXFLAGS) $< $O/CWrappers.o: ../../Common/CWrappers.cpp $(CXX) $(CXXFLAGS) $< $O/FilePathAutoRename.o: ../../Common/FilePathAutoRename.cpp $(CXX) $(CXXFLAGS) $< $O/FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CXXFLAGS) $< $O/FilterCoder.o: ../../Common/FilterCoder.cpp $(CXX) $(CXXFLAGS) $< $O/InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CXXFLAGS) $< $O/InOutTempBuffer.o: ../../Common/InOutTempBuffer.cpp $(CXX) $(CXXFLAGS) $< $O/LimitedStreams.o: ../../Common/LimitedStreams.cpp $(CXX) $(CXXFLAGS) $< $O/LockedStream.o: ../../Common/LockedStream.cpp $(CXX) $(CXXFLAGS) $< $O/MemBlocks.o: ../../Common/MemBlocks.cpp $(CXX) $(CXXFLAGS) $< $O/MethodId.o: ../../Common/MethodId.cpp $(CXX) $(CXXFLAGS) $< $O/MethodProps.o: ../../Common/MethodProps.cpp $(CXX) $(CXXFLAGS) $< $O/MultiOutStream.o: ../../Common/MultiOutStream.cpp $(CXX) $(CXXFLAGS) $< $O/OffsetStream.o: ../../Common/OffsetStream.cpp $(CXX) $(CXXFLAGS) $< $O/OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CXXFLAGS) $< $O/OutMemStream.o: ../../Common/OutMemStream.cpp $(CXX) $(CXXFLAGS) $< $O/ProgressMt.o: ../../Common/ProgressMt.cpp $(CXX) $(CXXFLAGS) $< $O/ProgressUtils.o: ../../Common/ProgressUtils.cpp $(CXX) $(CXXFLAGS) $< $O/PropId.o: ../../Common/PropId.cpp $(CXX) $(CXXFLAGS) $< $O/StreamBinder.o: ../../Common/StreamBinder.cpp $(CXX) $(CXXFLAGS) $< $O/StreamObjects.o: ../../Common/StreamObjects.cpp $(CXX) $(CXXFLAGS) $< $O/StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CXXFLAGS) $< $O/UniqBlocks.o: ../../Common/UniqBlocks.cpp $(CXX) $(CXXFLAGS) $< $O/VirtThread.o: ../../Common/VirtThread.cpp $(CXX) $(CXXFLAGS) $< $O/ApfsHandler.o: ../../Archive/ApfsHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ApmHandler.o: ../../Archive/ApmHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveExports.o: ../../Archive/ArchiveExports.cpp $(CXX) $(CXXFLAGS) $< $O/ArHandler.o: ../../Archive/ArHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ArjHandler.o: ../../Archive/ArjHandler.cpp $(CXX) $(CXXFLAGS) $< $O/AvbHandler.o: ../../Archive/AvbHandler.cpp $(CXX) $(CXXFLAGS) $< $O/Base64Handler.o: ../../Archive/Base64Handler.cpp $(CXX) $(CXXFLAGS) $< $O/Bz2Handler.o: ../../Archive/Bz2Handler.cpp $(CXX) $(CXXFLAGS) $< $O/ComHandler.o: ../../Archive/ComHandler.cpp $(CXX) $(CXXFLAGS) $< $O/CpioHandler.o: ../../Archive/CpioHandler.cpp $(CXX) $(CXXFLAGS) $< $O/CramfsHandler.o: ../../Archive/CramfsHandler.cpp $(CXX) $(CXXFLAGS) $< $O/DeflateProps.o: ../../Archive/DeflateProps.cpp $(CXX) $(CXXFLAGS) $< $O/DllExports.o: ../../Archive/DllExports.cpp $(CXX) $(CXXFLAGS) $< $O/DllExports2.o: ../../Archive/DllExports2.cpp $(CXX) $(CXXFLAGS) $< $O/DmgHandler.o: ../../Archive/DmgHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ElfHandler.o: ../../Archive/ElfHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ExtHandler.o: ../../Archive/ExtHandler.cpp $(CXX) $(CXXFLAGS) $< $O/FatHandler.o: ../../Archive/FatHandler.cpp $(CXX) $(CXXFLAGS) $< $O/FlvHandler.o: ../../Archive/FlvHandler.cpp $(CXX) $(CXXFLAGS) $< $O/GptHandler.o: ../../Archive/GptHandler.cpp $(CXX) $(CXXFLAGS) $< $O/GzHandler.o: ../../Archive/GzHandler.cpp $(CXX) $(CXXFLAGS) $< $O/HandlerCont.o: ../../Archive/HandlerCont.cpp $(CXX) $(CXXFLAGS) $< $O/HfsHandler.o: ../../Archive/HfsHandler.cpp $(CXX) $(CXXFLAGS) $< $O/IhexHandler.o: ../../Archive/IhexHandler.cpp $(CXX) $(CXXFLAGS) $< $O/LpHandler.o: ../../Archive/LpHandler.cpp $(CXX) $(CXXFLAGS) $< $O/LvmHandler.o: ../../Archive/LvmHandler.cpp $(CXX) $(CXXFLAGS) $< $O/LzhHandler.o: ../../Archive/LzhHandler.cpp $(CXX) $(CXXFLAGS) $< $O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp $(CXX) $(CXXFLAGS) $< $O/MachoHandler.o: ../../Archive/MachoHandler.cpp $(CXX) $(CXXFLAGS) $< $O/MbrHandler.o: ../../Archive/MbrHandler.cpp $(CXX) $(CXXFLAGS) $< $O/MslzHandler.o: ../../Archive/MslzHandler.cpp $(CXX) $(CXXFLAGS) $< $O/MubHandler.o: ../../Archive/MubHandler.cpp $(CXX) $(CXXFLAGS) $< $O/NtfsHandler.o: ../../Archive/NtfsHandler.cpp $(CXX) $(CXXFLAGS) $< $O/PeHandler.o: ../../Archive/PeHandler.cpp $(CXX) $(CXXFLAGS) $< $O/PpmdHandler.o: ../../Archive/PpmdHandler.cpp $(CXX) $(CXXFLAGS) $< $O/QcowHandler.o: ../../Archive/QcowHandler.cpp $(CXX) $(CXXFLAGS) $< $O/RpmHandler.o: ../../Archive/RpmHandler.cpp $(CXX) $(CXXFLAGS) $< $O/SparseHandler.o: ../../Archive/SparseHandler.cpp $(CXX) $(CXXFLAGS) $< $O/SplitHandler.o: ../../Archive/SplitHandler.cpp $(CXX) $(CXXFLAGS) $< $O/SquashfsHandler.o: ../../Archive/SquashfsHandler.cpp $(CXX) $(CXXFLAGS) $< $O/SwfHandler.o: ../../Archive/SwfHandler.cpp $(CXX) $(CXXFLAGS) $< $O/UefiHandler.o: ../../Archive/UefiHandler.cpp $(CXX) $(CXXFLAGS) $< $O/VdiHandler.o: ../../Archive/VdiHandler.cpp $(CXX) $(CXXFLAGS) $< $O/VhdHandler.o: ../../Archive/VhdHandler.cpp $(CXX) $(CXXFLAGS) $< $O/VhdxHandler.o: ../../Archive/VhdxHandler.cpp $(CXX) $(CXXFLAGS) $< $O/VmdkHandler.o: ../../Archive/VmdkHandler.cpp $(CXX) $(CXXFLAGS) $< $O/XarHandler.o: ../../Archive/XarHandler.cpp $(CXX) $(CXXFLAGS) $< $O/XzHandler.o: ../../Archive/XzHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ZHandler.o: ../../Archive/ZHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ZstdHandler.o: ../../Archive/ZstdHandler.cpp $(CXX) $(CXXFLAGS) $< $O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp $(CXX) $(CXXFLAGS) $< $O/7zDecode.o: ../../Archive/7z/7zDecode.cpp $(CXX) $(CXXFLAGS) $< $O/7zEncode.o: ../../Archive/7z/7zEncode.cpp $(CXX) $(CXXFLAGS) $< $O/7zExtract.o: ../../Archive/7z/7zExtract.cpp $(CXX) $(CXXFLAGS) $< $O/7zFolderInStream.o: ../../Archive/7z/7zFolderInStream.cpp $(CXX) $(CXXFLAGS) $< $O/7zHandler.o: ../../Archive/7z/7zHandler.cpp $(CXX) $(CXXFLAGS) $< $O/7zHandlerOut.o: ../../Archive/7z/7zHandlerOut.cpp $(CXX) $(CXXFLAGS) $< $O/7zHeader.o: ../../Archive/7z/7zHeader.cpp $(CXX) $(CXXFLAGS) $< $O/7zIn.o: ../../Archive/7z/7zIn.cpp $(CXX) $(CXXFLAGS) $< $O/7zOut.o: ../../Archive/7z/7zOut.cpp $(CXX) $(CXXFLAGS) $< $O/7zProperties.o: ../../Archive/7z/7zProperties.cpp $(CXX) $(CXXFLAGS) $< $O/7zRegister.o: ../../Archive/7z/7zRegister.cpp $(CXX) $(CXXFLAGS) $< $O/7zSpecStream.o: ../../Archive/7z/7zSpecStream.cpp $(CXX) $(CXXFLAGS) $< $O/7zUpdate.o: ../../Archive/7z/7zUpdate.cpp $(CXX) $(CXXFLAGS) $< $O/CabBlockInStream.o: ../../Archive/Cab/CabBlockInStream.cpp $(CXX) $(CXXFLAGS) $< $O/CabHandler.o: ../../Archive/Cab/CabHandler.cpp $(CXX) $(CXXFLAGS) $< $O/CabHeader.o: ../../Archive/Cab/CabHeader.cpp $(CXX) $(CXXFLAGS) $< $O/CabIn.o: ../../Archive/Cab/CabIn.cpp $(CXX) $(CXXFLAGS) $< $O/CabRegister.o: ../../Archive/Cab/CabRegister.cpp $(CXX) $(CXXFLAGS) $< $O/ChmHandler.o: ../../Archive/Chm/ChmHandler.cpp $(CXX) $(CXXFLAGS) $< $O/ChmIn.o: ../../Archive/Chm/ChmIn.cpp $(CXX) $(CXXFLAGS) $< $O/IsoHandler.o: ../../Archive/Iso/IsoHandler.cpp $(CXX) $(CXXFLAGS) $< $O/IsoHeader.o: ../../Archive/Iso/IsoHeader.cpp $(CXX) $(CXXFLAGS) $< $O/IsoIn.o: ../../Archive/Iso/IsoIn.cpp $(CXX) $(CXXFLAGS) $< $O/IsoRegister.o: ../../Archive/Iso/IsoRegister.cpp $(CXX) $(CXXFLAGS) $< $O/NsisDecode.o: ../../Archive/Nsis/NsisDecode.cpp $(CXX) $(CXXFLAGS) $< $O/NsisHandler.o: ../../Archive/Nsis/NsisHandler.cpp $(CXX) $(CXXFLAGS) $< $O/NsisIn.o: ../../Archive/Nsis/NsisIn.cpp $(CXX) $(CXXFLAGS) $< $O/NsisRegister.o: ../../Archive/Nsis/NsisRegister.cpp $(CXX) $(CXXFLAGS) $< $O/Rar5Handler.o: ../../Archive/Rar/Rar5Handler.cpp $(CXX) $(CXXFLAGS) $< $O/RarHandler.o: ../../Archive/Rar/RarHandler.cpp $(CXX) $(CXXFLAGS) $< $O/TarHandler.o: ../../Archive/Tar/TarHandler.cpp $(CXX) $(CXXFLAGS) $< $O/TarHandlerOut.o: ../../Archive/Tar/TarHandlerOut.cpp $(CXX) $(CXXFLAGS) $< $O/TarHeader.o: ../../Archive/Tar/TarHeader.cpp $(CXX) $(CXXFLAGS) $< $O/TarIn.o: ../../Archive/Tar/TarIn.cpp $(CXX) $(CXXFLAGS) $< $O/TarOut.o: ../../Archive/Tar/TarOut.cpp $(CXX) $(CXXFLAGS) $< $O/TarRegister.o: ../../Archive/Tar/TarRegister.cpp $(CXX) $(CXXFLAGS) $< $O/TarUpdate.o: ../../Archive/Tar/TarUpdate.cpp $(CXX) $(CXXFLAGS) $< $O/UdfHandler.o: ../../Archive/Udf/UdfHandler.cpp $(CXX) $(CXXFLAGS) $< $O/UdfIn.o: ../../Archive/Udf/UdfIn.cpp $(CXX) $(CXXFLAGS) $< $O/WimHandler.o: ../../Archive/Wim/WimHandler.cpp $(CXX) $(CXXFLAGS) $< $O/WimHandlerOut.o: ../../Archive/Wim/WimHandlerOut.cpp $(CXX) $(CXXFLAGS) $< $O/WimIn.o: ../../Archive/Wim/WimIn.cpp $(CXX) $(CXXFLAGS) $< $O/WimRegister.o: ../../Archive/Wim/WimRegister.cpp $(CXX) $(CXXFLAGS) $< $O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp $(CXX) $(CXXFLAGS) $< $O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp $(CXX) $(CXXFLAGS) $(ZIP_FLAGS) $< $O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp $(CXX) $(CXXFLAGS) $< $O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp $(CXX) $(CXXFLAGS) $< $O/ZipItem.o: ../../Archive/Zip/ZipItem.cpp $(CXX) $(CXXFLAGS) $< $O/ZipOut.o: ../../Archive/Zip/ZipOut.cpp $(CXX) $(CXXFLAGS) $< $O/ZipUpdate.o: ../../Archive/Zip/ZipUpdate.cpp $(CXX) $(CXXFLAGS) $< $O/ZipRegister.o: ../../Archive/Zip/ZipRegister.cpp $(CXX) $(CXXFLAGS) $< $O/Bcj2Coder.o: ../../Compress/Bcj2Coder.cpp $(CXX) $(CXXFLAGS) $< $O/Bcj2Register.o: ../../Compress/Bcj2Register.cpp $(CXX) $(CXXFLAGS) $< $O/BcjCoder.o: ../../Compress/BcjCoder.cpp $(CXX) $(CXXFLAGS) $< $O/BcjRegister.o: ../../Compress/BcjRegister.cpp $(CXX) $(CXXFLAGS) $< $O/BitlDecoder.o: ../../Compress/BitlDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/BranchMisc.o: ../../Compress/BranchMisc.cpp $(CXX) $(CXXFLAGS) $< $O/BranchRegister.o: ../../Compress/BranchRegister.cpp $(CXX) $(CXXFLAGS) $< $O/ByteSwap.o: ../../Compress/ByteSwap.cpp $(CXX) $(CXXFLAGS) $< $O/BZip2Crc.o: ../../Compress/BZip2Crc.cpp $(CXX) $(CXXFLAGS) $< $O/BZip2Decoder.o: ../../Compress/BZip2Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/BZip2Encoder.o: ../../Compress/BZip2Encoder.cpp $(CXX) $(CXXFLAGS) $< $O/BZip2Register.o: ../../Compress/BZip2Register.cpp $(CXX) $(CXXFLAGS) $< $O/CodecExports.o: ../../Compress/CodecExports.cpp $(CXX) $(CXXFLAGS) $< $O/CopyCoder.o: ../../Compress/CopyCoder.cpp $(CXX) $(CXXFLAGS) $< $O/CopyRegister.o: ../../Compress/CopyRegister.cpp $(CXX) $(CXXFLAGS) $< $O/Deflate64Register.o: ../../Compress/Deflate64Register.cpp $(CXX) $(CXXFLAGS) $< $O/DeflateDecoder.o: ../../Compress/DeflateDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/DeflateEncoder.o: ../../Compress/DeflateEncoder.cpp $(CXX) $(CXXFLAGS) $< $O/DeflateRegister.o: ../../Compress/DeflateRegister.cpp $(CXX) $(CXXFLAGS) $< $O/DeltaFilter.o: ../../Compress/DeltaFilter.cpp $(CXX) $(CXXFLAGS) $< $O/DllExports2Compress.o: ../../Compress/DllExports2Compress.cpp $(CXX) $(CXXFLAGS) $< $O/DllExportsCompress.o: ../../Compress/DllExportsCompress.cpp $(CXX) $(CXXFLAGS) $< $O/ImplodeDecoder.o: ../../Compress/ImplodeDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/ImplodeHuffmanDecoder.o: ../../Compress/ImplodeHuffmanDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/LzfseDecoder.o: ../../Compress/LzfseDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/LzhDecoder.o: ../../Compress/LzhDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/Lzma2Decoder.o: ../../Compress/Lzma2Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/Lzma2Encoder.o: ../../Compress/Lzma2Encoder.cpp $(CXX) $(CXXFLAGS) $< $O/Lzma2Register.o: ../../Compress/Lzma2Register.cpp $(CXX) $(CXXFLAGS) $< $O/LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp $(CXX) $(CXXFLAGS) $< $O/LzmaRegister.o: ../../Compress/LzmaRegister.cpp $(CXX) $(CXXFLAGS) $< $O/LzmsDecoder.o: ../../Compress/LzmsDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/LzOutWindow.o: ../../Compress/LzOutWindow.cpp $(CXX) $(CXXFLAGS) $< $O/LzxDecoder.o: ../../Compress/LzxDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/PpmdDecoder.o: ../../Compress/PpmdDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/PpmdEncoder.o: ../../Compress/PpmdEncoder.cpp $(CXX) $(CXXFLAGS) $< $O/PpmdRegister.o: ../../Compress/PpmdRegister.cpp $(CXX) $(CXXFLAGS) $< $O/PpmdZip.o: ../../Compress/PpmdZip.cpp $(CXX) $(CXXFLAGS) $< $O/QuantumDecoder.o: ../../Compress/QuantumDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/Rar1Decoder.o: ../../Compress/Rar1Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/Rar2Decoder.o: ../../Compress/Rar2Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/Rar3Decoder.o: ../../Compress/Rar3Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/Rar3Vm.o: ../../Compress/Rar3Vm.cpp $(CXX) $(CXXFLAGS) $< $O/Rar5Decoder.o: ../../Compress/Rar5Decoder.cpp $(CXX) $(CXXFLAGS) $< $O/RarCodecsRegister.o: ../../Compress/RarCodecsRegister.cpp $(CXX) $(CXXFLAGS) $< $O/ShrinkDecoder.o: ../../Compress/ShrinkDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/XpressDecoder.o: ../../Compress/XpressDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/XzDecoder.o: ../../Compress/XzDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/XzEncoder.o: ../../Compress/XzEncoder.cpp $(CXX) $(CXXFLAGS) $< $O/ZDecoder.o: ../../Compress/ZDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/ZlibDecoder.o: ../../Compress/ZlibDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp $(CXX) $(CXXFLAGS) $< $O/ZstdDecoder.o: ../../Compress/ZstdDecoder.cpp $(CXX) $(CXXFLAGS) $< $O/ZstdRegister.o: ../../Compress/ZstdRegister.cpp $(CXX) $(CXXFLAGS) $< $O/7zAes.o: ../../Crypto/7zAes.cpp $(CXX) $(CXXFLAGS) $< $O/7zAesRegister.o: ../../Crypto/7zAesRegister.cpp $(CXX) $(CXXFLAGS) $< $O/HmacSha1.o: ../../Crypto/HmacSha1.cpp $(CXX) $(CXXFLAGS) $< $O/HmacSha256.o: ../../Crypto/HmacSha256.cpp $(CXX) $(CXXFLAGS) $< $O/MyAes.o: ../../Crypto/MyAes.cpp $(CXX) $(CXXFLAGS) $< $O/MyAesReg.o: ../../Crypto/MyAesReg.cpp $(CXX) $(CXXFLAGS) $< $O/Pbkdf2HmacSha1.o: ../../Crypto/Pbkdf2HmacSha1.cpp $(CXX) $(CXXFLAGS) $< $O/RandGen.o: ../../Crypto/RandGen.cpp $(CXX) $(CXXFLAGS) $< $O/Rar20Crypto.o: ../../Crypto/Rar20Crypto.cpp $(CXX) $(CXXFLAGS) $< $O/Rar5Aes.o: ../../Crypto/Rar5Aes.cpp $(CXX) $(CXXFLAGS) $< $O/RarAes.o: ../../Crypto/RarAes.cpp $(CXX) $(CXXFLAGS) $< $O/WzAes.o: ../../Crypto/WzAes.cpp $(CXX) $(CXXFLAGS) $< $O/ZipCrypto.o: ../../Crypto/ZipCrypto.cpp $(CXX) $(CXXFLAGS) $< $O/ZipStrong.o: ../../Crypto/ZipStrong.cpp $(CXX) $(CXXFLAGS) $< $O/CoderMixer2.o: ../../Archive/Common/CoderMixer2.cpp $(CXX) $(CXXFLAGS) $< $O/DummyOutStream.o: ../../Archive/Common/DummyOutStream.cpp $(CXX) $(CXXFLAGS) $< $O/FindSignature.o: ../../Archive/Common/FindSignature.cpp $(CXX) $(CXXFLAGS) $< $O/HandlerOut.o: ../../Archive/Common/HandlerOut.cpp $(CXX) $(CXXFLAGS) $< $O/InStreamWithCRC.o: ../../Archive/Common/InStreamWithCRC.cpp $(CXX) $(CXXFLAGS) $< $O/ItemNameUtils.o: ../../Archive/Common/ItemNameUtils.cpp $(CXX) $(CXXFLAGS) $< $O/MultiStream.o: ../../Archive/Common/MultiStream.cpp $(CXX) $(CXXFLAGS) $< $O/OutStreamWithCRC.o: ../../Archive/Common/OutStreamWithCRC.cpp $(CXX) $(CXXFLAGS) $< $O/OutStreamWithSha1.o: ../../Archive/Common/OutStreamWithSha1.cpp $(CXX) $(CXXFLAGS) $< $O/ParseProperties.o: ../../Archive/Common/ParseProperties.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveCommandLine.o: ../../UI/Common/ArchiveCommandLine.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveExtractCallback.o: ../../UI/Common/ArchiveExtractCallback.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveName.o: ../../UI/Common/ArchiveName.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveOpenCallback.o: ../../UI/Common/ArchiveOpenCallback.cpp $(CXX) $(CXXFLAGS) $< $O/Bench.o: ../../UI/Common/Bench.cpp $(CXX) $(CXXFLAGS) $< $O/CompressCall.o: ../../UI/Common/CompressCall.cpp $(CXX) $(CXXFLAGS) $< $O/CompressCall2.o: ../../UI/Common/CompressCall2.cpp $(CXX) $(CXXFLAGS) $< $O/DefaultName.o: ../../UI/Common/DefaultName.cpp $(CXX) $(CXXFLAGS) $< $O/EnumDirItems.o: ../../UI/Common/EnumDirItems.cpp $(CXX) $(CXXFLAGS) $< $O/Extract.o: ../../UI/Common/Extract.cpp $(CXX) $(CXXFLAGS) $< $O/ExtractingFilePath.o: ../../UI/Common/ExtractingFilePath.cpp $(CXX) $(CXXFLAGS) $< $O/HashCalc.o: ../../UI/Common/HashCalc.cpp $(CXX) $(CXXFLAGS) $< $O/LoadCodecs.o: ../../UI/Common/LoadCodecs.cpp $(CXX) $(CXXFLAGS) $< $O/OpenArchive.o: ../../UI/Common/OpenArchive.cpp $(CXX) $(CXXFLAGS) $< $O/PropIDUtils.o: ../../UI/Common/PropIDUtils.cpp $(CXX) $(CXXFLAGS) $< $O/SetProperties.o: ../../UI/Common/SetProperties.cpp $(CXX) $(CXXFLAGS) $< $O/SortUtils.o: ../../UI/Common/SortUtils.cpp $(CXX) $(CXXFLAGS) $< $O/TempFiles.o: ../../UI/Common/TempFiles.cpp $(CXX) $(CXXFLAGS) $< $O/Update.o: ../../UI/Common/Update.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateAction.o: ../../UI/Common/UpdateAction.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallback.o: ../../UI/Common/UpdateCallback.cpp $(CXX) $(CXXFLAGS) $< $O/UpdatePair.o: ../../UI/Common/UpdatePair.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateProduce.o: ../../UI/Common/UpdateProduce.cpp $(CXX) $(CXXFLAGS) $< $O/WorkDir.o: ../../UI/Common/WorkDir.cpp $(CXX) $(CXXFLAGS) $< $O/ZipRegistry.o: ../../UI/Common/ZipRegistry.cpp $(CXX) $(CXXFLAGS) $< $O/Agent.o: ../../UI/Agent/Agent.cpp $(CXX) $(CXXFLAGS) $< $O/AgentOut.o: ../../UI/Agent/AgentOut.cpp $(CXX) $(CXXFLAGS) $< $O/AgentProxy.o: ../../UI/Agent/AgentProxy.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveFolder.o: ../../UI/Agent/ArchiveFolder.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveFolderOpen.o: ../../UI/Agent/ArchiveFolderOpen.cpp $(CXX) $(CXXFLAGS) $< $O/ArchiveFolderOut.o: ../../UI/Agent/ArchiveFolderOut.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallbackAgent.o: ../../UI/Agent/UpdateCallbackAgent.cpp $(CXX) $(CXXFLAGS) $< $O/Client7z.o: ../../UI/Client7z/Client7z.cpp $(CXX) $(CXXFLAGS) $< $O/BenchCon.o: ../../UI/Console/BenchCon.cpp $(CXX) $(CXXFLAGS) $< $O/ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp $(CXX) $(CXXFLAGS) $< $O/ExtractCallbackConsole.o: ../../UI/Console/ExtractCallbackConsole.cpp $(CXX) $(CXXFLAGS) $< $O/HashCon.o: ../../UI/Console/HashCon.cpp $(CXX) $(CXXFLAGS) $< $O/List.o: ../../UI/Console/List.cpp $(CXX) $(CXXFLAGS) $< $O/Main.o: ../../UI/Console/Main.cpp ../../../../C/7zVersion.h $(CXX) $(CXXFLAGS) $(CONSOLE_VARIANT_FLAGS) $(CONSOLE_ASM_FLAGS) $< $O/MainAr.o: ../../UI/Console/MainAr.cpp $(CXX) $(CXXFLAGS) $< $O/OpenCallbackConsole.o: ../../UI/Console/OpenCallbackConsole.cpp $(CXX) $(CXXFLAGS) $< $O/PercentPrinter.o: ../../UI/Console/PercentPrinter.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallbackConsole.o: ../../UI/Console/UpdateCallbackConsole.cpp $(CXX) $(CXXFLAGS) $< $O/UserInputUtils.o: ../../UI/Console/UserInputUtils.cpp $(CXX) $(CXXFLAGS) $< $O/BenchmarkDialog.o: ../../UI/GUI/BenchmarkDialog.cpp $(CXX) $(CXXFLAGS) $< $O/CompressDialog.o: ../../UI/GUI/CompressDialog.cpp $(CXX) $(CXXFLAGS) $< $O/ExtractDialog.o: ../../UI/GUI/ExtractDialog.cpp $(CXX) $(CXXFLAGS) $< $O/ExtractGUI.o: ../../UI/GUI/ExtractGUI.cpp $(CXX) $(CXXFLAGS) $< $O/GUI.o: ../../UI/GUI/GUI.cpp $(CXX) $(CXXFLAGS) $< $O/HashGUI.o: ../../UI/GUI/HashGUI.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallbackGUI.o: ../../UI/GUI/UpdateCallbackGUI.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallbackGUI2.o: ../../UI/GUI/UpdateCallbackGUI2.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateGUI.o: ../../UI/GUI/UpdateGUI.cpp $(CXX) $(CXXFLAGS) $< $O/MyMessages.o: ../../UI/Explorer/MyMessages.cpp $(CXX) $(CXXFLAGS) $< $O/ContextMenu.o: ../../UI/Explorer/ContextMenu.cpp $(CXX) $(CXXFLAGS) $< $O/DllExportsExplorer.o: ../../UI/Explorer/DllExportsExplorer.cpp $(CXX) $(CXXFLAGS) $< $O/RegistryContextMenu.o: ../../UI/Explorer/RegistryContextMenu.cpp $(CXX) $(CXXFLAGS) $< $O/AboutDialog.o: ../../UI/FileManager/AboutDialog.cpp $(CXX) $(CXXFLAGS) $< $O/AltStreamsFolder.o: ../../UI/FileManager/AltStreamsFolder.cpp $(CXX) $(CXXFLAGS) $< $O/App.o: ../../UI/FileManager/App.cpp $(CXX) $(CXXFLAGS) $< $O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp $(CXX) $(CXXFLAGS) $< $O/BrowseDialog2.o: ../../UI/FileManager/BrowseDialog2.cpp $(CXX) $(CXXFLAGS) $< $O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp $(CXX) $(CXXFLAGS) $< $O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp $(CXX) $(CXXFLAGS) $< $O/CopyDialog.o: ../../UI/FileManager/CopyDialog.cpp $(CXX) $(CXXFLAGS) $< $O/EditDialog.o: ../../UI/FileManager/EditDialog.cpp $(CXX) $(CXXFLAGS) $< $O/EditPage.o: ../../UI/FileManager/EditPage.cpp $(CXX) $(CXXFLAGS) $< $O/EnumFormatEtc.o: ../../UI/FileManager/EnumFormatEtc.cpp $(CXX) $(CXXFLAGS) $< $O/ExtractCallback.o: ../../UI/FileManager/ExtractCallback.cpp $(CXX) $(CXXFLAGS) $< $O/FileFolderPluginOpen.o: ../../UI/FileManager/FileFolderPluginOpen.cpp $(CXX) $(CXXFLAGS) $< $O/FilePlugins.o: ../../UI/FileManager/FilePlugins.cpp $(CXX) $(CXXFLAGS) $< $O/FM.o: ../../UI/FileManager/FM.cpp $(CXX) $(CXXFLAGS) $< $O/FoldersPage.o: ../../UI/FileManager/FoldersPage.cpp $(CXX) $(CXXFLAGS) $< $O/FormatUtils.o: ../../UI/FileManager/FormatUtils.cpp $(CXX) $(CXXFLAGS) $< $O/FSDrives.o: ../../UI/FileManager/FSDrives.cpp $(CXX) $(CXXFLAGS) $< $O/FSFolder.o: ../../UI/FileManager/FSFolder.cpp $(CXX) $(CXXFLAGS) $< $O/FSFolderCopy.o: ../../UI/FileManager/FSFolderCopy.cpp $(CXX) $(CXXFLAGS) $< $O/HelpUtils.o: ../../UI/FileManager/HelpUtils.cpp $(CXX) $(CXXFLAGS) $< $O/LangPage.o: ../../UI/FileManager/LangPage.cpp $(CXX) $(CXXFLAGS) $< $O/LangUtils.o: ../../UI/FileManager/LangUtils.cpp $(CXX) $(CXXFLAGS) $< $O/LinkDialog.o: ../../UI/FileManager/LinkDialog.cpp $(CXX) $(CXXFLAGS) $< $O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp $(CXX) $(CXXFLAGS) $< $O/MemDialog.o: ../../UI/FileManager/MemDialog.cpp $(CXX) $(CXXFLAGS) $< $O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp $(CXX) $(CXXFLAGS) $< $O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp $(CXX) $(CXXFLAGS) $< $O/MyLoadMenu.o: ../../UI/FileManager/MyLoadMenu.cpp $(CXX) $(CXXFLAGS) $< $O/NetFolder.o: ../../UI/FileManager/NetFolder.cpp $(CXX) $(CXXFLAGS) $< $O/OpenCallback.o: ../../UI/FileManager/OpenCallback.cpp $(CXX) $(CXXFLAGS) $< $O/OptionsDialog.o: ../../UI/FileManager/OptionsDialog.cpp $(CXX) $(CXXFLAGS) $< $O/OverwriteDialog.o: ../../UI/FileManager/OverwriteDialog.cpp $(CXX) $(CXXFLAGS) $< $O/Panel.o: ../../UI/FileManager/Panel.cpp $(CXX) $(CXXFLAGS) $< $O/PanelCopy.o: ../../UI/FileManager/PanelCopy.cpp $(CXX) $(CXXFLAGS) $< $O/PanelCrc.o: ../../UI/FileManager/PanelCrc.cpp $(CXX) $(CXXFLAGS) $< $O/PanelDrag.o: ../../UI/FileManager/PanelDrag.cpp $(CXX) $(CXXFLAGS) $< $O/PanelFolderChange.o: ../../UI/FileManager/PanelFolderChange.cpp $(CXX) $(CXXFLAGS) $< $O/PanelItemOpen.o: ../../UI/FileManager/PanelItemOpen.cpp $(CXX) $(CXXFLAGS) $< $O/PanelItems.o: ../../UI/FileManager/PanelItems.cpp $(CXX) $(CXXFLAGS) $< $O/PanelKey.o: ../../UI/FileManager/PanelKey.cpp $(CXX) $(CXXFLAGS) $< $O/PanelListNotify.o: ../../UI/FileManager/PanelListNotify.cpp $(CXX) $(CXXFLAGS) $< $O/PanelMenu.o: ../../UI/FileManager/PanelMenu.cpp $(CXX) $(CXXFLAGS) $< $O/PanelOperations.o: ../../UI/FileManager/PanelOperations.cpp $(CXX) $(CXXFLAGS) $< $O/PanelSelect.o: ../../UI/FileManager/PanelSelect.cpp $(CXX) $(CXXFLAGS) $< $O/PanelSort.o: ../../UI/FileManager/PanelSort.cpp $(CXX) $(CXXFLAGS) $< $O/PanelSplitFile.o: ../../UI/FileManager/PanelSplitFile.cpp $(CXX) $(CXXFLAGS) $< $O/PasswordDialog.o: ../../UI/FileManager/PasswordDialog.cpp $(CXX) $(CXXFLAGS) $< $O/ProgramLocation.o: ../../UI/FileManager/ProgramLocation.cpp $(CXX) $(CXXFLAGS) $< $O/ProgressDialog.o: ../../UI/FileManager/ProgressDialog.cpp $(CXX) $(CXXFLAGS) $< $O/ProgressDialog2.o: ../../UI/FileManager/ProgressDialog2.cpp $(CXX) $(CXXFLAGS) $< $O/PropertyName.o: ../../UI/FileManager/PropertyName.cpp $(CXX) $(CXXFLAGS) $< $O/RegistryAssociations.o: ../../UI/FileManager/RegistryAssociations.cpp $(CXX) $(CXXFLAGS) $< $O/RegistryPlugins.o: ../../UI/FileManager/RegistryPlugins.cpp $(CXX) $(CXXFLAGS) $< $O/RegistryUtils.o: ../../UI/FileManager/RegistryUtils.cpp $(CXX) $(CXXFLAGS) $< $O/RootFolder.o: ../../UI/FileManager/RootFolder.cpp $(CXX) $(CXXFLAGS) $< $O/SettingsPage.o: ../../UI/FileManager/SettingsPage.cpp $(CXX) $(CXXFLAGS) $< $O/SplitDialog.o: ../../UI/FileManager/SplitDialog.cpp $(CXX) $(CXXFLAGS) $< $O/SplitUtils.o: ../../UI/FileManager/SplitUtils.cpp $(CXX) $(CXXFLAGS) $< $O/StringUtils.o: ../../UI/FileManager/StringUtils.cpp $(CXX) $(CXXFLAGS) $< $O/SysIconUtils.o: ../../UI/FileManager/SysIconUtils.cpp $(CXX) $(CXXFLAGS) $< $O/SystemPage.o: ../../UI/FileManager/SystemPage.cpp $(CXX) $(CXXFLAGS) $< $O/TextPairs.o: ../../UI/FileManager/TextPairs.cpp $(CXX) $(CXXFLAGS) $< $O/UpdateCallback100.o: ../../UI/FileManager/UpdateCallback100.cpp $(CXX) $(CXXFLAGS) $< $O/VerCtrl.o: ../../UI/FileManager/VerCtrl.cpp $(CXX) $(CXXFLAGS) $< $O/ViewSettings.o: ../../UI/FileManager/ViewSettings.cpp $(CXX) $(CXXFLAGS) $< $O/SfxCon.o: ../../Bundles/SFXCon/SfxCon.cpp $(CXX) $(CXXFLAGS) $< $O/$(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CXXFLAGS) $< $O/7zAlloc.o: ../../../../C/7zAlloc.c $(CC) $(CFLAGS) $< $O/7zArcIn.o: ../../../../C/7zArcIn.c $(CC) $(CFLAGS) $< $O/7zBuf.o: ../../../../C/7zBuf.c $(CC) $(CFLAGS) $< $O/7zBuf2.o: ../../../../C/7zBuf2.c $(CC) $(CFLAGS) $< $O/7zCrc.o: ../../../../C/7zCrc.c $(CC) $(CFLAGS) $< $O/7zDec.o: ../../../../C/7zDec.c $(CC) $(CFLAGS) $< $O/7zFile.o: ../../../../C/7zFile.c $(CC) $(CFLAGS) $< $O/7zStream.o: ../../../../C/7zStream.c $(CC) $(CFLAGS) $< $O/Aes.o: ../../../../C/Aes.c $(CC) $(CFLAGS) $< $O/Alloc.o: ../../../../C/Alloc.c $(CC) $(CFLAGS) $< $O/Bcj2.o: ../../../../C/Bcj2.c $(CC) $(CFLAGS) $< $O/Bcj2Enc.o: ../../../../C/Bcj2Enc.c $(CC) $(CFLAGS) $< $O/Blake2s.o: ../../../../C/Blake2s.c $(CC) $(CFLAGS) $< $O/Bra.o: ../../../../C/Bra.c $(CC) $(CFLAGS) $< $O/Bra86.o: ../../../../C/Bra86.c $(CC) $(CFLAGS) $< $O/BraIA64.o: ../../../../C/BraIA64.c $(CC) $(CFLAGS) $< $O/BwtSort.o: ../../../../C/BwtSort.c $(CC) $(CFLAGS) $< $O/CpuArch.o: ../../../../C/CpuArch.c $(CC) $(CFLAGS) $< $O/Delta.o: ../../../../C/Delta.c $(CC) $(CFLAGS) $< $O/DllSecur.o: ../../../../C/DllSecur.c $(CC) $(CFLAGS) $< $O/HuffEnc.o: ../../../../C/HuffEnc.c $(CC) $(CFLAGS) $< $O/LzFind.o: ../../../../C/LzFind.c $(CC) $(CFLAGS) $< # ifdef MT_FILES $O/LzFindMt.o: ../../../../C/LzFindMt.c $(CC) $(CFLAGS) $< $O/Threads.o: ../../../../C/Threads.c $(CC) $(CFLAGS) $< # endif $O/LzmaEnc.o: ../../../../C/LzmaEnc.c $(CC) $(CFLAGS) $< $O/Lzma86Dec.o: ../../../../C/Lzma86Dec.c $(CC) $(CFLAGS) $< $O/Lzma86Enc.o: ../../../../C/Lzma86Enc.c $(CC) $(CFLAGS) $< $O/Lzma2Dec.o: ../../../../C/Lzma2Dec.c $(CC) $(CFLAGS) $< $O/Lzma2DecMt.o: ../../../../C/Lzma2DecMt.c $(CC) $(CFLAGS) $< $O/Lzma2Enc.o: ../../../../C/Lzma2Enc.c $(CC) $(CFLAGS) $< $O/LzmaLib.o: ../../../../C/LzmaLib.c $(CC) $(CFLAGS) $< $O/MtCoder.o: ../../../../C/MtCoder.c $(CC) $(CFLAGS) $< $O/MtDec.o: ../../../../C/MtDec.c $(CC) $(CFLAGS) $< $O/Ppmd7.o: ../../../../C/Ppmd7.c $(CC) $(CFLAGS) $< $O/Ppmd7aDec.o: ../../../../C/Ppmd7aDec.c $(CC) $(CFLAGS) $< $O/Ppmd7Dec.o: ../../../../C/Ppmd7Dec.c $(CC) $(CFLAGS) $< $O/Ppmd7Enc.o: ../../../../C/Ppmd7Enc.c $(CC) $(CFLAGS) $< $O/Ppmd8.o: ../../../../C/Ppmd8.c $(CC) $(CFLAGS) $< $O/Ppmd8Dec.o: ../../../../C/Ppmd8Dec.c $(CC) $(CFLAGS) $< $O/Ppmd8Enc.o: ../../../../C/Ppmd8Enc.c $(CC) $(CFLAGS) $< $O/Sha1.o: ../../../../C/Sha1.c $(CC) $(CFLAGS) $< $O/Sha256.o: ../../../../C/Sha256.c $(CC) $(CFLAGS) $< $O/Sort.o: ../../../../C/Sort.c $(CC) $(CFLAGS) $< $O/SwapBytes.o: ../../../../C/SwapBytes.c $(CC) $(CFLAGS) $< $O/Xxh64.o: ../../../../C/Xxh64.c $(CC) $(CFLAGS) $< $O/Xz.o: ../../../../C/Xz.c $(CC) $(CFLAGS) $< $O/XzCrc64.o: ../../../../C/XzCrc64.c $(CC) $(CFLAGS) $< $O/XzDec.o: ../../../../C/XzDec.c $(CC) $(CFLAGS) $< $O/XzEnc.o: ../../../../C/XzEnc.c $(CC) $(CFLAGS) $< $O/XzIn.o: ../../../../C/XzIn.c $(CC) $(CFLAGS) $< $O/ZstdDec.o: ../../../../C/ZstdDec.c $(CC) $(CFLAGS) $< ifdef USE_ASM ifdef IS_X64 USE_X86_ASM=1 USE_X64_ASM=1 else ifdef IS_X86 USE_X86_ASM=1 endif endif endif ifdef USE_X86_ASM $O/7zCrcOpt.o: ../../../../Asm/x86/7zCrcOpt.asm $(MY_ASM) $(AFLAGS) $< $O/XzCrc64Opt.o: ../../../../Asm/x86/XzCrc64Opt.asm $(MY_ASM) $(AFLAGS) $< $O/Sha1Opt.o: ../../../../Asm/x86/Sha1Opt.asm $(MY_ASM) $(AFLAGS) $< $O/Sha256Opt.o: ../../../../Asm/x86/Sha256Opt.asm $(MY_ASM) $(AFLAGS) $< ifndef USE_JWASM USE_X86_ASM_AES=1 endif else $O/7zCrcOpt.o: ../../../../C/7zCrcOpt.c $(CC) $(CFLAGS) $< $O/XzCrc64Opt.o: ../../../../C/XzCrc64Opt.c $(CC) $(CFLAGS) $< $O/Sha1Opt.o: ../../../../C/Sha1Opt.c $(CC) $(CFLAGS) $< $O/Sha256Opt.o: ../../../../C/Sha256Opt.c $(CC) $(CFLAGS) $< endif ifdef USE_X86_ASM_AES $O/AesOpt.o: ../../../../Asm/x86/AesOpt.asm $(MY_ASM) $(AFLAGS) $< else $O/AesOpt.o: ../../../../C/AesOpt.c $(CC) $(CFLAGS) $< endif ifdef USE_X64_ASM $O/LzFindOpt.o: ../../../../Asm/x86/LzFindOpt.asm $(MY_ASM) $(AFLAGS) $< else $O/LzFindOpt.o: ../../../../C/LzFindOpt.c $(CC) $(CFLAGS) $< endif ifdef USE_LZMA_DEC_ASM ifdef IS_X64 $O/LzmaDecOpt.o: ../../../../Asm/x86/LzmaDecOpt.asm $(MY_ASM) $(AFLAGS) $< endif ifdef IS_ARM64 $O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S $(CC) $(CFLAGS) $(ASM_FLAGS) $< endif $O/LzmaDec.o: ../../../../C/LzmaDec.c $(CC) $(CFLAGS) -DZ7_LZMA_DEC_OPT $< else $O/LzmaDec.o: ../../../../C/LzmaDec.c $(CC) $(CFLAGS) $< endif $O/7zMain.o: ../../../../C/Util/7z/7zMain.c $(CC) $(CFLAGS) $< $O/LzmaUtil.o: ../../../../C/Util/Lzma/LzmaUtil.c $(CC) $(CFLAGS) $< ifneq ($(CC), xlc) SHOW_PREDEF=-dM else SHOW_PREDEF= -qshowmacros=pre endif predef_cc: $(CC) $(CFLAGS) -E $(SHOW_PREDEF) ../../../../C/CpuArch.c > predef_cc_log # $(CC) $(CFLAGS) -E -dM - < /dev/null predef_cxx: $(CXX) $(CFLAGS) -E $(SHOW_PREDEF) ../../../Common/CrcReg.cpp > predef_cxx_log predef: predef_cc predef_cxx clean: -$(DEL_OBJ_EXE) tmp41wklro_/CPP/7zip/Aes.mak0000444000175000001440000000050014021624612016647 0ustar nabijaczleweliusersC_OBJS = $(C_OBJS) \ $O\Aes.obj !IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" C_OBJS = $(C_OBJS) \ $O\AesOpt.obj !ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" ASM_OBJS = $(ASM_OBJS) \ $O\AesOpt.obj !ENDIF tmp41wklro_/CPP/7zip/Archive/0000700000175000001440000000000014706260545017036 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Archive/7z/0000700000175000001440000000000014706260545017376 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Archive/7z/7zCompressionMode.cpp0000444000175000001440000000006107674441740023502 0ustar nabijaczleweliusers// CompressionMethod.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Archive/7z/7zCompressionMode.h0000444000175000001440000000410514530162240023132 0ustar nabijaczleweliusers// 7zCompressionMode.h #ifndef ZIP7_INC_7Z_COMPRESSION_MODE_H #define ZIP7_INC_7Z_COMPRESSION_MODE_H #include "../../Common/MethodId.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethodProps { CMethodId Id; UInt32 NumStreams; int CodecIndex; UInt32 NumThreads; bool Set_NumThreads; CMethodFull(): CodecIndex(-1), NumThreads(1), Set_NumThreads(false) {} bool IsSimpleCoder() const { return NumStreams == 1; } }; struct CBond2 { UInt32 OutCoder; UInt32 OutStream; UInt32 InCoder; }; struct CCompressionMethodMode { /* if (Bonds.Empty()), then default bonds must be created if (Filter_was_Inserted) { Methods[0] is filter method Bonds don't contain bonds for filter (these bonds must be created) } */ CObjectVector Methods; CRecordVector Bonds; bool IsThereBond_to_Coder(unsigned coderIndex) const { FOR_VECTOR(i, Bonds) if (Bonds[i].InCoder == coderIndex) return true; return false; } bool DefaultMethod_was_Inserted; bool Filter_was_Inserted; bool PasswordIsDefined; bool MemoryUsageLimit_WasSet; #ifndef Z7_ST bool NumThreads_WasForced; bool MultiThreadMixer; UInt32 NumThreads; #endif UString Password; // _Wipe UInt64 MemoryUsageLimit; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): DefaultMethod_was_Inserted(false) , Filter_was_Inserted(false) , PasswordIsDefined(false) , MemoryUsageLimit_WasSet(false) #ifndef Z7_ST , NumThreads_WasForced(false) , MultiThreadMixer(true) , NumThreads(1) #endif , MemoryUsageLimit((UInt64)1 << 30) {} #ifdef Z7_CPP_IS_SUPPORTED_default CCompressionMethodMode(const CCompressionMethodMode &) = default; CCompressionMethodMode& operator =(const CCompressionMethodMode &) = default; #endif ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zDecode.cpp0000444000175000001440000003730514564072620021563 0ustar nabijaczleweliusers// 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" namespace NArchive { namespace N7z { Z7_CLASS_IMP_COM_1( CDecProgress , ICompressProgressInfo ) CMyComPtr _progress; public: CDecProgress(ICompressProgressInfo *progress): _progress(progress) {} }; Z7_COM7F_IMF(CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)) { return _progress->SetRatioInfo(NULL, outSize); } static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi) { bi.Clear(); bi.Bonds.ClearAndSetSize(folder.Bonds.Size()); unsigned i; for (i = 0; i < folder.Bonds.Size(); i++) { NCoderMixer2::CBond &bond = bi.Bonds[i]; const N7z::CBond &folderBond = folder.Bonds[i]; bond.PackIndex = folderBond.PackIndex; bond.UnpackIndex = folderBond.UnpackIndex; } bi.Coders.ClearAndSetSize(folder.Coders.Size()); bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coderInfo = folder.Coders[i]; bi.Coders[i].NumStreams = coderInfo.NumStreams; bi.CoderMethodIDs[i] = coderInfo.MethodID; } /* if (!bi.SetUnpackCoder()) throw 1112; */ bi.UnpackCoder = folder.UnpackCoder; bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size()); for (i = 0; i < folder.PackStreams.Size(); i++) bi.PackStreams[i] = folder.PackStreams[i]; } static inline bool AreCodersEqual( const NCoderMixer2::CCoderStreamsInfo &a1, const NCoderMixer2::CCoderStreamsInfo &a2) { return (a1.NumStreams == a2.NumStreams); } static inline bool AreBondsEqual( const NCoderMixer2::CBond &a1, const NCoderMixer2::CBond &a2) { return (a1.PackIndex == a2.PackIndex) && (a1.UnpackIndex == a2.UnpackIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; unsigned i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.Bonds.Size() != a2.Bonds.Size()) return false; for (i = 0; i < a1.Bonds.Size(); i++) if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.PackStreams.Size() != a2.PackStreams.Size()) return false; for (i = 0; i < a1.PackStreams.Size(); i++) if (a1.PackStreams[i] != a2.PackStreams[i]) return false; /* if (a1.UnpackCoder != a2.UnpackCoder) return false; */ return true; } CDecoder::CDecoder(bool useMixerMT): _bindInfoPrev_Defined(false) { #if defined(USE_MIXER_ST) && defined(USE_MIXER_MT) _useMixerMT = useMixerMT; #else UNUSED_VAR(useMixerMT) #endif } Z7_CLASS_IMP_COM_0( CLockedInStream ) public: CMyComPtr Stream; UInt64 Pos; #ifdef USE_MIXER_MT NWindows::NSynchronization::CCriticalSection CriticalSection; #endif }; #ifdef USE_MIXER_MT Z7_CLASS_IMP_COM_1( CLockedSequentialInStreamMT , ISequentialInStream ) CLockedInStream *_glob; UInt64 _pos; CMyComPtr _globRef; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _globRef = lockedInStream; _glob = lockedInStream; _pos = startPos; } }; Z7_COM7F_IMF(CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)) { NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection); if (_pos != _glob->Pos) { RINOK(InStream_SeekSet(_glob->Stream, _pos)) _glob->Pos = _pos; } UInt32 realProcessedSize = 0; const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); _pos += realProcessedSize; _glob->Pos = _pos; if (processedSize) *processedSize = realProcessedSize; return res; } #endif #ifdef USE_MIXER_ST Z7_CLASS_IMP_COM_1( CLockedSequentialInStreamST , ISequentialInStream ) CLockedInStream *_glob; UInt64 _pos; CMyComPtr _globRef; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _globRef = lockedInStream; _glob = lockedInStream; _pos = startPos; } }; Z7_COM7F_IMF(CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (_pos != _glob->Pos) { RINOK(InStream_SeekSet(_glob->Stream, _pos)) _glob->Pos = _pos; } UInt32 realProcessedSize = 0; const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); _pos += realProcessedSize; _glob->Pos = _pos; if (processedSize) *processedSize = realProcessedSize; return res; } #endif HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const CFolders &folders, unsigned folderIndex, const UInt64 *unpackSize , ISequentialOutStream *outStream , ICompressProgressInfo *compressProgress , ISequentialInStream ** #ifdef USE_MIXER_ST inStreamMainRes #endif , bool &dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS_DECL #if !defined(Z7_ST) , bool mtMode, UInt32 numThreads, UInt64 memUsage #endif ) { dataAfterEnd_Error = false; const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; CFolderEx folderInfo; folders.ParseFolderEx(folderIndex, folderInfo); if (!folderInfo.IsDecodingSupported()) return E_NOTIMPL; CBindInfoEx bindInfo; Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo); if (!bindInfo.CalcMapsAndCheck()) return E_NOTIMPL; UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex); bool fullUnpack = true; if (unpackSize) { if (*unpackSize > folderUnpackSize) return E_FAIL; fullUnpack = (*unpackSize == folderUnpackSize); } /* We don't need to init isEncrypted and passwordIsDefined We must upgrade them only #ifndef Z7_NO_CRYPTO isEncrypted = false; passwordIsDefined = false; #endif */ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev)) { _bindInfoPrev_Defined = false; _mixerRef.Release(); #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST if (_useMixerMT) #endif { _mixerMT = new NCoderMixer2::CMixerMT(false); _mixerRef = _mixerMT; _mixer = _mixerMT; } #ifdef USE_MIXER_ST else #endif #endif { #ifdef USE_MIXER_ST _mixerST = new NCoderMixer2::CMixerST(false); _mixerRef = _mixerST; _mixer = _mixerST; #endif } RINOK(_mixer->SetBindInfo(bindInfo)) FOR_VECTOR(i, folderInfo.Coders) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; #ifndef Z7_SFX // we don't support RAR codecs here if ((coderInfo.MethodID >> 8) == 0x403) return E_NOTIMPL; #endif CCreatedCoder cod; RINOK(CreateCoder_Id( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, false, cod)) if (coderInfo.IsSimpleCoder()) { if (!cod.Coder) return E_NOTIMPL; // CMethodId m = coderInfo.MethodID; // isFilter = (IsFilterMethod(m) || m == k_AES); } else { if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams) return E_NOTIMPL; } _mixer->AddCoder(cod); // now there is no codec that uses another external codec /* #ifdef Z7_EXTERNAL_CODECS CMyComPtr setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs)); } #endif */ } _bindInfoPrev = bindInfo; _bindInfoPrev_Defined = true; } RINOK(_mixer->ReInit2()) UInt32 packStreamIndex = 0; UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; unsigned i; #if !defined(Z7_ST) bool mt_wasUsed = false; #endif for (i = 0; i < folderInfo.Coders.Size(); i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; IUnknown *decoder = _mixer->GetCoder(i).GetUnknown(); // now there is no codec that uses another external codec /* #ifdef Z7_EXTERNAL_CODECS { Z7_DECL_CMyComPtr_QI_FROM(ISetCompressCodecsInfo, setCompressCodecsInfo, decoder) if (setCompressCodecsInfo) { // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs)) } } #endif */ #if !defined(Z7_ST) if (!mt_wasUsed) { if (mtMode) { Z7_DECL_CMyComPtr_QI_FROM(ICompressSetCoderMt, setCoderMt, decoder) if (setCoderMt) { mt_wasUsed = true; RINOK(setCoderMt->SetNumberOfThreads(numThreads)) } } // if (memUsage != 0) { Z7_DECL_CMyComPtr_QI_FROM(ICompressSetMemLimit, setMemLimit, decoder) if (setMemLimit) { mt_wasUsed = true; RINOK(setMemLimit->SetMemLimit(memUsage)) } } } #endif { Z7_DECL_CMyComPtr_QI_FROM( ICompressSetDecoderProperties2, setDecoderProperties, decoder) const CByteBuffer &props = coderInfo.Props; const UInt32 size32 = (UInt32)props.Size(); if (props.Size() != size32) return E_NOTIMPL; if (setDecoderProperties) { HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32); if (res == E_INVALIDARG) res = E_NOTIMPL; RINOK(res) } else if (size32 != 0) { // v23: we fail, if decoder doesn't support properties return E_NOTIMPL; } } #ifndef Z7_NO_CRYPTO { Z7_DECL_CMyComPtr_QI_FROM( ICryptoSetPassword, cryptoSetPassword, decoder) if (cryptoSetPassword) { isEncrypted = true; if (!getTextPassword) return E_NOTIMPL; CMyComBSTR_Wipe passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)) passwordIsDefined = true; password.Wipe_and_Empty(); size_t len = 0; if (passwordBSTR) { password = passwordBSTR; len = password.Len(); } CByteBuffer_Wipe buffer(len * 2); const LPCOLESTR psw = passwordBSTR; for (size_t k = 0; k < len; k++) { const wchar_t c = psw[k]; ((Byte *)buffer)[k * 2] = (Byte)c; ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())) } } #endif bool finishMode = false; { Z7_DECL_CMyComPtr_QI_FROM( ICompressSetFinishMode, setFinishMode, decoder) if (setFinishMode) { finishMode = fullUnpack; RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode))) } } UInt32 numStreams = (UInt32)coderInfo.NumStreams; CObjArray packSizes(numStreams); CObjArray packSizesPointers(numStreams); for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++) { int bond = folderInfo.FindBond_for_PackStream(packStreamIndex); if (bond >= 0) packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex]; else { int index = folderInfo.Find_in_PackStreams(packStreamIndex); if (index < 0) return E_NOTIMPL; packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index]; packSizesPointers[j] = &packSizes[j]; } } const UInt64 *unpackSizesPointer = (unpackSize && i == bindInfo.UnpackCoder) ? unpackSize : &folders.CoderUnpackSizes[unpackStreamIndexStart + i]; _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode); } if (outStream) { _mixer->SelectMainCoder(!fullUnpack); } CObjectVector< CMyComPtr > inStreams; CMyComPtr2_Create lockedInStream; #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST bool needMtLock = _useMixerMT; #endif #endif if (folderInfo.PackStreams.Size() > 1) { // lockedInStream.Pos = (UInt64)(Int64)-1; // RINOK(InStream_GetPos(inStream, lockedInStream.Pos)) RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos)) lockedInStream->Stream = inStream; #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST /* For ST-mixer mode: If parallel input stream reading from pack streams is possible, we must use MT-lock for packed streams. Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode. So we force to needMtLock mode only if there is unknown (external) decoder. */ if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) needMtLock = true; #endif #endif } for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) { CMyComPtr packStream; const UInt64 packPos = startPos + packPositions[j]; if (folderInfo.PackStreams.Size() == 1) { RINOK(InStream_SeekSet(inStream, packPos)) packStream = inStream; } else { #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST if (needMtLock) #endif { CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; packStream = lockedStreamImpSpec; lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos); } #ifdef USE_MIXER_ST else #endif #endif { #ifdef USE_MIXER_ST CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; packStream = lockedStreamImpSpec; lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos); #endif } } CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; inStreams.AddNew() = streamSpec; streamSpec->SetStream(packStream); streamSpec->Init(packPositions[j + 1] - packPositions[j]); } const unsigned num = inStreams.Size(); CObjArray inStreamPointers(num); for (i = 0; i < num; i++) inStreamPointers[i] = inStreams[i]; if (outStream) { CMyComPtr progress2; if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex)) progress2 = new CDecProgress(compressProgress); ISequentialOutStream *outStreamPointer = outStream; return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress, dataAfterEnd_Error); } #ifdef USE_MIXER_ST return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes); #else return E_FAIL; #endif } }} tmp41wklro_/CPP/7zip/Archive/7z/7zDecode.h0000444000175000001440000000274714400604220021214 0ustar nabijaczleweliusers// 7zDecode.h #ifndef ZIP7_INC_7Z_DECODE_H #define ZIP7_INC_7Z_DECODE_H #include "../Common/CoderMixer2.h" #include "7zIn.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer2::CBindInfo { CRecordVector CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoPrev_Defined; #ifdef USE_MIXER_ST #ifdef USE_MIXER_MT bool _useMixerMT; #endif #endif CBindInfoEx _bindInfoPrev; #ifdef USE_MIXER_ST NCoderMixer2::CMixerST *_mixerST; #endif #ifdef USE_MIXER_MT NCoderMixer2::CMixerMT *_mixerMT; #endif NCoderMixer2::CMixer *_mixer; CMyComPtr _mixerRef; public: CDecoder(bool useMixerMT); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const CFolders &folders, unsigned folderIndex, const UInt64 *unpackSize // if (!unpackSize), then full folder is required // if (unpackSize), then only *unpackSize bytes from folder are required , ISequentialOutStream *outStream , ICompressProgressInfo *compressProgress , ISequentialInStream **inStreamMainRes , bool &dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS_DECL #if !defined(Z7_ST) , bool mtMode, UInt32 numThreads, UInt64 memUsage #endif ); }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zEncode.cpp0000444000175000001440000004540214540526420021566 0ustar nabijaczleweliusers// 7zEncode.cpp #include "StdAfx.h" #include "../../../Common/ComTry.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zEncode.h" #include "7zSpecStream.h" namespace NArchive { namespace N7z { void CEncoder::InitBindConv() { unsigned numIn = _bindInfo.Coders.Size(); SrcIn_to_DestOut.ClearAndSetSize(numIn); DestOut_to_SrcIn.ClearAndSetSize(numIn); unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams(); SrcOut_to_DestIn.ClearAndSetSize(numOut); // _DestIn_to_SrcOut.ClearAndSetSize(numOut); UInt32 destIn = 0; UInt32 destOut = 0; for (unsigned i = _bindInfo.Coders.Size(); i != 0;) { i--; const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i]; numIn--; numOut -= coder.NumStreams; SrcIn_to_DestOut[numIn] = destOut; DestOut_to_SrcIn[destOut] = numIn; destOut++; for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++) { UInt32 index = numOut + j; SrcOut_to_DestIn[index] = destIn; // _DestIn_to_SrcOut[destIn] = index; } } } void CEncoder::SetFolder(CFolder &folder) { folder.Bonds.SetSize(_bindInfo.Bonds.Size()); unsigned i; for (i = 0; i < _bindInfo.Bonds.Size(); i++) { CBond &fb = folder.Bonds[i]; const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i]; fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex]; fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex]; } folder.Coders.SetSize(_bindInfo.Coders.Size()); for (i = 0; i < _bindInfo.Coders.Size(); i++) { CCoderInfo &coderInfo = folder.Coders[i]; const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i]; coderInfo.NumStreams = coderStreamsInfo.NumStreams; coderInfo.MethodID = _decompressionMethods[i]; // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty. } folder.PackStreams.SetSize(_bindInfo.PackStreams.Size()); for (i = 0; i < _bindInfo.PackStreams.Size(); i++) folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]]; } static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) { Z7_DECL_CMyComPtr_QI_FROM( ICompressSetCoderProperties, setCoderProperties, coder) if (setCoderProperties) return props.SetCoderProps(setCoderProperties, dataSizeReduce); return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; } void CMtEncMultiProgress::Init(ICompressProgressInfo *progress) { _progress = progress; OutSize = 0; } Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)) { UInt64 outSize2; { #ifndef Z7_ST NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); #endif outSize2 = OutSize; } if (_progress) return _progress->SetRatioInfo(inSize, &outSize2); return S_OK; } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST if (_options.MultiThreadMixer) #endif { _mixerMT = new NCoderMixer2::CMixerMT(true); _mixerRef = _mixerMT; _mixer = _mixerMT; } #ifdef USE_MIXER_ST else #endif #endif { #ifdef USE_MIXER_ST _mixerST = new NCoderMixer2::CMixerST(true); _mixerRef = _mixerST; _mixer = _mixerST; #endif } RINOK(_mixer->SetBindInfo(_bindInfo)) FOR_VECTOR (m, _options.Methods) { const CMethodFull &methodFull = _options.Methods[m]; CCreatedCoder cod; if (methodFull.CodecIndex >= 0) { RINOK(CreateCoder_Index( EXTERNAL_CODECS_LOC_VARS (unsigned)methodFull.CodecIndex, true, cod)) } else { RINOK(CreateCoder_Id( EXTERNAL_CODECS_LOC_VARS methodFull.Id, true, cod)) } if (!cod.Coder && !cod.Coder2) { return E_NOTIMPL; // unsupported method, if encoder // return E_FAIL; } if (cod.NumStreams != methodFull.NumStreams) return E_FAIL; CMyComPtr encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2; #ifndef Z7_ST if (methodFull.Set_NumThreads) { CMyComPtr setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads( /* _options.NumThreads */ methodFull.NumThreads )) } } #endif RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)) /* CMyComPtr resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt) { resetSalt->ResetSalt(); } */ // now there is no codec that uses another external codec /* #ifdef Z7_EXTERNAL_CODECS CMyComPtr setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs)); } #endif */ CMyComPtr cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { const unsigned sizeInBytes = _options.Password.Len() * 2; CByteBuffer_Wipe buffer(sizeInBytes); for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes)) } _mixer->AddCoder(cod); } return S_OK; } Z7_CLASS_IMP_COM_1( CSequentialOutTempBufferImp2 , ISequentialOutStream ) public: CInOutTempBuffer TempBuffer; CMtEncMultiProgress *_mtProgressSpec; CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {} }; Z7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)) { COM_TRY_BEGIN if (processed) *processed = 0; RINOK(TempBuffer.Write_HRESULT(data, size)) if (processed) *processed = size; if (_mtProgressSpec) _mtProgressSpec->AddOutSize(size); return S_OK; COM_TRY_END } Z7_CLASS_IMP_COM_1( CSequentialOutMtNotify , ISequentialOutStream ) public: CMyComPtr _stream; CMtEncMultiProgress *_mtProgressSpec; CSequentialOutMtNotify(): _mtProgressSpec(NULL) {} }; Z7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)) { UInt32 realProcessed = 0; HRESULT res = _stream->Write(data, size, &realProcessed); if (processed) *processed = realProcessed; if (_mtProgressSpec) _mtProgressSpec->AddOutSize(size); return res; } static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props) { Z7_DECL_CMyComPtr_QI_FROM( ICompressWriteCoderProperties, writeCoderProperties, coder) if (writeCoderProperties) { CMyComPtr2_Create outStreamSpec; outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec)) outStreamSpec->CopyToBuffer(props); } else props.Free(); return S_OK; } HRESULT CEncoder::Encode1( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, // const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, UInt64 expectedDataSize, CFolder &folderItem, // CRecordVector &coderUnpackSizes, // UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()) if (!_mixerRef) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)) } RINOK(_mixer->ReInit2()) CMyComPtr2 mtProgress; CMyComPtr2 mtOutStreamNotify; CRecordVector tempBufferSpecs; CObjectVector > tempBuffers; unsigned i; for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2(); CMyComPtr tempBuffer = tempBufferSpec; tempBufferSpecs.Add(tempBufferSpec); tempBuffers.Add(tempBuffer); } const unsigned numMethods = _bindInfo.Coders.Size(); for (i = 0; i < numMethods; i++) _mixer->SetCoderInfo(i, NULL, NULL, false); /* inStreamSize can be used by BCJ2 to set optimal range of conversion. But current BCJ2 encoder uses also another way to check exact size of current file. So inStreamSize is not required. */ /* if (inStreamSize) _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); */ /* CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; */ CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; CMyComPtr outStreamSizeCount; // inStreamSizeCountSpec->Init(inStream); // ISequentialInStream *inStreamPointer = inStreamSizeCount; ISequentialInStream *inStreamPointer = inStream; CRecordVector outStreamPointers; SetFolder(folderItem); for (i = 0; i < numMethods; i++) { IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); /* { CEncoder *sfEncoder = NULL; Z7_DECL_CMyComPtr_QI_FROM( IGetSfEncoderInternal, sf, coder) if (sf) { RINOK(sf->GetSfEncoder(&sfEncoder)); if (!sfEncoder) return E_FAIL; } } */ /* #ifdef Z7_EXTERNAL_CODECS { Z7_DECL_CMyComPtr_QI_FROM( ISetCompressCodecsInfo, setCompressCodecsInfo, coder) if (setCompressCodecsInfo) { // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs)) } } #endif */ { Z7_DECL_CMyComPtr_QI_FROM( ICryptoResetInitVector, resetInitVector, coder) if (resetInitVector) { RINOK(resetInitVector->ResetInitVector()) } } { Z7_DECL_CMyComPtr_QI_FROM( ICompressSetCoderPropertiesOpt, optProps, coder) if (optProps) { const PROPID propID = NCoderPropID::kExpectedDataSize; NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize; RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1)) } } // we must write properties from coder after ResetInitVector() RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props)) } _mixer->SelectMainCoder(false); const UInt32 mainCoder = _mixer->MainCoderIndex; bool useMtProgress = false; if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder)) { #ifdef Z7_ST if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder)) #endif useMtProgress = true; } if (useMtProgress) { mtProgress.SetFromCls(new CMtEncMultiProgress); mtProgress->Init(compressProgress); mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify); mtOutStreamNotify->_stream = outStream; mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr(); FOR_VECTOR (t, tempBufferSpecs) { tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr(); } } if (_bindInfo.PackStreams.Size() != 0) { outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; outStreamSizeCount = outStreamSizeCountSpec; outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ? mtOutStreamNotify.Interface() : outStream); outStreamSizeCountSpec->Init(); outStreamPointers.Add(outStreamSizeCount); } for (i = 1; i < _bindInfo.PackStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); bool dataAfterEnd_Error; RINOK(_mixer->Code( &inStreamPointer, outStreamPointers.ConstData(), mtProgress.IsDefined() ? mtProgress.Interface() : compressProgress, dataAfterEnd_Error)) if (_bindInfo.PackStreams.Size() != 0) packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer; RINOK(iotb.WriteToStream(outStream)) packSizes.Add(iotb.GetDataSize()); } /* Code() in some future codec can change properties. v23: so we fill properties again after Code() */ for (i = 0; i < numMethods; i++) { IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props)) } return S_OK; } void CEncoder::Encode_Post( UInt64 unpackSize, CRecordVector &coderUnpackSizes) { // unpackSize = 0; for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++) { const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]); UInt64 streamSize; if (bond < 0) { // streamSize = inStreamSizeCountSpec->GetSize(); // unpackSize = streamSize; streamSize = unpackSize; } else streamSize = _mixer->GetBondStreamSize((unsigned)bond); coderUnpackSizes.Add(streamSize); } } CEncoder::CEncoder(const CCompressionMethodMode &options): _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; #ifdef USE_MIXER_ST _mixerST = NULL; #endif #ifdef USE_MIXER_MT _mixerMT = NULL; #endif _mixer = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Bonds.IsEmpty()) throw 1; CMethodFull method; method.Id = k_AES; method.NumStreams = 1; _options.Methods.Add(method); NCoderMixer2::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumStreams = 1; _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.PackStreams.Add(0); _bindInfo.UnpackCoder = 0; } else { UInt32 numOutStreams = 0; unsigned i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer2::CCoderStreamsInfo cod; cod.NumStreams = methodFull.NumStreams; if (_options.Bonds.IsEmpty()) { // if there are no bonds in options, we create bonds via first streams of coders if (i != _options.Methods.Size() - 1) { NCoderMixer2::CBond bond; bond.PackIndex = numOutStreams; bond.UnpackIndex = i + 1; // it's next coder _bindInfo.Bonds.Add(bond); } else if (cod.NumStreams != 0) _bindInfo.PackStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < cod.NumStreams; j++) _bindInfo.PackStreams.Add(numOutStreams + j); } numOutStreams += cod.NumStreams; _bindInfo.Coders.Add(cod); } if (!_options.Bonds.IsEmpty()) { for (i = 0; i < _options.Bonds.Size(); i++) { NCoderMixer2::CBond mixerBond; const CBond2 &bond = _options.Bonds[i]; if (bond.InCoder >= _bindInfo.Coders.Size() || bond.OutCoder >= _bindInfo.Coders.Size() || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams) return E_INVALIDARG; mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream; mixerBond.UnpackIndex = bond.InCoder; _bindInfo.Bonds.Add(mixerBond); } for (i = 0; i < numOutStreams; i++) if (_bindInfo.FindBond_for_PackStream(i) == -1) _bindInfo.PackStreams.Add(i); } if (!_bindInfo.SetUnpackCoder()) return E_INVALIDARG; if (!_bindInfo.CalcMapsAndCheck()) return E_INVALIDARG; if (_bindInfo.PackStreams.Size() != 1) { /* main_PackStream is pack stream of main path of coders tree. We find main_PackStream, and place to start of list of out streams. It allows to use more optimal memory usage for temp buffers, if main_PackStream is largest stream. */ UInt32 ci = _bindInfo.UnpackCoder; for (;;) { if (_bindInfo.Coders[ci].NumStreams == 0) break; const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci]; const int bond = _bindInfo.FindBond_for_PackStream(outIndex); if (bond >= 0) { ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex; continue; } const int si = _bindInfo.FindStream_in_PackStreams(outIndex); if (si >= 0) _bindInfo.PackStreams.MoveToFront((unsigned)si); break; } } if (_options.PasswordIsDefined) { unsigned numCryptoStreams = _bindInfo.PackStreams.Size(); unsigned numInStreams = _bindInfo.Coders.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer2::CBond bond; bond.UnpackIndex = numInStreams + i; bond.PackIndex = _bindInfo.PackStreams[i]; _bindInfo.Bonds.Add(bond); } _bindInfo.PackStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { CMethodFull method; method.NumStreams = 1; method.Id = k_AES; _options.Methods.Add(method); NCoderMixer2::CCoderStreamsInfo cod; cod.NumStreams = 1; _bindInfo.Coders.Add(cod); _bindInfo.PackStreams.Add(numOutStreams++); } } } for (unsigned i = _options.Methods.Size(); i != 0;) _decompressionMethods.Add(_options.Methods[--i].Id); if (_bindInfo.Coders.Size() > 16) return E_INVALIDARG; if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16) return E_INVALIDARG; if (!_bindInfo.CalcMapsAndCheck()) return E_INVALIDARG; InitBindConv(); _constructed = true; return S_OK; } CEncoder::~CEncoder() {} }} tmp41wklro_/CPP/7zip/Archive/7z/7zEncode.h0000444000175000001440000000415514366244420021236 0ustar nabijaczleweliusers// 7zEncode.h #ifndef ZIP7_INC_7Z_ENCODE_H #define ZIP7_INC_7Z_ENCODE_H #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "7zItem.h" namespace NArchive { namespace N7z { Z7_CLASS_IMP_COM_1( CMtEncMultiProgress, ICompressProgressInfo ) CMyComPtr _progress; #ifndef Z7_ST NWindows::NSynchronization::CCriticalSection CriticalSection; #endif public: UInt64 OutSize; CMtEncMultiProgress(): OutSize(0) {} void Init(ICompressProgressInfo *progress); void AddOutSize(UInt64 addOutSize) { #ifndef Z7_ST NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); #endif OutSize += addOutSize; } }; class CEncoder Z7_final MY_UNCOPYABLE { #ifdef USE_MIXER_ST NCoderMixer2::CMixerST *_mixerST; #endif #ifdef USE_MIXER_MT NCoderMixer2::CMixerMT *_mixerMT; #endif NCoderMixer2::CMixer *_mixer; CMyComPtr _mixerRef; CCompressionMethodMode _options; NCoderMixer2::CBindInfo _bindInfo; CRecordVector _decompressionMethods; CRecordVector SrcIn_to_DestOut; CRecordVector SrcOut_to_DestIn; // CRecordVector DestIn_to_SrcOut; CRecordVector DestOut_to_SrcIn; void InitBindConv(); void SetFolder(CFolder &folder); HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode1( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, // const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, UInt64 expectedDataSize, CFolder &folderItem, // CRecordVector &coderUnpackSizes, // UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress); void Encode_Post( UInt64 unpackSize, CRecordVector &coderUnpackSizes); }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zExtract.cpp0000444000175000001440000002567514540255620022016 0ustar nabijaczleweliusers// 7zExtract.cpp #include "StdAfx.h" #include "../../../../C/7zCrc.h" #include "../../../Common/ComTry.h" #include "../../Common/ProgressUtils.h" #include "7zDecode.h" #include "7zHandler.h" // EXTERN_g_ExternalCodecs namespace NArchive { namespace N7z { Z7_CLASS_IMP_COM_1( CFolderOutStream , ISequentialOutStream /* , ICompressGetSubStreamSize */ ) CMyComPtr _stream; public: bool TestMode; bool CheckCrc; private: bool _fileIsOpen; bool _calcCrc; UInt32 _crc; UInt64 _rem; const UInt32 *_indexes; // unsigned _startIndex; unsigned _numFiles; unsigned _fileIndex; HRESULT OpenFile(bool isCorrupted = false); HRESULT CloseFile_and_SetResult(Int32 res); HRESULT CloseFile(); HRESULT ProcessEmptyFiles(); public: const CDbEx *_db; CMyComPtr ExtractCallback; bool ExtraWriteWasCut; CFolderOutStream(): TestMode(false), CheckCrc(true) {} HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles); HRESULT FlushCorrupted(Int32 callbackOperationResult); bool WasWritingFinished() const { return _numFiles == 0; } }; HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles) { // _startIndex = startIndex; _fileIndex = startIndex; _indexes = indexes; _numFiles = numFiles; _fileIsOpen = false; ExtraWriteWasCut = false; return ProcessEmptyFiles(); } HRESULT CFolderOutStream::OpenFile(bool isCorrupted) { const CFileItem &fi = _db->Files[_fileIndex]; const UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); Int32 askMode = (_fileIndex == nextFileIndex) ? TestMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract : NExtract::NAskMode::kSkip; if (isCorrupted && askMode == NExtract::NAskMode::kExtract && !_db->IsItemAnti(_fileIndex) && !fi.IsDir) askMode = NExtract::NAskMode::kTest; CMyComPtr realOutStream; RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)) _stream = realOutStream; _crc = CRC_INIT_VAL; _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir); _fileIsOpen = true; _rem = fi.Size; if (askMode == NExtract::NAskMode::kExtract && !realOutStream && !_db->IsItemAnti(_fileIndex) && !fi.IsDir) askMode = NExtract::NAskMode::kSkip; return ExtractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res) { _stream.Release(); _fileIsOpen = false; if (!_indexes) _numFiles--; else if (*_indexes == _fileIndex) { _indexes++; _numFiles--; } _fileIndex++; return ExtractCallback->SetOperationResult(res); } HRESULT CFolderOutStream::CloseFile() { const CFileItem &fi = _db->Files[_fileIndex]; return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ? NExtract::NOperationResult::kOK : NExtract::NOperationResult::kCRCError); } HRESULT CFolderOutStream::ProcessEmptyFiles() { while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0) { RINOK(OpenFile()) RINOK(CloseFile()) } return S_OK; } Z7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_fileIsOpen) { UInt32 cur = (size < _rem ? size : (UInt32)_rem); if (_calcCrc) { const UInt32 k_Step = (UInt32)1 << 20; if (cur > k_Step) cur = k_Step; } HRESULT result = S_OK; if (_stream) result = _stream->Write(data, cur, &cur); if (_calcCrc) _crc = CrcUpdate(_crc, data, cur); if (processedSize) *processedSize += cur; data = (const Byte *)data + cur; size -= cur; _rem -= cur; if (_rem == 0) { RINOK(CloseFile()) RINOK(ProcessEmptyFiles()) } RINOK(result) if (cur == 0) break; continue; } RINOK(ProcessEmptyFiles()) if (_numFiles == 0) { // we support partial extracting /* if (processedSize) *processedSize += size; break; */ ExtraWriteWasCut = true; // return S_FALSE; return k_My_HRESULT_WritingWasCut; } RINOK(OpenFile()) } return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) { while (_numFiles != 0) { if (_fileIsOpen) { RINOK(CloseFile_and_SetResult(callbackOperationResult)) } else { RINOK(OpenFile(true)) } } return S_OK; } /* Z7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) { *value = 0; // const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex; const unsigned numFiles_Original = _numFiles; if (subStream >= numFiles_Original) return S_FALSE; // E_FAIL; *value = _db->Files[_startIndex + (unsigned)subStream].Size; return S_OK; } */ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)) { // for GCC // CFolderOutStream *folderOutStream = new CFolderOutStream; // CMyComPtr outStream(folderOutStream); COM_TRY_BEGIN CMyComPtr extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; // numItems = (UInt32)(Int32)-1; const bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _db.Files.Size(); if (numItems == 0) return S_OK; { CNum prevFolder = kNumNoIndex; UInt32 nextFile = 0; UInt32 i; for (i = 0; i < numItems; i++) { const UInt32 fileIndex = allFilesMode ? i : indices[i]; const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) continue; if (folderIndex != prevFolder || fileIndex < nextFile) nextFile = _db.FolderStartFileIndex[folderIndex]; for (CNum index = nextFile; index <= fileIndex; index++) importantTotalUnpacked += _db.Files[index].Size; nextFile = fileIndex + 1; prevFolder = folderIndex; } } RINOK(extractCallback->SetTotal(importantTotalUnpacked)) CMyComPtr2_Create lps; lps->Init(extractCallback, false); CDecoder decoder( #if !defined(USE_MIXER_MT) false #elif !defined(USE_MIXER_ST) true #elif !defined(Z7_7Z_SET_PROPERTIES) #ifdef Z7_ST false #else true #endif #else _useMultiThreadMixer #endif ); UInt64 curPacked, curUnpacked; CMyComPtr callbackMessage; extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage); CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr outStream(folderOutStream); folderOutStream->_db = &_db; folderOutStream->ExtractCallback = extractCallback; folderOutStream->TestMode = (testModeSpec != 0); folderOutStream->CheckCrc = (_crcSize != 0); for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked) { RINOK(lps->SetCur()) if (i >= numItems) break; curUnpacked = 0; curPacked = 0; UInt32 fileIndex = allFilesMode ? i : indices[i]; const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; UInt32 numSolidFiles = 1; if (folderIndex != kNumNoIndex) { curPacked = _db.GetFolderFullPackSize(folderIndex); UInt32 nextFile = fileIndex + 1; fileIndex = _db.FolderStartFileIndex[folderIndex]; UInt32 k; for (k = i + 1; k < numItems; k++) { const UInt32 fileIndex2 = allFilesMode ? k : indices[k]; if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex || fileIndex2 < nextFile) break; nextFile = fileIndex2 + 1; } numSolidFiles = k - i; for (k = fileIndex; k < nextFile; k++) curUnpacked += _db.Files[k].Size; } { const HRESULT result = folderOutStream->Init(fileIndex, allFilesMode ? NULL : indices + i, numSolidFiles); i += numSolidFiles; RINOK(result) } if (folderOutStream->WasWritingFinished()) { // for debug: to test zero size stream unpacking // if (folderIndex == kNumNoIndex) // enable this check for debug continue; } if (folderIndex == kNumNoIndex) return E_FAIL; #ifndef Z7_NO_CRYPTO CMyComPtr getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef Z7_NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; UString_Wipe password; #endif bool dataAfterEnd_Error = false; const HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS _inStream, _db.ArcInfo.DataStartPosition, _db, folderIndex, &curUnpacked, outStream, lps, NULL // *inStreamMainRes , dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS #if !defined(Z7_ST) , true, _numThreads, _memUsage_Decompress #endif ); if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error) { const bool wasFinished = folderOutStream->WasWritingFinished(); int resOp = NExtract::NOperationResult::kDataError; if (result != S_FALSE) { if (result == E_NOTIMPL) resOp = NExtract::NOperationResult::kUnsupportedMethod; else if (wasFinished && dataAfterEnd_Error) resOp = NExtract::NOperationResult::kDataAfterEnd; } RINOK(folderOutStream->FlushCorrupted(resOp)) if (wasFinished) { // we don't show error, if it's after required files if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage) { RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)) } } continue; } if (result != S_OK) return result; RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) continue; } catch(...) { RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) // continue; // return E_FAIL; throw; } } return S_OK; COM_TRY_END } }} tmp41wklro_/CPP/7zip/Archive/7z/7zFolderInStream.cpp0000444000175000001440000001534714427210400023244 0ustar nabijaczleweliusers// 7zFolderInStream.cpp #include "StdAfx.h" #include "../../../Windows/TimeUtils.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles) { _updateCallback = updateCallback; _indexes = indexes; _numFiles = numFiles; _totalSize_for_Coder = 0; ClearFileInfo(); Processed.ClearAndReserve(numFiles); Sizes.ClearAndReserve(numFiles); CRCs.ClearAndReserve(numFiles); TimesDefined.ClearAndReserve(numFiles); MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0); CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0); ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0); Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0); // FolderCrc = CRC_INIT_VAL; _stream.Release(); } void CFolderInStream::ClearFileInfo() { _pos = 0; _crc = CRC_INIT_VAL; _size_Defined = false; _times_Defined = false; _size = 0; FILETIME_Clear(_mTime); FILETIME_Clear(_cTime); FILETIME_Clear(_aTime); _attrib = 0; } HRESULT CFolderInStream::OpenStream() { while (Processed.Size() < _numFiles) { CMyComPtr stream; const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream); if (result != S_OK && result != S_FALSE) return result; _stream = stream; if (stream) { { CMyComPtr getProps; stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); if (getProps) { // access could be changed in first myx pass if (getProps->GetProps(&_size, Need_CTime ? &_cTime : NULL, Need_ATime ? &_aTime : NULL, Need_MTime ? &_mTime : NULL, Need_Attrib ? &_attrib : NULL) == S_OK) { _size_Defined = true; _times_Defined = true; } return S_OK; } } { CMyComPtr streamGetSize; stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); if (streamGetSize) { if (streamGetSize->GetSize(&_size) == S_OK) _size_Defined = true; } return S_OK; } } RINOK(AddFileInfo(result == S_OK)) } return S_OK; } static void AddFt(CRecordVector &vec, const FILETIME &ft) { vec.AddInReserved(FILETIME_To_UInt64(ft)); } /* HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp, UInt32 index, UInt64 size, const UInt32 *crc) { PROPVARIANT prop; prop.vt = VT_EMPTY; prop.wReserved1 = 0; NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size); RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop)); if (crc) { NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc); RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop)); } return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK); } */ HRESULT CFolderInStream::AddFileInfo(bool isProcessed) { // const UInt32 index = _indexes[Processed.Size()]; Processed.AddInReserved(isProcessed); Sizes.AddInReserved(_pos); CRCs.AddInReserved(CRC_GET_DIGEST(_crc)); if (Need_Attrib) Attribs.AddInReserved(_attrib); TimesDefined.AddInReserved(_times_Defined); if (Need_MTime) AddFt(MTimes, _mTime); if (Need_CTime) AddFt(CTimes, _cTime); if (Need_ATime) AddFt(ATimes, _aTime); ClearFileInfo(); /* if (isProcessed && _reportArcProp) RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc)) */ return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } Z7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_stream) { /* if (_pos == 0) { const UInt32 align = (UInt32)1 << AlignLog; const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1); if (offset != 0) { UInt32 cur = align - offset; if (cur > size) cur = size; memset(data, 0, cur); data = (Byte *)data + cur; size -= cur; // _pos += cur; // for debug _totalSize_for_Coder += cur; if (processedSize) *processedSize += cur; continue; } } */ UInt32 cur = size; const UInt32 kMax = (UInt32)1 << 20; if (cur > kMax) cur = kMax; RINOK(_stream->Read(data, cur, &cur)) if (cur != 0) { // if (Need_Crc) _crc = CrcUpdate(_crc, data, cur); /* if (FolderCrc) FolderCrc = CrcUpdate(FolderCrc, data, cur); */ _pos += cur; _totalSize_for_Coder += cur; if (processedSize) *processedSize = cur; // use +=cur, if continue is possible in loop return S_OK; } _stream.Release(); RINOK(AddFileInfo(true)) } if (Processed.Size() >= _numFiles) break; RINOK(OpenStream()) } return S_OK; } Z7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) { *value = 0; if (subStream > Sizes.Size()) return S_FALSE; // E_FAIL; const unsigned index = (unsigned)subStream; if (index < Sizes.Size()) { *value = Sizes[index]; return S_OK; } if (!_size_Defined) { *value = _pos; return S_FALSE; } *value = (_pos > _size ? _pos : _size); return S_OK; } /* HRESULT CFolderInStream::CloseCrcStream() { if (!_crcStream) return S_OK; if (!_crcStream_Spec->WasFinished()) return E_FAIL; _crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it const UInt64 size = _crcStream_Spec->GetSize(); _pos = size; _totalSize_for_Coder += size; _crcStream.Release(); // _crcStream->ReleaseStream(); _stream.Release(); return AddFileInfo(true); } Z7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream) { RINOK(CloseCrcStream()) *stream = NULL; *streamIndexRes = Processed.Size(); if (Processed.Size() >= _numFiles) return S_OK; RINOK(OpenStream()); if (!_stream) return S_OK; if (!_crcStream) { _crcStream_Spec = new CSequentialInStreamWithCRC; _crcStream = _crcStream_Spec; } _crcStream_Spec->Init(); _crcStream_Spec->SetStream(_stream); *stream = _crcStream; _crcStream->AddRef(); return S_OK; } */ }} tmp41wklro_/CPP/7zip/Archive/7z/7zFolderInStream.h0000444000175000001440000000451514427210400022704 0ustar nabijaczleweliusers// 7zFolderInStream.h #ifndef ZIP7_INC_7Z_FOLDER_IN_STREAM_H #define ZIP7_INC_7Z_FOLDER_IN_STREAM_H #include "../../../../C/7zCrc.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" // #include "../Common/InStreamWithCRC.h" #include "../../ICoder.h" #include "../IArchive.h" namespace NArchive { namespace N7z { Z7_CLASS_IMP_COM_2( CFolderInStream , ISequentialInStream , ICompressGetSubStreamSize ) /* Z7_COM7F_IMP(GetNextStream(UInt64 *streamIndex)) Z7_IFACE_COM7_IMP(ICompressInSubStreams) */ CMyComPtr _stream; UInt64 _totalSize_for_Coder; UInt64 _pos; UInt32 _crc; bool _size_Defined; bool _times_Defined; UInt64 _size; FILETIME _mTime; FILETIME _cTime; FILETIME _aTime; UInt32 _attrib; unsigned _numFiles; const UInt32 *_indexes; CMyComPtr _updateCallback; void ClearFileInfo(); HRESULT OpenStream(); HRESULT AddFileInfo(bool isProcessed); // HRESULT CloseCrcStream(); public: bool Need_MTime; bool Need_CTime; bool Need_ATime; bool Need_Attrib; // bool Need_Crc; // bool Need_FolderCrc; // unsigned AlignLog; CRecordVector Processed; CRecordVector Sizes; CRecordVector CRCs; CRecordVector Attribs; CRecordVector TimesDefined; CRecordVector MTimes; CRecordVector CTimes; CRecordVector ATimes; // UInt32 FolderCrc; // UInt32 GetFolderCrc() const { return CRC_GET_DIGEST(FolderCrc); } // CSequentialInStreamWithCRC *_crcStream_Spec; // CMyComPtr _crcStream; // CMyComPtr _reportArcProp; void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles); bool WasFinished() const { return Processed.Size() == _numFiles; } UInt64 Get_TotalSize_for_Coder() const { return _totalSize_for_Coder; } /* UInt64 GetFullSize() const { UInt64 size = 0; FOR_VECTOR (i, Sizes) size += Sizes[i]; return size; } */ CFolderInStream(): Need_MTime(false), Need_CTime(false), Need_ATime(false), Need_Attrib(false) // , Need_Crc(true) // , Need_FolderCrc(false) // , AlignLog(0) {} }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zHandler.cpp0000444000175000001440000004702214567042400021746 0ustar nabijaczleweliusers// 7zHandler.cpp #include "StdAfx.h" #include "../../../../C/CpuArch.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifndef Z7_7Z_SET_PROPERTIES #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef Z7_7Z_SET_PROPERTIES #ifdef Z7_EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; using namespace NCOM; namespace NArchive { namespace N7z { CHandler::CHandler() { #ifndef Z7_NO_CRYPTO _isEncrypted = false; _passwordIsDefined = false; #endif #ifdef Z7_EXTRACT_ONLY _crcSize = 4; #ifdef Z7_7Z_SET_PROPERTIES _useMultiThreadMixer = true; #endif #endif } Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = _db.Files.Size(); return S_OK; } #ifdef Z7_SFX IMP_IInArchive_ArcProps_NO_Table Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps)) { *numProps = 0; return S_OK; } Z7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)) { return E_NOTIMPL; } #else static const Byte kArcProps[] = { kpidHeadersSize, kpidMethod, kpidSolid, kpidNumBlocks // , kpidIsTree }; IMP_IInArchive_ArcProps static inline char GetHex(unsigned value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id) { int len = 0; do { s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; } while (id != 0); return (unsigned)-len; } static void ConvertMethodIdToString(AString &res, UInt64 id) { const unsigned kLen = 32; char s[kLen]; unsigned len = kLen - 1; s[len] = 0; res += s + len - ConvertMethodIdToString_Back(s + len, id); } static char *GetStringForSizeValue(char *s, UInt32 val) { for (unsigned i = 0; i < 32; i++) if (((UInt32)1 << i) == val) { if (i >= 10) { *s++= (char)('0' + i / 10); i %= 10; } *s++ = (char)('0' + i); *s = 0; return s; } char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } s = ConvertUInt32ToString(val, s); *s++ = c; *s = 0; return s; } static void GetLzma2String(char *s, unsigned d) { if (d > 40) { *s = 0; return; // s = MyStpCpy(s, "unsup"); } else if ((d & 1) == 0) d = (d >> 1) + 12; else { // s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11)); d = (d >> 1) + 1; char c = 'k'; if (d >= 10) { c = 'm'; d -= 10; } s = ConvertUInt32ToString((UInt32)3 << d, s); *s++ = c; *s = 0; return; } ConvertUInt32ToString(d, s); } /* static inline void AddHexToString(UString &res, Byte value) { res += GetHex((Byte)(value >> 4)); res += GetHex((Byte)(value & 0xF)); } */ static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); return ConvertUInt32ToString(v, s); } void CHandler::AddMethodName(AString &s, UInt64 id) { AString name; FindMethod(EXTERNAL_CODECS_VARS id, name); if (name.IsEmpty()) ConvertMethodIdToString(s, id); else s += name; } #endif Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) { #ifndef Z7_SFX COM_TRY_BEGIN #endif NCOM::CPropVariant prop; switch (propID) { #ifndef Z7_SFX case kpidMethod: { AString s; const CParsedMethods &pm = _db.ParsedMethods; FOR_VECTOR (i, pm.IDs) { UInt64 id = pm.IDs[i]; s.Add_Space_if_NotEmpty(); char temp[16]; if (id == k_LZMA2) { s += "LZMA2:"; GetLzma2String(temp, pm.Lzma2Prop); s += temp; } else if (id == k_LZMA) { s += "LZMA:"; GetStringForSizeValue(temp, pm.LzmaDic); s += temp; } /* else if (id == k_ZSTD) { s += "ZSTD"; } */ else AddMethodName(s, id); } prop = s; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break; /* case kpidIsTree: if (_db.IsTree) prop = true; break; case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break; case kpidIsAux: if (_db.IsTree) prop = true; break; */ // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break; #endif case kpidWarningFlags: { UInt32 v = 0; if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError; if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature; if (v != 0) prop = v; break; } case kpidErrorFlags: { UInt32 v = 0; if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc; if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError; if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported; if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature; prop = v; break; } case kpidReadOnly: { if (!_db.CanUpdate()) prop = true; break; } default: break; } return prop.Detach(value); #ifndef Z7_SFX COM_TRY_END #endif } static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index) { UInt64 value; if (v.GetItem(index, value)) PropVarEm_Set_FileTime64_Prec(prop, value, k_PropVar_TimePrec_100ns); } bool CHandler::IsFolderEncrypted(CNum folderIndex) const { if (folderIndex == kNumNoIndex) return false; const size_t startPos = _db.FoCodersDataOffset[folderIndex]; const Byte *p = _db.CodersData.ConstData() + startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; CInByte2 inByte; inByte.Init(p, size); CNum numCoders = inByte.ReadNum(); for (; numCoders != 0; numCoders--) { const Byte mainByte = inByte.ReadByte(); const unsigned idSize = (mainByte & 0xF); const Byte *longID = inByte.GetPtr(); UInt64 id64 = 0; for (unsigned j = 0; j < idSize; j++) id64 = ((id64 << 8) | longID[j]); inByte.SkipDataNoCheck(idSize); if (id64 == k_AES) return true; if ((mainByte & 0x20) != 0) inByte.SkipDataNoCheck(inByte.ReadNum()); } return false; } Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)) { *numProps = 0; return S_OK; } Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)) { *name = NULL; *propID = kpidNtSecure; return S_OK; } Z7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)) { /* const CFileItem &file = _db.Files[index]; *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir); *parent = (UInt32)(Int32)file.Parent; */ *parentType = NParentType::kDir; *parent = (UInt32)(Int32)-1; return S_OK; } Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) { *data = NULL; *dataSize = 0; *propType = 0; if (/* _db.IsTree && propID == kpidName || !_db.IsTree && */ propID == kpidPath) { if (_db.NameOffsets && _db.NamesBuf) { const size_t offset = _db.NameOffsets[index]; const size_t size = (_db.NameOffsets[index + 1] - offset) * 2; if (size < ((UInt32)1 << 31)) { *data = (const void *)(_db.NamesBuf.ConstData() + offset * 2); *dataSize = (UInt32)size; *propType = NPropDataType::kUtf16z; } } return S_OK; } /* if (propID == kpidNtSecure) { if (index < (UInt32)_db.SecureIDs.Size()) { int id = _db.SecureIDs[index]; size_t offs = _db.SecureOffsets[id]; size_t size = _db.SecureOffsets[id + 1] - offs; if (size >= 0) { *data = _db.SecureBuf + offs; *dataSize = (UInt32)size; *propType = NPropDataType::kRaw; } } } */ return S_OK; } #ifndef Z7_SFX HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { PropVariant_Clear(prop); if (folderIndex == kNumNoIndex) return S_OK; // for (int ttt = 0; ttt < 1; ttt++) { const unsigned kTempSize = 256; char temp[kTempSize]; unsigned pos = kTempSize; temp[--pos] = 0; const size_t startPos = _db.FoCodersDataOffset[folderIndex]; const Byte *p = _db.CodersData.ConstData() + startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; CInByte2 inByte; inByte.Init(p, size); // numCoders == 0 ??? CNum numCoders = inByte.ReadNum(); bool needSpace = false; for (; numCoders != 0; numCoders--, needSpace = true) { if (pos < 32) // max size of property break; const Byte mainByte = inByte.ReadByte(); UInt64 id64 = 0; const unsigned idSize = (mainByte & 0xF); const Byte *longID = inByte.GetPtr(); for (unsigned j = 0; j < idSize; j++) id64 = ((id64 << 8) | longID[j]); inByte.SkipDataNoCheck(idSize); if ((mainByte & 0x10) != 0) { inByte.ReadNum(); // NumInStreams inByte.ReadNum(); // NumOutStreams } CNum propsSize = 0; const Byte *props = NULL; if ((mainByte & 0x20) != 0) { propsSize = inByte.ReadNum(); props = inByte.GetPtr(); inByte.SkipDataNoCheck(propsSize); } const char *name = NULL; char s[32]; s[0] = 0; if (id64 <= (UInt32)0xFFFFFFFF) { const UInt32 id = (UInt32)id64; if (id == k_LZMA) { name = "LZMA"; if (propsSize == 5) { const UInt32 dicSize = GetUi32((const Byte *)props + 1); char *dest = GetStringForSizeValue(s, dicSize); UInt32 d = props[0]; if (d != 0x5D) { const UInt32 lc = d % 9; d /= 9; const UInt32 pb = d / 5; const UInt32 lp = d % 5; if (lc != 3) dest = AddProp32(dest, "lc", lc); if (lp != 0) dest = AddProp32(dest, "lp", lp); if (pb != 2) dest = AddProp32(dest, "pb", pb); } } } else if (id == k_LZMA2) { name = "LZMA2"; if (propsSize == 1) GetLzma2String(s, props[0]); } else if (id == k_PPMD) { name = "PPMD"; if (propsSize == 5) { char *dest = s; *dest++ = 'o'; dest = ConvertUInt32ToString(*props, dest); dest = MyStpCpy(dest, ":mem"); GetStringForSizeValue(dest, GetUi32(props + 1)); } } else if (id == k_Delta) { name = "Delta"; if (propsSize == 1) ConvertUInt32ToString((UInt32)props[0] + 1, s); } else if (id == k_ARM64 || id == k_RISCV) { name = id == k_ARM64 ? "ARM64" : "RISCV"; if (propsSize == 4) ConvertUInt32ToString(GetUi32(props), s); /* else if (propsSize != 0) MyStringCopy(s, "unsupported"); */ } else if (id == k_BCJ2) name = "BCJ2"; else if (id == k_BCJ) name = "BCJ"; else if (id == k_AES) { name = "7zAES"; if (propsSize >= 1) { const Byte firstByte = props[0]; const UInt32 numCyclesPower = firstByte & 0x3F; ConvertUInt32ToString(numCyclesPower, s); } } } if (name) { const unsigned nameLen = MyStringLen(name); const unsigned propsLen = MyStringLen(s); unsigned totalLen = nameLen + propsLen; if (propsLen != 0) totalLen++; if (needSpace) totalLen++; if (totalLen + 5 >= pos) break; pos -= totalLen; MyStringCopy(temp + pos, name); if (propsLen != 0) { char *dest = temp + pos + nameLen; *dest++ = ':'; MyStringCopy(dest, s); } if (needSpace) temp[pos + totalLen - 1] = ' '; } else { AString methodName; FindMethod(EXTERNAL_CODECS_VARS id64, methodName); if (needSpace) temp[--pos] = ' '; if (methodName.IsEmpty()) pos -= ConvertMethodIdToString_Back(temp + pos, id64); else { const unsigned len = methodName.Len(); if (len + 5 > pos) break; pos -= len; for (unsigned i = 0; i < len; i++) temp[pos + i] = methodName[i]; } } } if (numCoders != 0 && pos >= 4) { temp[--pos] = ' '; temp[--pos] = '.'; temp[--pos] = '.'; temp[--pos] = '.'; } return PropVarEm_Set_Str(prop, temp + pos); // } } #endif Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { RINOK(PropVariant_Clear(value)) // COM_TRY_BEGIN // NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; const UInt32 index2 = index; switch (propID) { case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; case kpidSize: { PropVarEm_Set_UInt64(value, item.Size); // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex)); /* else PropVarEm_Set_UInt64(value, 0); */ } else PropVarEm_Set_UInt64(value, 0); } break; } // case kpidIsAux: prop = _db.IsItemAux(index2); break; case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; } case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break; case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break; case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break; case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break; case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break; case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break; case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break; /* case kpidIsAltStream: prop = item.IsAltStream; break; case kpidNtSecure: { int id = _db.SecureIDs[index]; size_t offs = _db.SecureOffsets[id]; size_t size = _db.SecureOffsets[id + 1] - offs; if (size >= 0) { prop.SetBlob(_db.SecureBuf + offs, (ULONG)size); } break; } */ case kpidPath: return _db.GetPath_Prop(index, value); #ifndef Z7_SFX case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); case kpidBlock: { const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) PropVarEm_Set_UInt32(value, (UInt32)folderIndex); } break; #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && _db.FoStartPackStreamIndex[folderIndex + 1] - _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0)) { PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0)); } } else PropVarEm_Set_UInt64(value, 0); } break; #endif #endif default: break; } // return prop.Detach(value); return S_OK; // COM_TRY_END } Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback)) { COM_TRY_BEGIN Close(); #ifndef Z7_SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr openArchiveCallbackTemp = openArchiveCallback; #ifndef Z7_NO_CRYPTO CMyComPtr getTextPassword; if (openArchiveCallback) openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif CInArchive archive( #ifdef Z7_7Z_SET_PROPERTIES _useMultiThreadMixer #else true #endif ); _db.IsArc = false; RINOK(archive.Open(stream, maxCheckStartPosition)) _db.IsArc = true; HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef Z7_NO_CRYPTO , getTextPassword, _isEncrypted, _passwordIsDefined, _password #endif ); RINOK(result) _inStream = stream; } catch(...) { Close(); // return E_INVALIDARG; // return S_FALSE; // we must return out_of_memory here return E_OUTOFMEMORY; } // _inStream = stream; #ifndef Z7_SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } Z7_COM7F_IMF(CHandler::Close()) { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); #ifndef Z7_NO_CRYPTO _isEncrypted = false; _passwordIsDefined = false; _password.Wipe_and_Empty(); #endif return S_OK; COM_TRY_END } #ifdef Z7_7Z_SET_PROPERTIES #ifdef Z7_EXTRACT_ONLY Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) { COM_TRY_BEGIN InitCommon(); _useMultiThreadMixer = true; for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; const unsigned index = ParseStringToUInt32(name, number); if (index == 0) { if (name.IsEqualTo("mtf")) { RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer)) continue; } { HRESULT hres; if (SetCommonProperty(name, value, hres)) { RINOK(hres) continue; } } return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} tmp41wklro_/CPP/7zip/Archive/7z/7zHandler.h0000444000175000001440000000704114620120460021401 0ustar nabijaczleweliusers// 7z/Handler.h #ifndef ZIP7_7Z_HANDLER_H #define ZIP7_7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #ifndef Z7_7Z_SET_PROPERTIES #ifdef Z7_EXTRACT_ONLY #if !defined(Z7_ST) && !defined(Z7_SFX) #define Z7_7Z_SET_PROPERTIES #endif #else #define Z7_7Z_SET_PROPERTIES #endif #endif // #ifdef Z7_7Z_SET_PROPERTIES #include "../Common/HandlerOut.h" // #endif #include "7zCompressionMode.h" #include "7zIn.h" namespace NArchive { namespace N7z { #ifndef Z7_EXTRACT_ONLY class COutHandler: public CMultiMethodProps { HRESULT SetSolidFromString(const UString &s); HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value); public: UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _useTypeSorting; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; // bool _useParents; 9.26 CHandlerTimeOptions TimeOptions; CBoolPair Write_Attrib; bool _useMultiThreadMixer; bool _removeSfxBlock; // bool _volumeMode; UInt32 _decoderCompatibilityVersion; CUIntVector _enabledFilters; CUIntVector _disabledFilters; void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void InitProps7z(); void InitProps(); COutHandler() { InitProps7z(); } HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); }; #endif class CHandler Z7_final: public IInArchive, public IArchiveGetRawProps, #ifdef Z7_7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef Z7_EXTRACT_ONLY public IOutArchive, #endif Z7_PUBLIC_ISetCompressCodecsInfo_IFEC public CMyUnknownImp, #ifndef Z7_EXTRACT_ONLY public COutHandler #else public CCommonMethodProps #endif { Z7_COM_QI_BEGIN2(IInArchive) Z7_COM_QI_ENTRY(IArchiveGetRawProps) #ifdef Z7_7Z_SET_PROPERTIES Z7_COM_QI_ENTRY(ISetProperties) #endif #ifndef Z7_EXTRACT_ONLY Z7_COM_QI_ENTRY(IOutArchive) #endif Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IInArchive) Z7_IFACE_COM7_IMP(IArchiveGetRawProps) #ifdef Z7_7Z_SET_PROPERTIES Z7_IFACE_COM7_IMP(ISetProperties) #endif #ifndef Z7_EXTRACT_ONLY Z7_IFACE_COM7_IMP(IOutArchive) #endif DECL_ISetCompressCodecsInfo private: CMyComPtr _inStream; NArchive::N7z::CDbEx _db; #ifndef Z7_NO_CRYPTO bool _isEncrypted; bool _passwordIsDefined; UString _password; // _Wipe #endif #ifdef Z7_EXTRACT_ONLY #ifdef Z7_7Z_SET_PROPERTIES bool _useMultiThreadMixer; #endif UInt32 _crcSize; #else CRecordVector _bonds; HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); HRESULT SetMainMethod(CCompressionMethodMode &method); #endif bool IsFolderEncrypted(CNum folderIndex) const; #ifndef Z7_SFX CRecordVector _fileInfoPopIDs; void FillPopIDs(); void AddMethodName(AString &s, UInt64 id); HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const; #endif DECL_EXTERNAL_CODECS_VARS public: CHandler(); ~CHandler() { Close(); } }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zHandlerOut.cpp0000444000175000001440000007743714620127500022446 0ustar nabijaczleweliusers// 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../../Common/Wildcard.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" #ifndef Z7_EXTRACT_ONLY using namespace NWindows; namespace NArchive { namespace N7z { static const UInt32 k_decoderCompatibilityVersion = 2301; // 7-Zip version 2301 supports ARM64 filter #define k_LZMA_Name "LZMA" #define kDefaultMethodName "LZMA2" #define k_Copy_Name "Copy" #define k_MatchFinder_ForHeaders "BT2" static const UInt32 k_NumFastBytes_ForHeaders = 273; static const UInt32 k_Level_ForHeaders = 5; static const UInt32 k_Dictionary_ForHeaders = #ifdef UNDER_CE 1 << 18; #else 1 << 20; #endif Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type)) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) { bool isFilter; dest.CodecIndex = FindMethod_Index( EXTERNAL_CODECS_VARS m.MethodName, true, dest.Id, dest.NumStreams, isFilter); if (dest.CodecIndex < 0) return E_INVALIDARG; (CProps &)dest = (CProps &)m; return S_OK; } HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) { if (!_compressHeaders) return S_OK; COneMethodInfo m; m.MethodName = k_LZMA_Name; m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); m.AddProp_Level(k_Level_ForHeaders); m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); m.AddProp_NumThreads(1); CMethodFull &methodFull = headerMethod.Methods.AddNew(); return PropsMethod_To_FullMethod(methodFull, m); } HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) { methodMode.Bonds = _bonds; // we create local copy of _methods. So we can modify it. CObjectVector methods = _methods; { FOR_VECTOR (i, methods) { AString &methodName = methods[i].MethodName; if (methodName.IsEmpty()) methodName = kDefaultMethodName; } if (methods.IsEmpty()) { COneMethodInfo &m = methods.AddNew(); m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); methodMode.DefaultMethod_was_Inserted = true; } } if (!_filterMethod.MethodName.IsEmpty()) { // if (methodMode.Bonds.IsEmpty()) { FOR_VECTOR (k, methodMode.Bonds) { CBond2 &bond = methodMode.Bonds[k]; bond.InCoder++; bond.OutCoder++; } methods.Insert(0, _filterMethod); methodMode.Filter_was_Inserted = true; } } const UInt64 kSolidBytes_Min = (1 << 24); const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); bool needSolid = false; FOR_VECTOR (i, methods) { COneMethodInfo &oneMethodInfo = methods[i]; SetGlobalLevelTo(oneMethodInfo); #ifndef Z7_ST const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); if (!numThreads_WasSpecifiedInMethod) { // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads); } #endif CMethodFull &methodFull = methodMode.Methods.AddNew(); RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)) #ifndef Z7_ST methodFull.Set_NumThreads = true; methodFull.NumThreads = methodMode.NumThreads; #endif if (methodFull.Id != k_Copy) needSolid = true; UInt64 dicSize; switch (methodFull.Id) { case k_LZMA: case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; case k_Deflate: dicSize = (UInt32)1 << 15; break; case k_Deflate64: dicSize = (UInt32)1 << 16; break; case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; // case k_ZSTD: dicSize = 1 << 23; break; default: continue; } UInt64 numSolidBytes; /* if (methodFull.Id == k_ZSTD) { // continue; NCompress::NZstd::CEncoderProps encoderProps; RINOK(oneMethodInfo.Set_PropsTo_zstd(encoderProps)); CZstdEncProps &zstdProps = encoderProps.EncProps; ZstdEncProps_NormalizeFull(&zstdProps); UInt64 cs = (UInt64)(zstdProps.jobSize); UInt32 winSize = (UInt32)(1 << zstdProps.windowLog); if (cs < winSize) cs = winSize; numSolidBytes = cs << 6; const UInt64 kSolidBytes_Zstd_Max = ((UInt64)1 << 34); if (numSolidBytes > kSolidBytes_Zstd_Max) numSolidBytes = kSolidBytes_Zstd_Max; methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder #ifndef Z7_ST if (!numThreads_WasSpecifiedInMethod && !methodMode.NumThreads_WasForced && methodMode.MemoryUsageLimit_WasSet ) { const UInt32 numThreads_Original = methodMode.NumThreads; const UInt32 numThreads_New = ZstdEncProps_GetNumThreads_for_MemUsageLimit( &zstdProps, methodMode.MemoryUsageLimit, numThreads_Original); if (numThreads_Original != numThreads_New) { CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New); } } #endif } else */ if (methodFull.Id == k_LZMA2) { // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code /* lzma2 code use dictionary up to fake 4 GiB to calculate ChunkSize. So we do same */ UInt64 cs = (UInt64)dicSize << 2; const UInt32 kMinSize = (UInt32)1 << 20; const UInt32 kMaxSize = (UInt32)1 << 28; if (cs < kMinSize) cs = kMinSize; if (cs > kMaxSize) cs = kMaxSize; if (cs < dicSize) cs = dicSize; cs += (kMinSize - 1); cs &= ~(UInt64)(kMinSize - 1); // we want to use at least 64 chunks (threads) per one solid block. // here we don't use chunkSize property numSolidBytes = cs << 6; // here we get real chunkSize cs = oneMethodInfo.Get_Xz_BlockSize(); if (dicSize > cs) dicSize = cs; const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); if (numSolidBytes > kSolidBytes_Lzma2_Max) numSolidBytes = kSolidBytes_Lzma2_Max; methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder #ifndef Z7_ST if (!numThreads_WasSpecifiedInMethod && !methodMode.NumThreads_WasForced && methodMode.MemoryUsageLimit_WasSet ) { const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads; if (numBlockThreads_Original > 1) { /* const UInt32 kNumThreads_Max = 1024; if (numBlockThreads > kNumMaxThreads) numBlockThreads = kNumMaxThreads; */ UInt32 numBlockThreads = numBlockThreads_Original; const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); // solid for (; numBlockThreads > 1; numBlockThreads--) { UInt64 size = numBlockThreads * (lzmaMemUsage + cs); UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; if (cs < ((UInt32)1 << 26)) numPackChunks++; if (cs < ((UInt32)1 << 24)) numPackChunks++; if (cs < ((UInt32)1 << 22)) numPackChunks++; size += numPackChunks * cs; // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20)); if (size <= methodMode.MemoryUsageLimit) break; } if (numBlockThreads == 0) numBlockThreads = 1; if (numBlockThreads != numBlockThreads_Original) { const UInt32 numThreads_New = numBlockThreads * lzmaThreads; CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New); } } } #endif } else { numSolidBytes = (UInt64)dicSize << 7; if (numSolidBytes > kSolidBytes_Max) numSolidBytes = kSolidBytes_Max; } if (_numSolidBytesDefined) continue; if (numSolidBytes < kSolidBytes_Min) numSolidBytes = kSolidBytes_Min; _numSolidBytes = numSolidBytes; _numSolidBytesDefined = true; } if (!_numSolidBytesDefined) { if (needSolid) _numSolidBytes = kSolidBytes_Max; else _numSolidBytes = 0; } _numSolidBytesDefined = true; return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined) { // ft = 0; // ftDefined = false; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)) if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; else { ft = 0; ftDefined = false; } return S_OK; } /* #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } static int FillSortIndex(CObjectVector &treeFolders, int cur, int curSortIndex) { CTreeFolder &tf = treeFolders[cur]; tf.SortIndex = curSortIndex++; for (int i = 0; i < tf.SubFolders.Size(); i++) curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex); tf.SortIndexEnd = curSortIndex; return curSortIndex; } static int FindSubFolder(const CObjectVector &treeFolders, int cur, const UString &name, int &insertPos) { const CIntVector &subFolders = treeFolders[cur].SubFolders; int left = 0, right = subFolders.Size(); insertPos = -1; for (;;) { if (left == right) { insertPos = left; return -1; } int mid = (left + right) / 2; int midFolder = subFolders[mid]; int compare = CompareFileNames(name, treeFolders[midFolder].Name); if (compare == 0) return midFolder; if (compare < 0) right = mid; else left = mid + 1; } } static int AddFolder(CObjectVector &treeFolders, int cur, const UString &name) { int insertPos; int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos); if (folderIndex < 0) { folderIndex = treeFolders.Size(); CTreeFolder &newFolder = treeFolders.AddNew(); newFolder.Parent = cur; newFolder.Name = name; treeFolders[cur].SubFolders.Insert(insertPos, folderIndex); } // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234; return folderIndex; } */ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback)) { COM_TRY_BEGIN const CDbEx *db = NULL; #ifdef Z7_7Z_VOL if (_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream) db = &_db; #endif if (db && !db->CanUpdate()) return E_NOTIMPL; /* Z7_DECL_CMyComPtr_QI_FROM( IArchiveGetRawProps, getRawProps, updateCallback) CUniqBlocks secureBlocks; secureBlocks.AddUniq(NULL, 0); CObjectVector treeFolders; { CTreeFolder folder; folder.Parent = -1; treeFolders.Add(folder); } */ CObjectVector updateItems; bool need_CTime = (TimeOptions.Write_CTime.Def && TimeOptions.Write_CTime.Val); bool need_ATime = (TimeOptions.Write_ATime.Def && TimeOptions.Write_ATime.Val); bool need_MTime = (TimeOptions.Write_MTime.Def ? TimeOptions.Write_MTime.Val : true); bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); if (db && !db->Files.IsEmpty()) { if (!TimeOptions.Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); if (!TimeOptions.Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); if (!TimeOptions.Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); } // UString s; UString name; for (UInt32 i = 0; i < numItems; i++) { Int32 newData, newProps; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)) CUpdateItem ui; ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArchive = (int)indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; name.Empty(); // bool isAltStream = false; if (ui.IndexInArchive != -1) { if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size()) return E_INVALIDARG; const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive]; if (!ui.NewProps) { _db.GetPath((unsigned)ui.IndexInArchive, name); } ui.IsDir = fi.IsDir; ui.Size = fi.Size; // isAltStream = fi.IsAltStream; ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive); if (!ui.NewProps) { ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime); } } if (ui.NewProps) { bool folderStatusIsDefined; if (need_Attrib) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)) if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined)) if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined)) if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined)) /* if (getRawProps) { const void *data; UInt32 dataSize; UInt32 propType; getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); if (dataSize != 0 && propType != NPropDataType::kRaw) return E_FAIL; ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize); } */ { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)) if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { name = prop.bstrVal; NItemName::ReplaceSlashes_OsToUnix(name); } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)) if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)) if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } /* { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop)); if (prop.vt == VT_EMPTY) isAltStream = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else isAltStream = (prop.boolVal != VARIANT_FALSE); } */ if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } else { /* if (_db.SecureIDs.IsEmpty()) ui.SecureIndex = secureBlocks.AddUniq(NULL, 0); else { int id = _db.SecureIDs[ui.IndexInArchive]; size_t offs = _db.SecureOffsets[id]; size_t size = _db.SecureOffsets[id + 1] - offs; ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size); } */ } /* { int folderIndex = 0; if (_useParents) { int j; s.Empty(); for (j = 0; j < name.Len(); j++) { wchar_t c = name[j]; if (IsCharDirLimiter(c)) { folderIndex = AddFolder(treeFolders, folderIndex, s); s.Empty(); continue; } s += c; } if (isAltStream) { int colonPos = s.Find(':'); if (colonPos < 0) { // isAltStream = false; return E_INVALIDARG; } UString mainName = s.Left(colonPos); int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName); if (treeFolders[newFolderIndex].UpdateItemIndex < 0) { for (int j = updateItems.Size() - 1; j >= 0; j--) { CUpdateItem &ui2 = updateItems[j]; if (ui2.ParentFolderIndex == folderIndex && ui2.Name == mainName) { ui2.TreeFolderIndex = newFolderIndex; treeFolders[newFolderIndex].UpdateItemIndex = j; } } } folderIndex = newFolderIndex; s.Delete(0, colonPos + 1); } ui.Name = s; } else ui.Name = name; ui.IsAltStream = isAltStream; ui.ParentFolderIndex = folderIndex; ui.TreeFolderIndex = -1; if (ui.IsDir && !s.IsEmpty()) { ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s); treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size(); } } */ ui.Name = name; if (ui.NewData) { ui.Size = 0; if (!ui.IsDir) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)) if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } } updateItems.Add(ui); } /* FillSortIndex(treeFolders, 0, 0); for (i = 0; i < (UInt32)updateItems.Size(); i++) { CUpdateItem &ui = updateItems[i]; ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex; ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd; } */ CCompressionMethodMode methodMode, headerMethod; methodMode.MemoryUsageLimit = _memUsage_Compress; methodMode.MemoryUsageLimit_WasSet = _memUsage_WasSet; #ifndef Z7_ST { UInt32 numThreads = _numThreads; const UInt32 kNumThreads_Max = 1024; if (numThreads > kNumThreads_Max) numThreads = kNumThreads_Max; methodMode.NumThreads = numThreads; methodMode.NumThreads_WasForced = _numThreads_WasForced; methodMode.MultiThreadMixer = _useMultiThreadMixer; // headerMethod.NumThreads = 1; headerMethod.MultiThreadMixer = _useMultiThreadMixer; } #endif const HRESULT res = SetMainMethod(methodMode); RINOK(res) RINOK(SetHeaderMethod(headerMethod)) Z7_DECL_CMyComPtr_QI_FROM( ICryptoGetTextPassword2, getPassword2, updateCallback) methodMode.PasswordIsDefined = false; methodMode.Password.Wipe_and_Empty(); if (getPassword2) { CMyComBSTR_Wipe password; Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)) methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined && password) methodMode.Password = password; } bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; #ifndef Z7_NO_CRYPTO if (!methodMode.PasswordIsDefined && _passwordIsDefined) { // if header is compressed, we use that password for updated archive methodMode.PasswordIsDefined = true; methodMode.Password = _password; } #endif if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef Z7_NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if (encryptHeaders) { headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; headerMethod.Password = methodMode.Password; } } if (numItems < 2) compressMainHeader = false; const int level = GetLevel(); CUpdateOptions options; options.Need_CTime = need_CTime; options.Need_ATime = need_ATime; options.Need_MTime = need_MTime; options.Need_Attrib = need_Attrib; // options.Need_Crc = (_crcSize != 0); // for debug options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); options.MaxFilter = (level >= 8); options.AnalysisLevel = GetAnalysisLevel(); options.SetFilterSupporting_ver_enabled_disabled( _decoderCompatibilityVersion, _enabledFilters, _disabledFilters); options.HeaderOptions.CompressMainHeader = compressMainHeader; /* options.HeaderOptions.WriteCTime = Write_CTime; options.HeaderOptions.WriteATime = Write_ATime; options.HeaderOptions.WriteMTime = Write_MTime; options.HeaderOptions.WriteAttrib = Write_Attrib; */ options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.UseTypeSorting = _useTypeSorting; options.RemoveSfxBlock = _removeSfxBlock; // options.VolumeMode = _volumeMode; options.MultiThreadMixer = _useMultiThreadMixer; /* if (secureBlocks.Sorted.Size() > 1) { secureBlocks.GetReverseMap(); for (int i = 0; i < updateItems.Size(); i++) { int &secureIndex = updateItems[i].SecureIndex; secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex]; } } */ return Update( EXTERNAL_CODECS_VARS #ifdef Z7_7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, // treeFolders, // secureBlocks, outStream, updateCallback, options); COM_TRY_END } static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; { const unsigned index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.DeleteFrontal(index); } if (srcString[0] == 's') { srcString.Delete(0); const unsigned index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.DeleteFrontal(index); } return S_OK; } void COutHandler::InitProps7z() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; // _useParents = false; TimeOptions.Init(); Write_Attrib.Init(); _useMultiThreadMixer = true; // _volumeMode = false; InitSolid(); _useTypeSorting = false; _decoderCompatibilityVersion = k_decoderCompatibilityVersion; _enabledFilters.Clear(); _disabledFilters.Clear(); } void COutHandler::InitProps() { CMultiMethodProps::Init(); InitProps7z(); } HRESULT COutHandler::SetSolidFromString(const UString &s) { UString s2 = s; s2.MakeLower_Ascii(); for (unsigned i = 0; i < s2.Len();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'e') return E_INVALIDARG; _solidExtension = true; continue; } i += (unsigned)(end - start); if (i == s2.Len()) return E_INVALIDARG; const wchar_t c = s2[i++]; if (c == 'f') { if (v < 1) v = 1; _numSolidFiles = v; } else { unsigned numBits; switch (c) { case 'b': numBits = 0; break; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; default: return E_INVALIDARG; } _numSolidBytes = (v << numBits); _numSolidBytesDefined = true; /* if (_numSolidBytes == 0) _numSolidFiles = 1; */ } } return S_OK; } HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) { bool isSolid; switch (value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidFromString(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) { RINOK(PROPVARIANT_to_bool(prop, dest.Val)) dest.Def = true; return S_OK; } struct C_Id_Name_pair { UInt32 Id; const char *Name; }; static const C_Id_Name_pair g_filter_pairs[] = { { k_Delta, "Delta" }, { k_ARM64, "ARM64" }, { k_RISCV, "RISCV" }, { k_SWAP2, "SWAP2" }, { k_SWAP4, "SWAP4" }, { k_BCJ, "BCJ" }, { k_BCJ2 , "BCJ2" }, { k_PPC, "PPC" }, { k_IA64, "IA64" }, { k_ARM, "ARM" }, { k_ARMT, "ARMT" }, { k_SPARC, "SPARC" } }; HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == L's') { name.Delete(0); if (name.IsEmpty()) return SetSolidFromPROPVARIANT(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidFromString(name); } UInt32 number; const unsigned index = ParseStringToUInt32(name, number); // UString realName = name.Ptr(index); if (index == 0) { if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders); // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents); if (name.IsEqualTo("hcf")) { bool compressHeadersFull = true; RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)) return compressHeadersFull ? S_OK: E_INVALIDARG; } if (name.IsEqualTo("he")) { RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)) _encryptHeadersSpecified = true; return S_OK; } { bool processed; RINOK(TimeOptions.Parse(name, value, processed)) if (processed) { if ( TimeOptions.Prec != (UInt32)(Int32)-1 && TimeOptions.Prec != k_PropVar_TimePrec_0 && TimeOptions.Prec != k_PropVar_TimePrec_HighPrec && TimeOptions.Prec != k_PropVar_TimePrec_100ns) return E_INVALIDARG; return S_OK; } } if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); if (name.IsPrefixedBy_Ascii_NoCase("yv")) { name.Delete(0, 2); UInt32 v = 1 << 16; // if no number is noit specified, we use big value RINOK(ParsePropToUInt32(name, value, v)) _decoderCompatibilityVersion = v; // if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion; return S_OK; } if (name.IsPrefixedBy_Ascii_NoCase("yf")) { name.Delete(0, 2); CUIntVector *vec; if (name.IsEqualTo_Ascii_NoCase("a")) vec = &_enabledFilters; else if (name.IsEqualTo_Ascii_NoCase("d")) vec = &_disabledFilters; else return E_INVALIDARG; if (value.vt != VT_BSTR) return E_INVALIDARG; for (unsigned k = 0;; k++) { if (k == Z7_ARRAY_SIZE(g_filter_pairs)) { // maybe we can ignore unsupported filter names here? return E_INVALIDARG; } const C_Id_Name_pair &pair = g_filter_pairs[k]; if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name)) { vec->AddToUniqueSorted(pair.Id); break; } } return S_OK; } // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); } return CMultiMethodProps::SetProperty(name, value); } Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) { COM_TRY_BEGIN _bonds.Clear(); InitProps(); for (UInt32 i = 0; i < numProps; i++) { UString name = names[i]; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name.Find(L':') >= 0) // 'b' was used as NCoderPropID::kBlockSize2 before v23 if (name[0] == 'b') { if (value.vt != VT_EMPTY) return E_INVALIDARG; name.Delete(0); CBond2 bond; RINOK(ParseBond(name, bond.OutCoder, bond.OutStream)) if (name[0] != ':') return E_INVALIDARG; name.Delete(0); UInt32 inStream = 0; RINOK(ParseBond(name, bond.InCoder, inStream)) if (inStream != 0) return E_INVALIDARG; if (!name.IsEmpty()) return E_INVALIDARG; _bonds.Add(bond); continue; } RINOK(SetProperty(name, value)) } unsigned numEmptyMethods = GetNumEmptyMethods(); if (numEmptyMethods > 0) { unsigned k; for (k = 0; k < _bonds.Size(); k++) { const CBond2 &bond = _bonds[k]; if (bond.InCoder < (UInt32)numEmptyMethods || bond.OutCoder < (UInt32)numEmptyMethods) return E_INVALIDARG; } for (k = 0; k < _bonds.Size(); k++) { CBond2 &bond = _bonds[k]; bond.InCoder -= (UInt32)numEmptyMethods; bond.OutCoder -= (UInt32)numEmptyMethods; } _methods.DeleteFrontal(numEmptyMethods); } FOR_VECTOR (k, _bonds) { const CBond2 &bond = _bonds[k]; if (bond.InCoder >= (UInt32)_methods.Size() || bond.OutCoder >= (UInt32)_methods.Size()) return E_INVALIDARG; } return S_OK; COM_TRY_END } }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zHeader.cpp0000444000175000001440000000076714400604220021554 0ustar nabijaczleweliusers// 7zHeader.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef Z7_7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif // We can change signature. So file doesn't contain correct signature. // struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } }; // static SignatureInitializer g_SignatureInitializer; }} tmp41wklro_/CPP/7zip/Archive/7z/7zHeader.h0000444000175000001440000000533614571036020021224 0ustar nabijaczleweliusers// 7z/7zHeader.h #ifndef ZIP7_INC_7Z_HEADER_H #define ZIP7_INC_7Z_HEADER_H #include "../../../Common/MyTypes.h" namespace NArchive { namespace N7z { const unsigned kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define Z7_7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef Z7_7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef Z7_7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttrib, kComment, kEncodedHeader, kStartPos, kDummy // kNtSecure, // kParent, // kIsAux }; } const UInt32 k_Copy = 0; const UInt32 k_Delta = 3; const UInt32 k_ARM64 = 0xa; const UInt32 k_RISCV = 0xb; const UInt32 k_LZMA2 = 0x21; const UInt32 k_SWAP2 = 0x20302; const UInt32 k_SWAP4 = 0x20304; const UInt32 k_LZMA = 0x30101; const UInt32 k_PPMD = 0x30401; const UInt32 k_Deflate = 0x40108; const UInt32 k_Deflate64 = 0x40109; const UInt32 k_BZip2 = 0x40202; const UInt32 k_BCJ = 0x3030103; const UInt32 k_BCJ2 = 0x303011B; const UInt32 k_PPC = 0x3030205; const UInt32 k_IA64 = 0x3030401; const UInt32 k_ARM = 0x3030501; const UInt32 k_ARMT = 0x3030701; const UInt32 k_SPARC = 0x3030805; const UInt32 k_AES = 0x6F10701; // const UInt32 k_ZSTD = 0x4015D; // winzip zstd // 0x4F71101, 7z-zstd inline bool IsFilterMethod(UInt64 m) { if (m > (UInt32)0xFFFFFFFF) return false; switch ((UInt32)m) { case k_Delta: case k_ARM64: case k_RISCV: case k_BCJ: case k_BCJ2: case k_PPC: case k_IA64: case k_ARM: case k_ARMT: case k_SPARC: case k_SWAP2: case k_SWAP4: return true; default: break; } return false; } }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zIn.cpp0000444000175000001440000013047614564072620020751 0ustar nabijaczleweliusers// 7zIn.cpp #include "StdAfx.h" #ifdef _WIN32 #include #else #include #endif #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" #include "../../../Common/MyBuffer2.h" // #include "../../../Common/UTFConvert.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef Z7_SFX #define FORMAT_7Z_RECOVERY #endif using namespace NWindows; using namespace NCOM; unsigned BoolVector_CountSum(const CBoolVector &v); Z7_NO_INLINE unsigned BoolVector_CountSum(const CBoolVector &v) { unsigned sum = 0; const unsigned size = v.Size(); if (size) { const bool *p = v.ConstData(); const bool * const lim = p + size; do if (*p) sum++; while (++p != lim); } return sum; } static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) { return i < v.Size() ? v[i] : false; } Z7_NO_INLINE static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { v.ClearAndSetSize(size); bool *p = v.NonConstData(); for (unsigned i = 0; i < size; i++) p[i] = false; } namespace NArchive { namespace N7z { #define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64 class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; Z7_ATTR_NORETURN static void ThrowException() { throw CInArchiveException(); } Z7_ATTR_NORETURN static inline void ThrowEndOfData() { ThrowException(); } Z7_ATTR_NORETURN static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } Z7_ATTR_NORETURN static inline void ThrowIncorrect() { ThrowException(); } class CStreamSwitch { CInArchive *_archive; bool _needRemove; bool _needUpdatePos; public: CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { if (_archive->_inByteBack->GetRem() != 0) _archive->ThereIsHeaderError = true; _archive->DeleteByteStream(_needUpdatePos); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; _needUpdatePos = needUpdatePos; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.Size(), false); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) { Remove(); const Byte external = archive->ReadByte(); if (external != 0) { if (!dataVector) ThrowIncorrect(); const CNum dataIndex = archive->ReadNum(); if (dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } void CInArchive::AddByteStream(const Byte *buf, size_t size) { if (_numInByteBufs == kNumBufLevelsMax) ThrowIncorrect(); _inByteBack = &_inByteVector[_numInByteBufs++]; _inByteBack->Init(buf, size); } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size == 0) return; if (size > _size - _pos) ThrowEndOfData(); memcpy(data, _buffer + _pos, size); _pos += size; } void CInByte2::SkipData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkipData() { SkipData(ReadNumber()); } static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) { if (size == 0) { processed = 0; return 0; } const unsigned b = *p++; size--; if ((b & 0x80) == 0) { processed = 1; return b; } if (size == 0) { processed = 0; return 0; } UInt64 value = (UInt64)*p; p++; size--; for (unsigned i = 1; i < 8; i++) { const unsigned mask = (unsigned)0x80 >> i; if ((b & mask) == 0) { const UInt64 high = b & (mask - 1); value |= (high << (i * 8)); processed = i + 1; return value; } if (size == 0) { processed = 0; return 0; } value |= ((UInt64)*p << (i * 8)); p++; size--; } processed = 9; return value; } UInt64 CInByte2::ReadNumber() { size_t processed; const UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); if (processed == 0) ThrowEndOfData(); _pos += processed; return res; } CNum CInByte2::ReadNum() { /* if (_pos < _size) { Byte val = _buffer[_pos]; if ((unsigned)val < 0x80) { _pos++; return (unsigned)val; } } */ const UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); const UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); const UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } #define Y0 '7' #define Y1 'z' #define Y2 0xBC #define Y3 0xAF #define Y4 0x27 #define Y5 0x1C #define IS_SIGNATURE(p)( \ (p)[2] == Y2 && \ (p)[3] == Y3 && \ (p)[5] == Y5 && \ (p)[4] == Y4 && \ (p)[1] == Y1 && \ (p)[0] == Y0) /* FindSignature_10() is allowed to access data up to and including &limit[9]. limit[10] access is not allowed. return: (return_ptr < limit) : signature was found at (return_ptr) (return_ptr >= limit) : limit was reached or crossed. So no signature found before limit */ Z7_NO_INLINE static const Byte *FindSignature_10(const Byte *p, const Byte *limit) { for (;;) { for (;;) { if (p >= limit) return limit; const Byte b = p[5]; p += 6; if (b == Y0) { break; } if (b == Y1) { p -= 1; break; } if (b == Y2) { p -= 2; break; } if (b == Y3) { p -= 3; break; } if (b == Y4) { p -= 4; break; } if (b == Y5) { p -= 5; break; } } if (IS_SIGNATURE(p - 1)) return p - 1; } } static inline bool TestStartCrc(const Byte *p) { return CrcCalc(p + 12, 20) == Get32(p + 8); } static inline bool TestSignature2(const Byte *p) { if (!IS_SIGNATURE(p)) return false; #ifdef FORMAT_7Z_RECOVERY if (TestStartCrc(p)) return true; for (unsigned i = 8; i < kHeaderSize; i++) if (p[i] != 0) return false; return (p[6] != 0 || p[7] != 0); #else return TestStartCrc(p); #endif } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)) if (TestSignature2(_header)) return S_OK; if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) return S_FALSE; const UInt32 kBufSize = (1 << 15) + kHeaderSize; // must be > (kHeaderSize * 2) CAlignedBuffer1 buf(kBufSize); memcpy(buf, _header, kHeaderSize); UInt64 offset = 0; for (;;) { UInt32 readSize = (offset == 0) ? kBufSize - kHeaderSize - kHeaderSize : kBufSize - kHeaderSize; if (searchHeaderSizeLimit) { const UInt64 rem = *searchHeaderSizeLimit - offset; if (readSize > rem) readSize = (UInt32)rem; if (readSize == 0) return S_FALSE; } UInt32 processed = 0; RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)) if (processed == 0) return S_FALSE; /* &buf[0] was already tested for signature before. So first search here will be for &buf[1] */ for (UInt32 pos = 0;;) { const Byte *p = buf + pos + 1; const Byte *lim = buf + processed + 1; /* we have (kHeaderSize - 1 = 31) filled bytes starting from (lim), and it's safe to access just 10 bytes in that reserved area */ p = FindSignature_10(p, lim); if (p >= lim) break; pos = (UInt32)(p - buf); if (TestStartCrc(p)) { memcpy(_header, p, kHeaderSize); _arhiveBeginStreamPosition += offset + pos; return InStream_SeekSet(stream, _arhiveBeginStreamPosition + kHeaderSize); } } offset += processed; memmove(buf, buf + processed, kHeaderSize); } } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(InStream_GetPos_GetSize(stream, _arhiveBeginStreamPosition, _fileEndPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)) _stream = stream; return S_OK; } void CInArchive::Close() { _numInByteBufs = 0; _stream.Release(); ThereIsHeaderError = false; } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkipData(); } } // CFolder &folder can be non empty. So we must set all fields void CInByte2::ParseFolder(CFolder &folder) { const UInt32 numCoders = ReadNum(); if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) ThrowUnsupported(); folder.Coders.SetSize(numCoders); UInt32 numInStreams = 0; UInt32 i; for (i = 0; i < numCoders; i++) { CCoderInfo &coder = folder.Coders[i]; { const Byte mainByte = ReadByte(); if ((mainByte & 0xC0) != 0) ThrowUnsupported(); const unsigned idSize = (mainByte & 0xF); if (idSize > 8 || idSize > GetRem()) ThrowUnsupported(); const Byte *longID = GetPtr(); UInt64 id = 0; for (unsigned j = 0; j < idSize; j++) id = ((id << 8) | longID[j]); SkipDataNoCheck(idSize); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumStreams = ReadNum(); // if (coder.NumStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported(); /* numOutStreams = */ ReadNum(); // if (ReadNum() != 1) // numOutStreams ThrowUnsupported(); } else { coder.NumStreams = 1; } if ((mainByte & 0x20) != 0) { const CNum propsSize = ReadNum(); coder.Props.Alloc((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } else coder.Props.Free(); } numInStreams += coder.NumStreams; } const UInt32 numBonds = numCoders - 1; folder.Bonds.SetSize(numBonds); for (i = 0; i < numBonds; i++) { CBond &bp = folder.Bonds[i]; bp.PackIndex = ReadNum(); bp.UnpackIndex = ReadNum(); } if (numInStreams < numBonds) ThrowUnsupported(); const UInt32 numPackStreams = numInStreams - numBonds; folder.PackStreams.SetSize(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBond_for_PackStream(i) < 0) { folder.PackStreams[0] = i; break; } if (i == numInStreams) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams[i] = ReadNum(); } void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const { const size_t startPos = FoCodersDataOffset[folderIndex]; CInByte2 inByte; inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); inByte.ParseFolder(folder); if (inByte.GetRem() != 0) throw 20120424; } void CDatabase::GetPath(unsigned index, UString &path) const { path.Empty(); if (!NameOffsets || !NamesBuf) return; const size_t offset = NameOffsets[index]; const size_t size = NameOffsets[index + 1] - offset; if (size >= (1 << 28)) return; wchar_t *s = path.GetBuf((unsigned)size - 1); const Byte *p = ((const Byte *)NamesBuf + offset * 2); #if defined(_WIN32) && defined(MY_CPU_LE) wmemcpy(s, (const wchar_t *)(const void *)p, size); #else for (size_t i = 0; i < size; i++) { *s = Get16(p); p += 2; s++; } #endif path.ReleaseBuf_SetLen((unsigned)size - 1); } HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() { PropVariant_Clear(path); if (!NameOffsets || !NamesBuf) return S_OK; const size_t offset = NameOffsets[index]; const size_t size = NameOffsets[index + 1] - offset; if (size >= (1 << 14)) return S_OK; // (size) includes null terminator /* #if WCHAR_MAX > 0xffff const Byte *p = ((const Byte *)NamesBuf + offset * 2); size = Utf16LE__Get_Num_WCHARs(p, size - 1); // (size) doesn't include null terminator RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size)); wchar_t *s = path->bstrVal; wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s); *sEnd = 0; if (s + size != sEnd) return E_FAIL; #else */ RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)) wchar_t *s = path->bstrVal; const Byte *p = ((const Byte *)NamesBuf + offset * 2); // Utf16LE__To_WCHARs_Sep(p, size, s); for (size_t i = 0; i < size; i++) { wchar_t c = Get16(p); p += 2; #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; else if (c == L'\\') c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif *s++ = c; } // #endif return S_OK; /* unsigned cur = index; unsigned size = 0; for (int i = 0;; i++) { size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; size += (unsigned)len; if (i > 256 || len > (1 << 14) || size > (1 << 14)) return PropVarEm_Set_Str(path, "[TOO-LONG]"); cur = Files[cur].Parent; if (cur < 0) break; } size--; RINOK(PropVarEm_Alloc_Bstr(path, size)); wchar_t *s = path->bstrVal; s += size; *s = 0; cur = index; for (;;) { unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; for (; len != 0; len--) { p -= 2; --s; wchar_t c = Get16(p); if (c == '/') c = WCHAR_PATH_SEPARATOR; *s = c; } const CFileItem &file = Files[cur]; cur = file.Parent; if (cur < 0) return S_OK; *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); } */ } void CInArchive::WaitId(UInt64 id) { for (;;) { const UInt64 type = ReadID(); if (type == id) return; if (type == NID::kEnd) ThrowIncorrect(); SkipData(); } } void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v) { const unsigned numItems = v.Defs.Size(); v.Vals.ClearAndSetSize(numItems); UInt32 *p = &v.Vals[0]; const bool *defs = &v.Defs[0]; for (unsigned i = 0; i < numItems; i++) { UInt32 a = 0; if (defs[i]) a = ReadUInt32(); p[i] = a; } } void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) { ReadBoolVector2(numItems, crcs.Defs); Read_UInt32_Vector(crcs); } void CInArchive::ReadPackInfo(CFolders &f) { const CNum numPackStreams = ReadNum(); WaitId(NID::kSize); f.PackPositions.Alloc(numPackStreams + 1); f.NumPackStreams = numPackStreams; UInt64 sum = 0; for (CNum i = 0; i < numPackStreams; i++) { f.PackPositions[i] = sum; const UInt64 packSize = ReadNumber(); sum += packSize; if (sum < packSize) ThrowIncorrect(); } f.PackPositions[numPackStreams] = sum; UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CUInt32DefVector PackCRCs; ReadHashDigests(numPackStreams, PackCRCs); continue; } SkipData(); } } void CInArchive::ReadUnpackInfo( const CObjectVector *dataVector, CFolders &folders) { WaitId(NID::kFolder); const CNum numFolders = ReadNum(); CNum numCodersOutStreams = 0; { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); const Byte *startBufPtr = _inByteBack->GetPtr(); folders.NumFolders = numFolders; folders.FoStartPackStreamIndex.Alloc(numFolders + 1); folders.FoToMainUnpackSizeIndex.Alloc(numFolders); folders.FoCodersDataOffset.Alloc(numFolders + 1); folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); CBoolVector StreamUsed; CBoolVector CoderUsed; CNum packStreamIndex = 0; CNum fo; CInByte2 *inByte = _inByteBack; for (fo = 0; fo < numFolders; fo++) { UInt32 indexOfMainStream = 0; UInt32 numPackStreams = 0; folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); CNum numInStreams = 0; const CNum numCoders = inByte->ReadNum(); if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) ThrowUnsupported(); for (CNum ci = 0; ci < numCoders; ci++) { const Byte mainByte = inByte->ReadByte(); if ((mainByte & 0xC0) != 0) ThrowUnsupported(); const unsigned idSize = (mainByte & 0xF); if (idSize > 8) ThrowUnsupported(); if (idSize > inByte->GetRem()) ThrowEndOfData(); const Byte *longID = inByte->GetPtr(); UInt64 id = 0; for (unsigned j = 0; j < idSize; j++) id = ((id << 8) | longID[j]); inByte->SkipDataNoCheck(idSize); if (folders.ParsedMethods.IDs.Size() < 128) folders.ParsedMethods.IDs.AddToUniqueSorted(id); CNum coderInStreams = 1; if ((mainByte & 0x10) != 0) { coderInStreams = inByte->ReadNum(); if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported(); if (inByte->ReadNum() != 1) ThrowUnsupported(); } numInStreams += coderInStreams; if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported(); if ((mainByte & 0x20) != 0) { const CNum propsSize = inByte->ReadNum(); if (propsSize > inByte->GetRem()) ThrowEndOfData(); if (id == k_LZMA2 && propsSize == 1) { const Byte v = *_inByteBack->GetPtr(); if (folders.ParsedMethods.Lzma2Prop < v) folders.ParsedMethods.Lzma2Prop = v; } else if (id == k_LZMA && propsSize == 5) { const UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); if (folders.ParsedMethods.LzmaDic < dicSize) folders.ParsedMethods.LzmaDic = dicSize; } inByte->SkipDataNoCheck((size_t)propsSize); } } if (numCoders == 1 && numInStreams == 1) { indexOfMainStream = 0; numPackStreams = 1; } else { UInt32 i; const CNum numBonds = numCoders - 1; if (numInStreams < numBonds) ThrowUnsupported(); BoolVector_Fill_False(StreamUsed, numInStreams); BoolVector_Fill_False(CoderUsed, numCoders); for (i = 0; i < numBonds; i++) { CNum index = ReadNum(); if (index >= numInStreams || StreamUsed[index]) ThrowUnsupported(); StreamUsed[index] = true; index = ReadNum(); if (index >= numCoders || CoderUsed[index]) ThrowUnsupported(); CoderUsed[index] = true; } numPackStreams = numInStreams - numBonds; if (numPackStreams != 1) for (i = 0; i < numPackStreams; i++) { const CNum index = inByte->ReadNum(); // PackStreams if (index >= numInStreams || StreamUsed[index]) ThrowUnsupported(); StreamUsed[index] = true; } for (i = 0; i < numCoders; i++) if (!CoderUsed[i]) { indexOfMainStream = i; break; } if (i == numCoders) ThrowUnsupported(); } folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; numCodersOutStreams += numCoders; folders.FoStartPackStreamIndex[fo] = packStreamIndex; if (numPackStreams > folders.NumPackStreams - packStreamIndex) ThrowIncorrect(); packStreamIndex += numPackStreams; folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.CodersData.CopyFrom(startBufPtr, dataSize); // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); } WaitId(NID::kCodersUnpackSize); folders.CoderUnpackSizes.Alloc(numCodersOutStreams); for (CNum i = 0; i < numCodersOutStreams; i++) folders.CoderUnpackSizes[i] = ReadNumber(); for (;;) { const UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { ReadHashDigests(numFolders, folders.FolderCRCs); continue; } SkipData(); } } void CInArchive::ReadSubStreamsInfo( CFolders &folders, CRecordVector &unpackSizes, CUInt32DefVector &digests) { folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); CNum i; for (i = 0; i < folders.NumFolders; i++) folders.NumUnpackStreamsVector[i] = 1; UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (i = 0; i < folders.NumFolders; i++) folders.NumUnpackStreamsVector[i] = ReadNum(); continue; } if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) break; SkipData(); } if (type == NID::kSize) { for (i = 0; i < folders.NumFolders; i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty const CNum numSubstreams = folders.NumUnpackStreamsVector[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) { const UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; if (sum < size) ThrowIncorrect(); } const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); if (folderUnpackSize < sum) ThrowIncorrect(); unpackSizes.Add(folderUnpackSize - sum); } type = ReadID(); } else { for (i = 0; i < folders.NumFolders; i++) { /* v9.26 - v9.29 incorrectly worked: if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ const CNum val = folders.NumUnpackStreamsVector[i]; if (val > 1) ThrowIncorrect(); if (val == 1) unpackSizes.Add(folders.GetFolderUnpackSize(i)); } } unsigned numDigests = 0; for (i = 0; i < folders.NumFolders; i++) { const CNum numSubstreams = folders.NumUnpackStreamsVector[i]; if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) numDigests += numSubstreams; } for (;;) { if (type == NID::kEnd) break; if (type == NID::kCRC) { // CUInt32DefVector digests2; // ReadHashDigests(numDigests, digests2); CBoolVector digests2; ReadBoolVector2(numDigests, digests2); digests.ClearAndSetSize(unpackSizes.Size()); unsigned k = 0; unsigned k2 = 0; for (i = 0; i < folders.NumFolders; i++) { const CNum numSubstreams = folders.NumUnpackStreamsVector[i]; if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { digests.Defs[k] = true; digests.Vals[k] = folders.FolderCRCs.Vals[i]; k++; } else for (CNum j = 0; j < numSubstreams; j++) { bool defined = digests2[k2++]; digests.Defs[k] = defined; UInt32 crc = 0; if (defined) crc = ReadUInt32(); digests.Vals[k] = crc; k++; } } // if (k != unpackSizes.Size()) throw 1234567; } else SkipData(); type = ReadID(); } if (digests.Defs.Size() != unpackSizes.Size()) { digests.ClearAndSetSize(unpackSizes.Size()); unsigned k = 0; for (i = 0; i < folders.NumFolders; i++) { const CNum numSubstreams = folders.NumUnpackStreamsVector[i]; if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { digests.Defs[k] = true; digests.Vals[k] = folders.FolderCRCs.Vals[i]; k++; } else for (CNum j = 0; j < numSubstreams; j++) { digests.Defs[k] = false; digests.Vals[k] = 0; k++; } } } } void CInArchive::ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, CFolders &folders, CRecordVector &unpackSizes, CUInt32DefVector &digests) { UInt64 type = ReadID(); if (type == NID::kPackInfo) { dataOffset = ReadNumber(); if (dataOffset > _rangeLimit) ThrowIncorrect(); ReadPackInfo(folders); if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset) ThrowIncorrect(); type = ReadID(); } if (type == NID::kUnpackInfo) { ReadUnpackInfo(dataVector, folders); type = ReadID(); } if (folders.NumFolders != 0 && !folders.PackPositions) { // if there are folders, we need PackPositions also folders.PackPositions.Alloc(1); folders.PackPositions[0] = 0; } if (type == NID::kSubStreamsInfo) { ReadSubStreamsInfo(folders, unpackSizes, digests); type = ReadID(); } else { folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); /* If digests.Defs.Size() == 0, it means that there are no crcs. So we don't need to fill digests with values. */ // digests.Vals.ClearAndSetSize(folders.NumFolders); // BoolVector_Fill_False(digests.Defs, folders.NumFolders); for (CNum i = 0; i < folders.NumFolders; i++) { folders.NumUnpackStreamsVector[i] = 1; unpackSizes.Add(folders.GetFolderUnpackSize(i)); // digests.Vals[i] = 0; } } if (type != NID::kEnd) ThrowIncorrect(); } void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) { v.ClearAndSetSize(numItems); Byte b = 0; Byte mask = 0; bool *p = &v[0]; for (unsigned i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } p[i] = ((b & mask) != 0); mask = (Byte)(mask >> 1); } } void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) { const Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.ClearAndSetSize(numItems); bool *p = &v[0]; for (unsigned i = 0; i < numItems; i++) p[i] = true; } void CInArchive::ReadUInt64DefVector(const CObjectVector &dataVector, CUInt64DefVector &v, unsigned numItems) { ReadBoolVector2(numItems, v.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Vals.ClearAndSetSize(numItems); UInt64 *p = &v.Vals[0]; const bool *defs = &v.Defs[0]; for (unsigned i = 0; i < numItems; i++) { UInt64 t = 0; if (defs[i]) t = ReadUInt64(); p[i] = t; } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector Z7_7Z_DECODER_CRYPRO_VARS_DECL ) { CFolders folders; CRecordVector unpackSizes; CUInt32DefVector digests; ReadStreamsInfo(NULL, dataOffset, folders, unpackSizes, digests); CDecoder decoder(_useMixerMT); for (CNum i = 0; i < folders.NumFolders; i++) { CByteBuffer &data = dataVector.AddNew(); const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); const size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.Alloc(unpackSize); CMyComPtr2_Create outStreamSpec; outStreamSpec->Init(data, unpackSize); bool dataAfterEnd_Error = false; HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, baseOffset + dataOffset, folders, i, NULL, // &unpackSize64 outStreamSpec, NULL, // *compressProgress NULL // **inStreamMainRes , dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS #if !defined(Z7_ST) , false // mtMode , 1 // numThreads , 0 // memUsage #endif ); RINOK(result) if (dataAfterEnd_Error) ThereIsHeaderError = true; if (unpackSize != outStreamSpec->GetPos()) ThrowIncorrect(); if (folders.FolderCRCs.ValidAndDefined(i)) if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); } if (folders.PackPositions) HeadersSize += folders.PackPositions[folders.NumPackStreams]; return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArcInfo); type = ReadID(); } CObjectVector dataVector; if (type == NID::kAdditionalStreamsInfo) { const HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArcInfo.StartPositionAfterHeader, db.ArcInfo.DataStartPosition2, dataVector Z7_7Z_DECODER_CRYPRO_VARS ); RINOK(result) db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector unpackSizes; CUInt32DefVector digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArcInfo.DataStartPosition, (CFolders &)db, unpackSizes, digests); db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } if (type == NID::kFilesInfo) { const CNum numFiles = ReadNum(); db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); // if (!db.PackSizes.IsEmpty()) db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.Defs.IsEmpty()) db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; CBoolVector emptyFileVector; CBoolVector antiFileVector; unsigned numEmptyStreams = 0; for (;;) { const UInt64 type2 = ReadID(); if (type2 == NID::kEnd) break; const UInt64 size = ReadNumber(); if (size > _inByteBack->GetRem()) ThrowIncorrect(); CStreamSwitch switchProp; switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); bool addPropIdToList = true; bool isKnownType = true; if (type2 > ((UInt32)1 << 30)) isKnownType = false; else switch ((UInt32)type2) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); const size_t rem = _inByteBack->GetRem(); db.NamesBuf.Alloc(rem); ReadBytes(db.NamesBuf, rem); db.NameOffsets.Alloc(numFiles + 1); size_t pos = 0; unsigned i; for (i = 0; i < numFiles; i++) { const size_t curRem = (rem - pos) / 2; const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos); size_t j; for (j = 0; j < curRem && buf[j] != 0; j++); if (j == curRem) ThrowEndOfData(); db.NameOffsets[i] = pos / 2; pos += j * 2 + 2; } db.NameOffsets[i] = pos / 2; if (pos != rem) ThereIsHeaderError = true; break; } case NID::kWinAttrib: { ReadBoolVector2(numFiles, db.Attrib.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); Read_UInt32_Vector(db.Attrib); break; } /* case NID::kIsAux: { ReadBoolVector(numFiles, db.IsAux); break; } case NID::kParent: { db.IsTree = true; // CBoolVector boolVector; // ReadBoolVector2(numFiles, boolVector); // CStreamSwitch streamSwitch; // streamSwitch.Set(this, &dataVector); CBoolVector boolVector; ReadBoolVector2(numFiles, boolVector); db.ThereAreAltStreams = false; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; // file.Parent = -1; // if (boolVector[i]) file.Parent = (int)ReadUInt32(); file.IsAltStream = !boolVector[i]; if (file.IsAltStream) db.ThereAreAltStreams = true; } break; } */ case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); numEmptyStreams = BoolVector_CountSum(emptyStreamVector); emptyFileVector.Clear(); antiFileVector.Clear(); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThereIsHeaderError = true; addPropIdToList = false; break; } /* case NID::kNtSecure: { try { { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); UInt32 numDescriptors = ReadUInt32(); size_t offset = 0; db.SecureOffsets.Clear(); for (i = 0; i < numDescriptors; i++) { UInt32 size = ReadUInt32(); db.SecureOffsets.Add(offset); offset += size; } // ThrowIncorrect();; db.SecureOffsets.Add(offset); db.SecureBuf.SetCapacity(offset); for (i = 0; i < numDescriptors; i++) { offset = db.SecureOffsets[i]; ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); } db.SecureIDs.Clear(); for (unsigned i = 0; i < numFiles; i++) { db.SecureIDs.Add(ReadNum()); // db.SecureIDs.Add(ReadUInt32()); } // ReadUInt32(); if (_inByteBack->GetRem() != 0) ThrowIncorrect();; } } catch(CInArchiveException &) { ThereIsHeaderError = true; addPropIdToList = isKnownType = false; db.ClearSecure(); } break; } */ default: addPropIdToList = isKnownType = false; } if (isKnownType) { if (addPropIdToList) db.ArcInfo.FileInfoPopIDs.Add(type2); } else { db.UnsupportedFeatureWarning = true; _inByteBack->SkipRem(); } // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02) if (_inByteBack->GetRem() != 0) ThrowIncorrect(); } type = ReadID(); // Read (NID::kEnd) end of headers if (numFiles - numEmptyStreams != unpackSizes.Size()) ThrowUnsupported(); CNum emptyFileIndex = 0; CNum sizeIndex = 0; const unsigned numAntiItems = BoolVector_CountSum(antiFileVector); if (numAntiItems != 0) db.IsAnti.ClearAndSetSize(numFiles); db.Files.ClearAndSetSize(numFiles); for (CNum i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.Crc = 0; if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i)) { file.HasStream = true; file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.CrcDefined = digests.ValidAndDefined(sizeIndex); if (file.CrcDefined) file.Crc = digests.Vals[sizeIndex]; sizeIndex++; } else { file.HasStream = false; file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex); isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex); emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti[i] = isAnti; } } db.FillLinks(); if (type != NID::kEnd || _inByteBack->GetRem() != 0) { db.UnsupportedFeatureWarning = true; // ThrowIncorrect(); } return S_OK; } void CDbEx::FillLinks() { FolderStartFileIndex.Alloc(NumFolders); FileIndexToFolderIndexMap.Alloc(Files.Size()); CNum folderIndex = 0; CNum indexInFolder = 0; unsigned i; for (i = 0; i < Files.Size(); i++) { const bool emptyStream = !Files[i].HasStream; if (indexInFolder == 0) { if (emptyStream) { FileIndexToFolderIndexMap[i] = kNumNoIndex; continue; } // v3.13 incorrectly worked with empty folders // v4.07: we skip empty folders for (;;) { if (folderIndex >= NumFolders) ThrowIncorrect(); FolderStartFileIndex[folderIndex] = i; if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } if (indexInFolder != 0) { folderIndex++; // 18.06 ThereIsHeaderError = true; // ThrowIncorrect(); } for (;;) { if (folderIndex >= NumFolders) return; FolderStartFileIndex[folderIndex] = i; if (NumUnpackStreamsVector[folderIndex] != 0) { // 18.06 ThereIsHeaderError = true; // ThrowIncorrect(); } folderIndex++; } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ) { db.Clear(); db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; db.ArcInfo.Version.Major = _header[6]; db.ArcInfo.Version.Minor = _header[7]; if (db.ArcInfo.Version.Major != kMajorVersion) { // db.UnsupportedVersion = true; return S_FALSE; } UInt64 nextHeaderOffset = Get64(_header + 12); UInt64 nextHeaderSize = Get64(_header + 20); UInt32 nextHeaderCRC = Get32(_header + 28); #ifdef FORMAT_7Z_RECOVERY const UInt32 crcFromArc = Get32(_header + 8); if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, fileSize; RINOK(InStream_GetPos(_stream, cur)) const unsigned kCheckSize = 512; Byte buf[kCheckSize]; RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize)) const UInt64 rem = fileSize - cur; unsigned checkSize = kCheckSize; if (rem < kCheckSize) checkSize = (unsigned)(rem); if (checkSize < 3) return S_FALSE; RINOK(InStream_SeekSet(_stream, fileSize - checkSize)) RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)) if (buf[checkSize - 1] != 0) return S_FALSE; unsigned i; for (i = checkSize - 2;; i--) { if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) || (buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)) break; if (i == 0) return S_FALSE; } nextHeaderSize = checkSize - i; nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(InStream_SeekSet(_stream, cur)) db.StartHeaderWasRecovered = true; } else #endif { // Crc was tested already at signature check // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); } db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; db.PhySize = kHeaderSize; db.IsArc = false; if ((Int64)nextHeaderOffset < 0 || nextHeaderSize > ((UInt64)1 << 62)) return S_FALSE; HeadersSize = kHeaderSize; if (nextHeaderSize == 0) { if (nextHeaderOffset != 0 || nextHeaderCRC != 0) return S_FALSE; db.IsArc = true; db.HeadersSize = HeadersSize; return S_OK; } if (!db.StartHeaderWasRecovered) db.IsArc = true; HeadersSize += nextHeaderSize; // db.EndHeaderOffset = nextHeaderOffset; _rangeLimit = nextHeaderOffset; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) { db.UnexpectedEnd = true; return S_FALSE; } RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL)) const size_t nextHeaderSize_t = (size_t)nextHeaderSize; if (nextHeaderSize_t != nextHeaderSize) return E_OUTOFMEMORY; CByteBuffer buffer2(nextHeaderSize_t); RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)) if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) ThrowIncorrect(); if (!db.StartHeaderWasRecovered) db.PhySizeWasConfirmed = true; CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector dataVector; const UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); const HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArcInfo.StartPositionAfterHeader, db.ArcInfo.DataStartPosition2, dataVector Z7_7Z_DECODER_CRYPRO_VARS ); RINOK(result) if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.IsArc = true; db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db Z7_7Z_DECODER_CRYPRO_VARS ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ) { try { const HRESULT res = ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db Z7_7Z_DECODER_CRYPRO_VARS ); if (ThereIsHeaderError) db.ThereIsHeaderError = true; if (res == E_NOTIMPL) ThrowUnsupported(); return res; } catch(CUnsupportedFeatureException &) { db.UnsupportedFeatureError = true; return S_FALSE; } catch(CInArchiveException &) { db.ThereIsHeaderError = true; return S_FALSE; } } }} tmp41wklro_/CPP/7zip/Archive/7z/7zIn.h0000444000175000001440000002631114564072620020406 0ustar nabijaczleweliusers// 7zIn.h #ifndef ZIP7_INC_7Z_IN_H #define ZIP7_INC_7Z_IN_H #include "../../../Common/MyCom.h" #include "../../../Windows/PropVariant.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { /* We don't need to init isEncrypted and passwordIsDefined We must upgrade them only */ #ifdef Z7_NO_CRYPTO #define Z7_7Z_DECODER_CRYPRO_VARS_DECL #define Z7_7Z_DECODER_CRYPRO_VARS #else #define Z7_7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password #define Z7_7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password #endif struct CParsedMethods { Byte Lzma2Prop; UInt32 LzmaDic; CRecordVector IDs; CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} }; struct CFolderEx: public CFolder { unsigned UnpackCoder; }; struct CFolders { CNum NumPackStreams; CNum NumFolders; CObjArray PackPositions; // NumPackStreams + 1 // CUInt32DefVector PackCRCs; // we don't use PackCRCs now CUInt32DefVector FolderCRCs; // NumFolders CObjArray NumUnpackStreamsVector; // NumFolders CObjArray CoderUnpackSizes; // including unpack sizes of bond coders CObjArray FoToCoderUnpackSizes; // NumFolders + 1 CObjArray FoStartPackStreamIndex; // NumFolders + 1 CObjArray FoToMainUnpackSizeIndex; // NumFolders CObjArray FoCodersDataOffset; // NumFolders + 1 CByteBuffer CodersData; CParsedMethods ParsedMethods; void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const { ParseFolderInfo(folderIndex, folder); folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex]; } unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const { return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]); } UInt64 GetFolderUnpackSize(unsigned folderIndex) const { return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; } UInt64 GetStreamPackSize(unsigned index) const { return PackPositions[index + 1] - PackPositions[index]; } CFolders(): NumPackStreams(0), NumFolders(0) {} void Clear() { NumPackStreams = 0; PackPositions.Free(); // PackCRCs.Clear(); NumFolders = 0; FolderCRCs.Clear(); NumUnpackStreamsVector.Free(); CoderUnpackSizes.Free(); FoToCoderUnpackSizes.Free(); FoStartPackStreamIndex.Free(); FoToMainUnpackSizeIndex.Free(); FoCodersDataOffset.Free(); CodersData.Free(); } }; struct CDatabase: public CFolders { CRecordVector Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CUInt32DefVector Attrib; CBoolVector IsAnti; /* CBoolVector IsAux; CByteBuffer SecureBuf; CRecordVector SecureIDs; */ CByteBuffer NamesBuf; CObjArray NameOffsets; // numFiles + 1, offsets of utf-16 symbols /* void ClearSecure() { SecureBuf.Free(); SecureIDs.Clear(); } */ void Clear() { CFolders::Clear(); // ClearSecure(); NamesBuf.Free(); NameOffsets.Free(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); Attrib.Clear(); IsAnti.Clear(); // IsAux.Clear(); } bool IsSolid() const { for (CNum i = 0; i < NumFolders; i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } /* const void* GetName(unsigned index) const { if (!NameOffsets || !NamesBuf) return NULL; return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); }; */ void GetPath(unsigned index, UString &path) const; HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); }; struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; // in stream UInt64 StartPositionAfterHeader; // in stream UInt64 DataStartPosition; // in stream UInt64 DataStartPosition2; // in stream. it's for headers CRecordVector FileInfoPopIDs; void Clear() { StartPosition = 0; StartPositionAfterHeader = 0; DataStartPosition = 0; DataStartPosition2 = 0; FileInfoPopIDs.Clear(); } }; struct CDbEx: public CDatabase { CInArchiveInfo ArcInfo; CObjArray FolderStartFileIndex; CObjArray FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes) /* CRecordVector SecureOffsets; bool IsTree; bool ThereAreAltStreams; */ bool IsArc; bool PhySizeWasConfirmed; bool ThereIsHeaderError; bool UnexpectedEnd; // bool UnsupportedVersion; bool StartHeaderWasRecovered; bool UnsupportedFeatureWarning; bool UnsupportedFeatureError; /* void ClearSecureEx() { ClearSecure(); SecureOffsets.Clear(); } */ void Clear() { IsArc = false; PhySizeWasConfirmed = false; ThereIsHeaderError = false; UnexpectedEnd = false; // UnsupportedVersion = false; StartHeaderWasRecovered = false; UnsupportedFeatureError = false; UnsupportedFeatureWarning = false; /* IsTree = false; ThereAreAltStreams = false; */ CDatabase::Clear(); // SecureOffsets.Clear(); ArcInfo.Clear(); FolderStartFileIndex.Free(); FileIndexToFolderIndexMap.Free(); HeadersSize = 0; PhySize = 0; // EndHeaderOffset = 0; } bool CanUpdate() const { if (ThereIsHeaderError || UnexpectedEnd || StartHeaderWasRecovered || UnsupportedFeatureError) return false; return true; } void FillLinks(); UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const { return ArcInfo.DataStartPosition + PackPositions.ConstData() [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(size_t folderIndex) const { return PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] - PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]]; } UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const { const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex; return PackPositions.ConstData()[i + 1] - PackPositions.ConstData()[i]; } /* UInt64 GetFilePackSize(size_t fileIndex) const { const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } */ }; const unsigned kNumBufLevelsMax = 4; struct CInByte2 { const Byte *_buffer; public: size_t _size; size_t _pos; size_t GetRem() const { return _size - _pos; } const Byte *GetPtr() const { return _buffer + _pos; } void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } void SkipData(UInt64 size); void SkipData(); void SkipRem() { _pos = _size; } UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ParseFolder(CFolder &folder); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr _stream; unsigned _numInByteBufs; CInByte2 _inByteVector[kNumBufLevelsMax]; CInByte2 *_inByteBack; bool ThereIsHeaderError; UInt64 _arhiveBeginStreamPosition; UInt64 _fileEndPosition; UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) Byte _header[kHeaderSize]; UInt64 HeadersSize; bool _useMixerMT; void AddByteStream(const Byte *buffer, size_t size); void DeleteByteStream(bool needUpdatePos) { _numInByteBufs--; if (_numInByteBufs > 0) { _inByteBack = &_inByteVector[_numInByteBufs - 1]; if (needUpdatePos) _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; } } HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkipData(UInt64 size) { _inByteBack->SkipData(size); } void SkipData() { _inByteBack->SkipData(); } void WaitId(UInt64 id); void Read_UInt32_Vector(CUInt32DefVector &v); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); void ReadPackInfo(CFolders &f); void ReadUnpackInfo( const CObjectVector *dataVector, CFolders &folders); void ReadSubStreamsInfo( CFolders &folders, CRecordVector &unpackSizes, CUInt32DefVector &digests); void ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, CFolders &folders, CRecordVector &unpackSizes, CUInt32DefVector &digests); void ReadBoolVector(unsigned numItems, CBoolVector &v); void ReadBoolVector2(unsigned numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector &dataVector, CUInt64DefVector &v, unsigned numItems); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector Z7_7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ); public: CInArchive(bool useMixerMT): _numInByteBufs(0), _useMixerMT(useMixerMT) {} HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db Z7_7Z_DECODER_CRYPRO_VARS_DECL ); }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zItem.h0000444000175000001440000000735514500042260020730 0ustar nabijaczleweliusers// 7zItem.h #ifndef ZIP7_INC_7Z_ITEM_H #define ZIP7_INC_7Z_ITEM_H #include "../../../Common/MyBuffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; UInt32 NumStreams; bool IsSimpleCoder() const { return NumStreams == 1; } }; struct CBond { UInt32 PackIndex; UInt32 UnpackIndex; }; struct CFolder { Z7_CLASS_NO_COPY(CFolder) public: CObjArray2 Coders; CObjArray2 Bonds; CObjArray2 PackStreams; CFolder() {} bool IsDecodingSupported() const { return Coders.Size() <= 32; } int Find_in_PackStreams(UInt32 packStream) const { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == packStream) return (int)i; return -1; } int FindBond_for_PackStream(UInt32 packStream) const { FOR_VECTOR(i, Bonds) if (Bonds[i].PackIndex == packStream) return (int)i; return -1; } /* int FindBond_for_UnpackStream(UInt32 unpackStream) const { FOR_VECTOR(i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) return i; return -1; } int FindOutCoder() const { for (int i = (int)Coders.Size() - 1; i >= 0; i--) if (FindBond_for_UnpackStream(i) < 0) return i; return -1; } */ bool IsEncrypted() const { FOR_VECTOR(i, Coders) if (Coders[i].MethodID == k_AES) return true; return false; } }; struct CUInt32DefVector { CBoolVector Defs; CRecordVector Vals; void ClearAndSetSize(unsigned newSize) { Defs.ClearAndSetSize(newSize); Vals.ClearAndSetSize(newSize); } void Clear() { Defs.Clear(); Vals.Clear(); } void ReserveDown() { Defs.ReserveDown(); Vals.ReserveDown(); } bool GetItem(unsigned index, UInt32 &value) const { if (index < Defs.Size() && Defs[index]) { value = Vals[index]; return true; } value = 0; return false; } bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; } bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } void SetItem(unsigned index, bool defined, UInt32 value); void if_NonEmpty_FillResidue_with_false(unsigned numItems) { if (Defs.Size() != 0 && Defs.Size() < numItems) SetItem(numItems - 1, false, 0); } }; struct CUInt64DefVector { CBoolVector Defs; CRecordVector Vals; void Clear() { Defs.Clear(); Vals.Clear(); } void ReserveDown() { Defs.ReserveDown(); Vals.ReserveDown(); } bool GetItem(unsigned index, UInt64 &value) const { if (index < Defs.Size() && Defs[index]) { value = Vals[index]; return true; } value = 0; return false; } bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } void SetItem(unsigned index, bool defined, UInt64 value); }; struct CFileItem { UInt64 Size; UInt32 Crc; /* int Parent; bool IsAltStream; */ bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; /* void Clear() { HasStream = true; IsDir = false; CrcDefined = false; } CFileItem(): // Parent(-1), // IsAltStream(false), HasStream(true), IsDir(false), CrcDefined(false), {} */ }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zOut.cpp0000444000175000001440000006564514540255620021154 0ustar nabijaczleweliusers// 7zOut.cpp #include "StdAfx.h" #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" #include "../../../Common/AutoPtr.h" // #include "../../../Common/UTFConvert.h" #include "../../Common/StreamObjects.h" #include "../Common/OutStreamWithCRC.h" #include "7zOut.h" unsigned BoolVector_CountSum(const CBoolVector &v); static UInt64 UInt64Vector_CountSum(const CRecordVector &v) { UInt64 sum = 0; const unsigned size = v.Size(); if (size) { const UInt64 *p = v.ConstData(); const UInt64 * const lim = p + size; do sum += *p++; while (p != lim); } return sum; } namespace NArchive { namespace N7z { static void FillSignature(Byte *buf) { memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 4; } #ifdef Z7_7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[32]; FillSignature(buf); SetUInt64(buf + 8 + 4, h.NextHeaderOffset); SetUInt64(buf + 8 + 12, h.NextHeaderSize); SetUInt32(buf + 8 + 20, h.NextHeaderCRC); SetUInt32(buf + 8, CrcCalc(buf + 8 + 4, 20)); return WriteDirect(buf, sizeof(buf)); } #ifdef Z7_7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */) { Close(); #ifdef Z7_7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; // if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_signatureHeaderPos)) Byte buf[32]; FillSignature(buf); memset(&buf[8], 0, 32 - 8); return WriteDirect(buf, sizeof(buf)); } #ifdef Z7_7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); return S_OK; */ } #endif } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); // _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) WriteByte_ToStream(b); else _outByte2.WriteByte(b); } /* void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } */ void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask = (Byte)(mask >> 1); } WriteByte(firstByte); for (; i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static unsigned GetBigNumberSize(UInt64 value) { unsigned i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef Z7_7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); unsigned i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { UInt64 id = coder.MethodID; unsigned idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; // idSize &= 0xF; // idSize is smaller than 16 already Byte temp[16]; for (unsigned t = idSize; t != 0; t--, id >>= 8) temp[t] = (Byte)(id & 0xFF); unsigned b = idSize; const bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); const size_t propsSize = coder.Props.Size(); b |= ((propsSize != 0) ? 0x20 : 0); temp[0] = (Byte)b; WriteBytes(temp, idSize + 1); if (isComplex) { WriteNumber(coder.NumStreams); WriteNumber(1); // NumOutStreams; } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.Bonds.Size(); i++) { const CBond &bond = folder.Bonds[i]; WriteNumber(bond.PackIndex); WriteNumber(bond.UnpackIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) WriteNumber(folder.PackStreams[i]); } void COutArchive::Write_BoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; FOR_VECTOR (i, boolVector) { if (boolVector[i]) b |= mask; mask = (Byte)(mask >> 1); if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) { WriteByte(id); WriteNumber(Bv_GetSizeInBytes(boolVector)); Write_BoolVector(boolVector); } void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined) { if (numDefined == boolVector.Size()) WriteByte(1); else { WriteByte(0); Write_BoolVector(boolVector); } } void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) { const unsigned numDefined = BoolVector_CountSum(digests.Defs); if (numDefined == 0) return; WriteByte(NID::kCRC); Write_BoolVector_numDefined(digests.Defs, numDefined); Write_UInt32DefVector_numDefined(digests, numDefined); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CUInt32DefVector &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); FOR_VECTOR (i, packSizes) WriteNumber(packSizes[i]); WriteHashDigests(packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector &folders, const COutFolders &outFolders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); FOR_VECTOR (i, folders) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); FOR_VECTOR (i, outFolders.CoderUnpackSizes) WriteNumber(outFolders.CoderUnpackSizes[i]); WriteHashDigests(outFolders.FolderUnpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo(const CObjectVector &folders, const COutFolders &outFolders, const CRecordVector &unpackSizes, const CUInt32DefVector &digests) { const CRecordVector &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; WriteByte(NID::kSubStreamsInfo); unsigned i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) if (numUnpackStreamsInFolders[i] > 1) { WriteByte(NID::kSize); CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { CNum num = numUnpackStreamsInFolders[i]; for (CNum j = 0; j < num; j++) { if (j + 1 != num) WriteNumber(unpackSizes[index]); index++; } } break; } CUInt32DefVector digests2; unsigned digestIndex = 0; for (i = 0; i < folders.Size(); i++) { unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) digestIndex++; else for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) { digests2.Defs.Add(digests.Defs[digestIndex]); digests2.Vals.Add(digests.Vals[digestIndex]); } } WriteHashDigests(digests2); WriteByte(NID::kEnd); } // 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts) { if (!_useAlign) return; const unsigned alignSize = (unsigned)1 << alignShifts; pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts) { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts); WriteByte(type); WriteNumber(dataSize); Write_BoolVector_numDefined(v, numDefined); WriteByte(0); // 0 means no switching to external stream } void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined) { if (_countMode) { _countSize += (size_t)numDefined * 4; return; } const bool * const defs = v.Defs.ConstData(); const UInt32 * const vals = v.Vals.ConstData(); const size_t num = v.Defs.Size(); for (size_t i = 0; i < num; i++) if (defs[i]) { UInt32 value = vals[i]; for (int k = 0; k < 4; k++) { if (_writeToStream) WriteByte_ToStream((Byte)value); else _outByte2.WriteByte((Byte)value); // WriteByte((Byte)value); value >>= 8; } // WriteUInt32(v.Vals[i]); } } void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type) { const unsigned numDefined = BoolVector_CountSum(v.Defs); if (numDefined == 0) return; WriteAlignedBools(v.Defs, numDefined, type, 3); if (_countMode) { _countSize += (size_t)numDefined * 8; return; } const bool * const defs = v.Defs.ConstData(); const UInt64 * const vals = v.Vals.ConstData(); const size_t num = v.Defs.Size(); for (size_t i = 0; i < num; i++) if (defs[i]) { UInt64 value = vals[i]; for (int k = 0; k < 8; k++) { if (_writeToStream) WriteByte_ToStream((Byte)value); else _outByte2.WriteByte((Byte)value); // WriteByte((Byte)value); value >>= 8; } // WriteUInt64(v.Vals[i]); } } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders) { CMyComPtr2_Create streamSpec; streamSpec->Init(data, data.Size()); outFolders.FolderUnpackCRCs.Defs.Add(true); outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); // outFolders.NumUnpackStreamsVector.Add(1); const UInt64 dataSize64 = data.Size(); const UInt64 expectSize = data.Size(); RINOK(encoder.Encode1( EXTERNAL_CODECS_LOC_VARS streamSpec, // NULL, &dataSize64, // inSizeForReduce expectSize, folders.AddNew(), // outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) if (!streamSpec->WasFinished()) return E_FAIL; encoder.Encode_Post(dataSize64, outFolders.CoderUnpackSizes); return S_OK; } void COutArchive::WriteHeader( const CArchiveDatabaseOut &db, // const CHeaderOptions &headerOptions, UInt64 &headerOffset) { /* bool thereIsSecure = (db.SecureBuf.Size() != 0); */ _useAlign = true; headerOffset = UInt64Vector_CountSum(db.PackSizes); WriteByte(NID::kHeader); /* { // It's example for per archive properies writing WriteByte(NID::kArchiveProperties); // you must use random 40-bit number that will identify you // then you can use same kDeveloperID for any properties and methods const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID) { const UInt64 kSubID = 0x1; // you can use small number for subID const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); WriteNumber(kID); const unsigned kPropsSize = 3; // it's example size WriteNumber(kPropsSize); for (unsigned i = 0; i < kPropsSize; i++) WriteByte((Byte)(i & 0xFF)); } { const UInt64 kSubID = 0x2; // you can use small number for subID const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); WriteNumber(kID); const unsigned kPropsSize = 5; // it's example size WriteNumber(kPropsSize); for (unsigned i = 0; i < kPropsSize; i++) WriteByte((Byte)(i + 16)); } WriteByte(NID::kEnd); } */ if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCs); WriteUnpackInfo(db.Folders, (const COutFolders &)db); CRecordVector unpackSizes; CUInt32DefVector digests; FOR_VECTOR (i, db.Files) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digests.Defs.Add(file.CrcDefined); digests.Vals.Add(file.Crc); } WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.ClearAndSetSize(db.Files.Size()); unsigned numEmptyStreams = 0; { FOR_VECTOR (i, db.Files) if (db.Files[i].HasStream) emptyStreamVector[i] = false; else { emptyStreamVector[i] = true; numEmptyStreams++; } } if (numEmptyStreams != 0) { WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.ClearAndSetSize(numEmptyStreams); antiVector.ClearAndSetSize(numEmptyStreams); bool thereAreEmptyFiles = false, thereAreAntiItems = false; unsigned cur = 0; FOR_VECTOR (i, db.Files) { const CFileItem &file = db.Files[i]; if (file.HasStream) continue; emptyFileVector[cur] = !file.IsDir; if (!file.IsDir) thereAreEmptyFiles = true; bool isAnti = db.IsItemAnti(i); antiVector[cur] = isAnti; if (isAnti) thereAreAntiItems = true; cur++; } if (thereAreEmptyFiles) WritePropBoolVector(NID::kEmptyFile, emptyFileVector); if (thereAreAntiItems) WritePropBoolVector(NID::kAnti, antiVector); } } { /* ---------- Names ---------- */ size_t namesDataSize = 0; { FOR_VECTOR (i, db.Files) { const UString &name = db.Names[i]; const size_t numUtfChars = /* #if WCHAR_MAX > 0xffff Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); #else */ name.Len(); // #endif namesDataSize += numUtfChars; } } if (namesDataSize) { namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding namesDataSize++; // for additional switch byte (zero value) SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); WriteByte(NID::kName); WriteNumber(namesDataSize); if (_countMode) _countSize += namesDataSize; else { WriteByte(0); FOR_VECTOR (i, db.Files) { const UString &name = db.Names[i]; const wchar_t *p = name.Ptr(); const size_t len = (size_t)name.Len() + 1; const wchar_t * const lim = p + len; if (_writeToStream) { do { const wchar_t c = *p++; WriteByte_ToStream((Byte)c); WriteByte_ToStream((Byte)(c >> 8)); } while (p != lim); } else { Byte *dest = _outByte2.GetDest_and_Update(len * 2); do { /* #if WCHAR_MAX > 0xffff if (c >= 0x10000) { c -= 0x10000; if (c < (1 << 20)) { unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); WriteByte((Byte)c0); WriteByte((Byte)(c0 >> 8)); c = 0xdc00 + (c & 0x3FF); } else c = '_'; // we change character unsupported by UTF16 } #endif */ const wchar_t c = *p++; SetUi16(dest, (UInt16)c) dest += 2; } while (p != lim); } } } } } /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime); /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime); /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime); Write_UInt64DefVector_type(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); if (numDefined != 0) { WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); Write_UInt32DefVector_numDefined(db.Attrib, numDefined); } } /* { // ---------- Write IsAux ---------- if (BoolVector_CountSum(db.IsAux) != 0) WritePropBoolVector(NID::kIsAux, db.IsAux); } { // ---------- Write Parent ---------- CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); unsigned numIsDir = 0; unsigned numParentLinks = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; bool defined = !file.IsAltStream; boolVector.Add(defined); if (defined) numIsDir++; if (file.Parent >= 0) numParentLinks++; } if (numParentLinks > 0) { // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2); const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2); WriteByte(NID::kParent); WriteNumber(dataSize); Write_BoolVector_numDefined(boolVector, numIsDir); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; // if (file.Parent >= 0) WriteUInt32(file.Parent); } } } if (thereIsSecure) { UInt64 secureDataSize = 1 + 4 + db.SecureBuf.Size() + db.SecureSizes.Size() * 4; // secureDataSize += db.SecureIDs.Size() * 4; for (i = 0; i < db.SecureIDs.Size(); i++) secureDataSize += GetBigNumberSize(db.SecureIDs[i]); SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2); WriteByte(NID::kNtSecure); WriteNumber(secureDataSize); WriteByte(0); WriteUInt32(db.SecureSizes.Size()); for (i = 0; i < db.SecureSizes.Size(); i++) WriteUInt32(db.SecureSizes[i]); WriteBytes(db.SecureBuf, db.SecureBuf.Size()); for (i = 0; i < db.SecureIDs.Size(); i++) { WriteNumber(db.SecureIDs[i]); // WriteUInt32(db.SecureIDs[i]); } } */ WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; CStartHeader sh; sh.NextHeaderOffset = 0; sh.NextHeaderSize = 0; sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0); if (!db.IsEmpty()) { CMyComPtr2_Create crcStream; crcStream->SetStream(SeqStream); crcStream->Init(); bool encodeHeaders = false; if (options) if (options->IsEmpty()) options = NULL; if (options) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; if (!_outByte.Create(1 << 16)) return E_OUTOFMEMORY; _outByte.SetStream(crcStream.Interface()); _outByte.Init(); // _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset); if (encodeHeaders) { CByteBuffer buf(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector packSizes; CObjectVector folders; COutFolders outFolders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, buf, packSizes, folders, outFolders)) _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector()); WriteUnpackInfo(folders, outFolders); WriteByte(NID::kEnd); sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes); } RINOK(_outByte.Flush()) sh.NextHeaderCRC = crcStream->GetCRC(); // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc); // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1; sh.NextHeaderSize = _outByte.GetProcessedSize(); } #ifdef Z7_7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif if (Stream) { RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL)) return WriteStartHeader(sh); } return S_OK; } void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value) { while (index >= Defs.Size()) Defs.Add(false); Defs[index] = defined; if (!defined) return; while (index >= Vals.Size()) Vals.Add(0); Vals[index] = value; } void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) { while (index >= Defs.Size()) Defs.Add(false); Defs[index] = defined; if (!defined) return; while (index >= Vals.Size()) Vals.Add(0); Vals[index] = value; } void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) { unsigned index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); Attrib.SetItem(index, file2.AttribDefined, file2.Attrib); SetItem_Anti(index, file2.IsAnti); // SetItem_Aux(index, file2.IsAux); Names.Add(name); Files.Add(file); } }} tmp41wklro_/CPP/7zip/Archive/7z/7zOut.h0000444000175000001440000001774714530405760020622 0ustar nabijaczleweliusers// 7zOut.h #ifndef ZIP7_INC_7Z_OUT_H #define ZIP7_INC_7Z_OUT_H #include "7zCompressionMode.h" #include "7zEncode.h" #include "7zHeader.h" #include "7zItem.h" #include "../../Common/OutBuffer.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace N7z { const unsigned k_StartHeadersRewriteSize = 32; class CWriteBufferLoc { Byte *_data; Byte *_dataLim; Byte *_dataBase; public: // CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {} void Init(Byte *data, size_t size) { _data = data; _dataBase = data; _dataLim = data + size; } Byte *GetDest_and_Update(size_t size) { Byte *dest = _data; if (size > (size_t)(_dataLim - dest)) throw 1; _data = dest + size; return dest; } void WriteBytes(const void *data, size_t size) { if (size == 0) return; Byte *dest = GetDest_and_Update(size); memcpy(dest, data, size); } void WriteByte(Byte b) { Byte *dest = _data; if (dest == _dataLim) throw 1; *dest++ = b; _data = dest; } size_t GetPos() const { return (size_t)(_data - _dataBase); } }; struct CHeaderOptions { bool CompressMainHeader; /* bool WriteCTime; bool WriteATime; bool WriteMTime; */ CHeaderOptions(): CompressMainHeader(true) /* , WriteCTime(false) , WriteATime(false) , WriteMTime(true) */ {} }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; UInt32 Attrib; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool AttribDefined; bool IsAnti; // bool IsAux; /* void Init() { CTimeDefined = false; ATimeDefined = false; MTimeDefined = false; StartPosDefined = false; AttribDefined = false; IsAnti = false; // IsAux = false; } */ }; struct COutFolders { CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. CRecordVector NumUnpackStreamsVector; CRecordVector CoderUnpackSizes; // including unpack sizes of bond coders void OutFoldersClear() { FolderUnpackCRCs.Clear(); NumUnpackStreamsVector.Clear(); CoderUnpackSizes.Clear(); } void OutFoldersReserveDown() { FolderUnpackCRCs.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); CoderUnpackSizes.ReserveDown(); } }; struct CArchiveDatabaseOut: public COutFolders { CRecordVector PackSizes; CUInt32DefVector PackCRCs; CObjectVector Folders; CRecordVector Files; UStringVector Names; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CUInt32DefVector Attrib; CBoolVector IsAnti; /* CBoolVector IsAux; CByteBuffer SecureBuf; CRecordVector SecureSizes; CRecordVector SecureIDs; void ClearSecure() { SecureBuf.Free(); SecureSizes.Clear(); SecureIDs.Clear(); } */ void Clear() { OutFoldersClear(); PackSizes.Clear(); PackCRCs.Clear(); Folders.Clear(); Files.Clear(); Names.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); Attrib.Clear(); IsAnti.Clear(); /* IsAux.Clear(); ClearSecure(); */ } void ReserveDown() { OutFoldersReserveDown(); PackSizes.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); Files.ReserveDown(); Names.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); Attrib.ReserveDown(); IsAnti.ReserveDown(); /* IsAux.ReserveDown(); */ } bool IsEmpty() const { return ( PackSizes.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Folders.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { unsigned size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && Attrib.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } void SetItem_Anti(unsigned index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } /* void SetItem_Aux(unsigned index, bool isAux) { while (index >= IsAux.Size()) IsAux.Add(false); IsAux[index] = isAux; } */ void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); }; class COutArchive { HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteByte(Byte b); void WriteByte_ToStream(Byte b) { _outByte.WriteByte(b); // _crc = CRC_UPDATE_BYTE(_crc, b); } // void WriteUInt32(UInt32 value); // void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void Write_BoolVector(const CBoolVector &boolVector); void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined); void WritePropBoolVector(Byte id, const CBoolVector &boolVector); void WriteHashDigests(const CUInt32DefVector &digests); void WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CUInt32DefVector &packCRCs); void WriteUnpackInfo( const CObjectVector &folders, const COutFolders &outFolders); void WriteSubStreamsInfo( const CObjectVector &folders, const COutFolders &outFolders, const CRecordVector &unpackSizes, const CUInt32DefVector &digests); void SkipToAligned(unsigned pos, unsigned alignShifts); void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined); void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders); void WriteHeader( const CArchiveDatabaseOut &db, // const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; bool _useAlign; #ifdef Z7_7Z_VOL bool _endMarker; #endif // UInt32 _crc; size_t _countSize; CWriteBufferLoc _outByte2; COutBuffer _outByte; UInt64 _signatureHeaderPos; CMyComPtr Stream; #ifdef Z7_7Z_VOL HRESULT WriteFinishSignature(); HRESULT WriteFinishHeader(const CFinishHeader &h); #endif HRESULT WriteStartHeader(const CStartHeader &h); public: CMyComPtr SeqStream; // COutArchive(); HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */); void Close(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef Z7_7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zProperties.cpp0000444000175000001440000001115014410777020022516 0ustar nabijaczleweliusers// 7zProperties.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zProperties.h" namespace NArchive { namespace N7z { struct CPropMap { Byte FilePropID; // CStatProp StatProp; VARTYPE vt; UInt32 StatPropID; }; // #define STAT_PROP(name, id, vt) { name, id, vt } #define STAT_PROP(name, id, vt) vt, id #define STAT_PROP2(id, vt) STAT_PROP(NULL, id, vt) #define k_7z_id_Encrypted 97 #define k_7z_id_Method 98 #define k_7z_id_Block 99 static const CPropMap kPropMap[] = { { NID::kName, STAT_PROP2(kpidPath, VT_BSTR) }, { NID::kSize, STAT_PROP2(kpidSize, VT_UI8) }, { NID::kPackInfo, STAT_PROP2(kpidPackSize, VT_UI8) }, #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES #define k_7z_id_PackedSize0 100 { k_7z_id_PackedSize0 + 0, STAT_PROP("Pack0", kpidPackedSize0, VT_UI8) }, { k_7z_id_PackedSize0 + 1, STAT_PROP("Pack1", kpidPackedSize1, VT_UI8) }, { k_7z_id_PackedSize0 + 2, STAT_PROP("Pack2", kpidPackedSize2, VT_UI8) }, { k_7z_id_PackedSize0 + 3, STAT_PROP("Pack3", kpidPackedSize3, VT_UI8) }, { k_7z_id_PackedSize0 + 4, STAT_PROP("Pack4", kpidPackedSize4, VT_UI8) }, #endif { NID::kCTime, STAT_PROP2(kpidCTime, VT_FILETIME) }, { NID::kMTime, STAT_PROP2(kpidMTime, VT_FILETIME) }, { NID::kATime, STAT_PROP2(kpidATime, VT_FILETIME) }, { NID::kWinAttrib, STAT_PROP2(kpidAttrib, VT_UI4) }, { NID::kStartPos, STAT_PROP2(kpidPosition, VT_UI8) }, { NID::kCRC, STAT_PROP2(kpidCRC, VT_UI4) }, // { NID::kIsAux, STAT_PROP2(kpidIsAux, VT_BOOL) }, { NID::kAnti, STAT_PROP2(kpidIsAnti, VT_BOOL) } #ifndef Z7_SFX , { k_7z_id_Encrypted, STAT_PROP2(kpidEncrypted, VT_BOOL) } , { k_7z_id_Method, STAT_PROP2(kpidMethod, VT_BSTR) } , { k_7z_id_Block, STAT_PROP2(kpidBlock, VT_UI4) } #endif }; static void CopyOneItem(CRecordVector &src, CRecordVector &dest, const UInt32 item) { FOR_VECTOR (i, src) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector &src, const UInt32 item) { FOR_VECTOR (i, src) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector &dest, const UInt32 item) { FOR_VECTOR (i, dest) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } #define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id); void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef Z7_7Z_VOL if (_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); /* RemoveOneItem(fileInfoPopIDs, NID::kParent); RemoveOneItem(fileInfoPopIDs, NID::kNtSecure); */ COPY_ONE_ITEM(kName) COPY_ONE_ITEM(kAnti) COPY_ONE_ITEM(kSize) COPY_ONE_ITEM(kPackInfo) COPY_ONE_ITEM(kCTime) COPY_ONE_ITEM(kMTime) COPY_ONE_ITEM(kATime) COPY_ONE_ITEM(kWinAttrib) COPY_ONE_ITEM(kCRC) COPY_ONE_ITEM(kComment) _fileInfoPopIDs += fileInfoPopIDs; #ifndef Z7_SFX _fileInfoPopIDs.Add(k_7z_id_Encrypted); _fileInfoPopIDs.Add(k_7z_id_Method); _fileInfoPopIDs.Add(k_7z_id_Block); #endif #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES for (unsigned i = 0; i < 5; i++) _fileInfoPopIDs.Add(k_7z_id_PackedSize0 + i); #endif #ifndef Z7_SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } Z7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps)) { *numProps = _fileInfoPopIDs.Size(); return S_OK; } Z7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) { if (index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; const UInt64 id = _fileInfoPopIDs[index]; for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPropMap); i++) { const CPropMap &pr = kPropMap[i]; if (pr.FilePropID == id) { *propID = pr.StatPropID; *varType = pr.vt; /* const CStatProp &st = pr.StatProp; *propID = st.PropID; *varType = st.vt; */ /* if (st.lpwstrName) *name = ::SysAllocString(st.lpwstrName); else */ *name = NULL; return S_OK; } } return E_INVALIDARG; } }} tmp41wklro_/CPP/7zip/Archive/7z/7zProperties.h0000444000175000001440000000063214410777020022166 0ustar nabijaczleweliusers// 7zProperties.h #ifndef ZIP7_INC_7Z_PROPERTIES_H #define ZIP7_INC_7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { // #define Z7_7Z_SHOW_PACK_STREAMS_SIZES // for debug #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; #endif }} #endif tmp41wklro_/CPP/7zip/Archive/7z/7zRegister.cpp0000444000175000001440000000114714277072720022161 0ustar nabijaczleweliusers// 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" namespace NArchive { namespace N7z { static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; REGISTER_ARC_IO_DECREMENT_SIG( "7z", "7z", NULL, 7, k_Signature_Dec, 0, NArcInfoFlags::kFindSignature | NArcInfoFlags::kCTime | NArcInfoFlags::kATime | NArcInfoFlags::kMTime | NArcInfoFlags::kMTime_Default , TIME_PREC_TO_ARC_FLAGS_MASK(NFileTimeType::kWindows) | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(NFileTimeType::kWindows) , NULL) }} tmp41wklro_/CPP/7zip/Archive/7z/7zSpecStream.cpp0000444000175000001440000000156714410751740022444 0ustar nabijaczleweliusers// 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" /* Z7_COM7F_IMF(CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize; const HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return result; } Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)) { if (!_getSubStreamSize) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } Z7_COM7F_IMF(CSequentialInStreamSizeCount2::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)) { if (!_compressGetSubStreamSize) return E_NOTIMPL; return _compressGetSubStreamSize->GetNextInSubStream(streamIndexRes, stream); } */ tmp41wklro_/CPP/7zip/Archive/7z/7zSpecStream.h0000444000175000001440000000267114410751740022106 0ustar nabijaczleweliusers// 7zSpecStream.h #ifndef ZIP7_INC_7Z_SPEC_STREAM_H #define ZIP7_INC_7Z_SPEC_STREAM_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" /* #define Z7_COM_QI_ENTRY_AG_2(i, sub0, sub) else if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ { i *ti = this; *outObject = ti; } } class CSequentialInStreamSizeCount2 Z7_final: public ISequentialInStream, public ICompressGetSubStreamSize, public ICompressInSubStreams, public CMyUnknownImp { Z7_COM_QI_BEGIN2(ISequentialInStream) Z7_COM_QI_ENTRY(ICompressGetSubStreamSize) Z7_COM_QI_ENTRY_AG_2(ISequentialInStream, _stream, _compressGetSubStreamSize) Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ISequentialInStream) Z7_IFACE_COM7_IMP(ICompressGetSubStreamSize) Z7_IFACE_COM7_IMP(ICompressInSubStreams) CMyComPtr _stream; CMyComPtr _getSubStreamSize; CMyComPtr _compressGetSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _size = 0; _getSubStreamSize.Release(); _compressGetSubStreamSize.Release(); _stream = stream; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _stream.QueryInterface(IID_ICompressInSubStreams, &_compressGetSubStreamSize); } UInt64 GetSize() const { return _size; } }; */ #endif tmp41wklro_/CPP/7zip/Archive/7z/7zUpdate.cpp0000444000175000001440000024601514634462720021624 0ustar nabijaczleweliusers// 7zUpdate.cpp #include "StdAfx.h" #include "../../../../C/CpuArch.h" #include "../../../Common/MyLinux.h" #include "../../../Common/StringToInt.h" #include "../../../Common/Wildcard.h" #include "../../Common/CreateCoder.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zDecode.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { #define k_X86 k_BCJ struct CFilterMode { UInt32 Id; UInt32 Delta; // required File Size alignment, if Id is not k_Delta. // (Delta == 0) means unknown alignment UInt32 Offset; // for k_ARM64 / k_RISCV // UInt32 AlignSizeOpt; // for k_ARM64 CFilterMode(): Id(0), Delta(0), Offset(0) // , AlignSizeOpt(0) {} void ClearFilterMode() { Id = 0; Delta = 0; Offset = 0; // AlignSizeOpt = 0; } // it sets Delta as Align value, if Id is exe filter // in another cases it sets Delta = 0, that void SetDelta() { if (Id == k_IA64) Delta = 16; else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) Delta = 4; else if (Id == k_ARMT || Id == k_RISCV) Delta = 2; else if (Id == k_BCJ || Id == k_BCJ2) Delta = 1; // do we need it? else Delta = 0; } }; /* ---------- PE ---------- */ #define MZ_SIG 0x5A4D #define PE_SIG 0x00004550 #define PE_OptHeader_Magic_32 0x10B #define PE_OptHeader_Magic_64 0x20B // #define PE_SectHeaderSize 40 // #define PE_SECT_EXECUTE 0x20000000 static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) { if (size < 512 || GetUi16(buf) != MZ_SIG) return 0; const Byte *p; UInt32 peOffset, optHeaderSize, filterId; peOffset = GetUi32(buf + 0x3C); if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0) return 0; p = buf + peOffset; if (GetUi32(p) != PE_SIG) return 0; p += 4; const unsigned machine = GetUi16(p); switch (machine) { case 0x014C: case 0x8664: filterId = k_X86; break; case 0xAA64: filterId = k_ARM64; break; /* IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2). */ case 0x01C0: // WinCE old case 0x01C2: filterId = k_ARM; break; // WinCE new case 0x01C4: filterId = k_ARMT; break; // WinRT case 0x5032: // RISCV32 case 0x5064: // RISCV64 // case 0x5128: // RISCV128 filterId = k_RISCV; break; case 0x0200: filterId = k_IA64; break; default: return 0; } const UInt32 numSections = GetUi16(p + 2); optHeaderSize = GetUi16(p + 16); if (optHeaderSize > (1 << 10)) return 0; p += 20; /* headerSize */ switch (GetUi16(p)) { case PE_OptHeader_Magic_32: case PE_OptHeader_Magic_64: break; default: return 0; } // Windows exe file sizes are not aligned for 4 KiB. // So we can't use (CFilterMode::Offset != 0) in solid archives. // So we just don't set Offset here. #define NUM_SCAN_SECTIONS_MAX (1 << 6) // #define EXE_SECTION_OFFSET_MAX (1 << 27) // #define EXE_SECTION_SIZE_MIN (1 << 8) // #define EXE_SECTION_SIZE_MAX (1 << 27) #define PE_SectHeaderSize 40 // #define PE_SECT_EXECUTE 0x20000000 /* if (numSections > NUM_SCAN_SECTIONS_MAX) return 0; */ if ((size_t)(p - buf) + optHeaderSize <= size) { p += optHeaderSize; /* // UInt32 numExeSections = 0; // bool execute_finded = false; // UInt32 sect_va = 0; // UInt32 sect_size = 0; // UInt32 sect_offset = 0; */ if (numSections <= NUM_SCAN_SECTIONS_MAX) if (machine == 0x8664) for (UInt32 i = 0; i < numSections ; i++, p += PE_SectHeaderSize) { // UInt32 characts, rawSize, offset; if ((UInt32)(p - buf) + PE_SectHeaderSize > size) { // return 0; break; } if (memcmp(p, ".a64xrm", 8) == 0) { // ARM64EC filterId = k_ARM64; break; } /* rawSize = GetUi32(p + 16); offset = GetUi32(p + 20); characts = GetUi32(p + 36); if (rawSize >= EXE_SECTION_SIZE_MIN && rawSize <= EXE_SECTION_SIZE_MAX && offset <= EXE_SECTION_OFFSET_MAX && // offset < limit && offset > 0) { if ((characts & PE_SECT_EXECUTE) != 0) { // execute_finded = true; // sect_va = GetUi32(p + 12); // sect_size = rawSize; // sect_offset = offset; break; } } */ } } /* filterMode->Offset = 0; if (filterId == k_ARM64) { // filterMode->AlignSizeOpt = (1 << 12); // const UInt32 offs = (sect_va - sect_offset) & 0xFFF; // if (offs != 0) // filterMode->Offset = offs; // change it } */ filterMode->Id = filterId; return 1; } /* Filters don't improve the compression ratio for relocatable object files (".o"). But we can get compression ratio gain, if we compress object files and executables in same solid block. So we use filters for relocatable object files (".o"): */ // #define Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ /* ---------- ELF ---------- */ #define ELF_SIG 0x464C457F #define ELF_CLASS_32 1 #define ELF_CLASS_64 2 #define ELF_DATA_2LSB 1 #define ELF_DATA_2MSB 2 static UInt16 Get16(const Byte *p, BoolInt be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); } static UInt32 Get32(const Byte *p, BoolInt be) { if (be) return GetBe32(p); return GetUi32(p); } // static UInt64 Get64(const Byte *p, BoolInt be) { if (be) return GetBe64(p); return GetUi64(p); } static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) { BoolInt /* is32, */ be; UInt32 filterId; if (size < 512 || buf[6] != 1) /* ver */ return 0; if (GetUi32(buf) != ELF_SIG) return 0; switch (buf[4]) { case ELF_CLASS_32: /* is32 = True; */ break; case ELF_CLASS_64: /* is32 = False; */ break; default: return 0; } switch (buf[5]) { case ELF_DATA_2LSB: be = False; break; case ELF_DATA_2MSB: be = True; break; default: return 0; } #ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ #define ELF_ET_REL 1 if (Get16(buf + 0x10, be) == ELF_ET_REL) return 0; #endif switch (Get16(buf + 0x12, be)) { case 3: case 6: case 62: filterId = k_X86; break; case 2: case 18: case 43: filterId = k_SPARC; break; case 20: case 21: if (!be) return 0; filterId = k_PPC; break; case 40: if (be) return 0; filterId = k_ARM; break; case 183: if (be) return 0; filterId = k_ARM64; break; case 243: if (be) return 0; filterId = k_RISCV; break; /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. So we don't use IA-64 filter for IA-64 ELF */ // case 50: if ( be) return 0; filterId = k_IA64; break; default: return 0; } filterMode->Id = filterId; return 1; } /* ---------- Mach-O ---------- */ #define MACH_SIG_BE_32 0xCEFAEDFE #define MACH_SIG_BE_64 0xCFFAEDFE #define MACH_SIG_LE_32 0xFEEDFACE #define MACH_SIG_LE_64 0xFEEDFACF #define MACH_ARCH_ABI64 (1 << 24) #define MACH_MACHINE_386 7 #define MACH_MACHINE_ARM 12 #define MACH_MACHINE_SPARC 14 #define MACH_MACHINE_PPC 18 #define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) #define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) #define MACH_MACHINE_ARM64 (MACH_ARCH_ABI64 | MACH_MACHINE_ARM) static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) { UInt32 filterId, numCommands, commandsSize; if (size < 512) return 0; BoolInt /* mode64, */ be; switch (GetUi32(buf)) { case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break; case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break; case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break; case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break; default: return 0; } #ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ #define MACH_TYPE_OBJECT 1 if (Get32(buf + 0xC, be) == MACH_TYPE_OBJECT) return 0; #endif switch (Get32(buf + 4, be)) { case MACH_MACHINE_386: case MACH_MACHINE_AMD64: filterId = k_X86; break; case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break; case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break; case MACH_MACHINE_PPC: case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break; case MACH_MACHINE_ARM64: if ( be) return 0; filterId = k_ARM64; break; default: return 0; } numCommands = Get32(buf + 0x10, be); commandsSize = Get32(buf + 0x14, be); if (commandsSize > (1 << 24) || numCommands > (1 << 18)) return 0; filterMode->Id = filterId; return 1; } /* ---------- WAV ---------- */ #define WAV_SUBCHUNK_fmt 0x20746D66 #define WAV_SUBCHUNK_data 0x61746164 #define RIFF_SIG 0x46464952 static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) { UInt32 subChunkSize, pos; if (size < 0x2C) return False; if (GetUi32(buf + 0) != RIFF_SIG || GetUi32(buf + 8) != 0x45564157 || // WAVE GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt) return False; subChunkSize = GetUi32(buf + 0x10); /* [0x14 = format] = 1 (PCM) */ if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1) return False; const unsigned numChannels = GetUi16(buf + 0x16); const unsigned bitsPerSample = GetUi16(buf + 0x22); if ((bitsPerSample & 0x7) != 0) return False; const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3); if (delta == 0 || delta > 256) return False; pos = 0x14 + subChunkSize; const int kNumSubChunksTests = 10; // Do we need to scan more than 3 sub-chunks? for (int i = 0; i < kNumSubChunksTests; i++) { if (pos + 8 > size) return False; subChunkSize = GetUi32(buf + pos + 4); if (GetUi32(buf + pos) == WAV_SUBCHUNK_data) { filterMode->Id = k_Delta; filterMode->Delta = delta; return True; } if (subChunkSize > (1 << 16)) return False; pos += subChunkSize + 8; } return False; } /* filterMode->Delta will be set as: = delta value : [1, 256] : for k_Delta = 0 for another filters (branch filters) */ static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) { filterMode->ClearFilterMode(); if (Parse_EXE(buf, size, filterMode)) return True; if (Parse_ELF(buf, size, filterMode)) return True; if (Parse_MACH(buf, size, filterMode)) return True; return Parse_WAV(buf, size, filterMode); } struct CFilterMode2: public CFilterMode { bool Encrypted; unsigned GroupIndex; CFilterMode2(): Encrypted(false) {} int Compare(const CFilterMode2 &m) const { if (!Encrypted) { if (m.Encrypted) return -1; } else if (!m.Encrypted) return 1; const UInt32 id1 = Id; const UInt32 id2 = m.Id; /* // we can change the order to place k_ARM64 files close to another exe files if (id1 <= k_SPARC && id2 <= k_SPARC) { #define k_ARM64_FOR_SORT 0x3030901 if (id1 == k_ARM64) id1 = k_ARM64_FOR_SORT; if (id2 == k_ARM64) id2 = k_ARM64_FOR_SORT; } */ if (id1 < id2) return -1; if (id1 > id2) return 1; if (Delta < m.Delta) return -1; if (Delta > m.Delta) return 1; if (Offset < m.Offset) return -1; if (Offset > m.Offset) return 1; /* we don't go here, because GetGroup() and operator ==(const CFilterMode2 &m) add only unique CFilterMode2:: { Id, Delta, Offset, Encrypted } items. */ /* if (GroupIndex < m.GroupIndex) return -1; if (GroupIndex > m.GroupIndex) return 1; */ return 0; } bool operator ==(const CFilterMode2 &m) const { return Id == m.Id && Delta == m.Delta && Offset == m.Offset && Encrypted == m.Encrypted; } }; static unsigned GetGroup(CRecordVector &filters, const CFilterMode2 &m) { unsigned i; for (i = 0; i < filters.Size(); i++) { const CFilterMode2 &m2 = filters[i]; if (m == m2) return i; /* if (m.Encrypted != m2.Encrypted) { if (!m.Encrypted) break; continue; } if (m.Id < m2.Id) break; if (m.Id != m2.Id) continue; if (m.Delta < m2.Delta) break; if (m.Delta != m2.Delta) continue; */ } // filters.Insert(i, m); // return i; return filters.Add(m); } static inline bool Is86Filter(CMethodId m) { return (m == k_BCJ || m == k_BCJ2); } static inline bool IsExeFilter(CMethodId m) { switch (m) { case k_ARM64: case k_RISCV: case k_BCJ: case k_BCJ2: case k_ARM: case k_ARMT: case k_PPC: case k_SPARC: case k_IA64: return true; default: break; } return false; } static unsigned Get_FilterGroup_for_Folder( CRecordVector &filters, const CFolderEx &f, bool extractFilter) { CFilterMode2 m; // m.Id = 0; // m.Delta = 0; // m.Offset = 0; m.Encrypted = f.IsEncrypted(); if (extractFilter) { const CCoderInfo &coder = f.Coders[f.UnpackCoder]; if (coder.MethodID == k_Delta) { if (coder.Props.Size() == 1) { m.Delta = (unsigned)coder.Props[0] + 1; m.Id = k_Delta; } } else if (IsExeFilter(coder.MethodID)) { m.Id = (UInt32)coder.MethodID; if (m.Id == k_BCJ2) m.Id = k_BCJ; m.SetDelta(); if (m.Id == k_ARM64 || m.Id == k_RISCV) if (coder.Props.Size() == 4) m.Offset = GetUi32(coder.Props); } } return GetGroup(filters, m); } static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(InStream_SeekSet(inStream, position)) CMyComPtr2_Create streamSpec; streamSpec->SetStream(inStream); streamSpec->Init(size); CMyComPtr2_Create copyCoder; RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress)) return (copyCoder->TotalSize == size ? S_OK : E_FAIL); } /* unsigned CUpdateItem::GetExtensionPos() const { int slashPos = Name.ReverseFind_PathSepar(); int dotPos = Name.ReverseFind_Dot(); if (dotPos <= slashPos) return Name.Len(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Ptr(GetExtensionPos()); } */ #define RINOZ(x) { const int _t_ = (x); if (_t_ != 0) return _t_; } #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) /* static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ_COMP(c1, c2); for (size_t i = 0; i < c1; i++) RINOZ_COMP(a1[i], a2[i]); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ_COMP(c1.NumInStreams, c2.NumInStreams); RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams); RINOZ_COMP(c1.MethodID, c2.MethodID); return CompareBuffers(c1.Props, c2.Props); } static int CompareBonds(const CBond &b1, const CBond &b2) { RINOZ_COMP(b1.InIndex, b2.InIndex); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ_COMP(s1, s2); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.Bonds.Size(); s2 = f2.Bonds.Size(); RINOZ_COMP(s1, s2); for (i = 0; i < s1; i++) RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i])); return 0; } */ /* static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return CompareFileNames(f1.Name, f2.Name); } */ struct CFolderRepack { unsigned FolderIndex; CNum NumCopyFiles; }; /* static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *) { int i1 = p1->FolderIndex; int i2 = p2->FolderIndex; // In that version we don't want to parse folders here, so we don't compare folders // probably it must be improved in future // const CDbEx &db = *(const CDbEx *)param; // RINOZ(CompareFolders( // db.Folders[i1], // db.Folders[i2])); return MyCompare(i1, i2); // RINOZ_COMP( // db.NumUnpackStreamsVector[i1], // db.NumUnpackStreamsVector[i2]); // if (db.NumUnpackStreamsVector[i1] == 0) // return 0; // return CompareFiles( // db.Files[db.FolderStartFileIndex[i1]], // db.Files[db.FolderStartFileIndex[i2]]); } */ /* we sort empty files and dirs in such order: - Dir.NonAnti (name sorted) - File.NonAnti (name sorted) - File.Anti (name sorted) - Dir.Anti (reverse name sorted) */ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param) { const CObjectVector &updateItems = *(const CObjectVector *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; // NonAnti < Anti if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); if (u1.IsDir != u2.IsDir) { // Dir.NonAnti < File < Dir.Anti if (u1.IsDir) return (u1.IsAnti ? 1 : -1); return (u2.IsAnti ? -1 : 1); } int n = CompareFileNames(u1.Name, u2.Name); return (u1.IsDir && u1.IsAnti) ? -n : n; } static const char *g_Exts = " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf" " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa" " h hpp hxx c cpp cxx m mm go swift" " rc java cs rs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm s" " sql manifest dep" " mak clw csproj vcproj sln dsp dsw" " class" " bat cmd bash sh" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so" " pdb pch idb ncb opt"; static unsigned GetExtIndex(const char *ext) { unsigned extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; unsigned pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; unsigned ExtensionPos; unsigned NamePos; unsigned ExtensionIndex; CRefItem() {} CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { const int slashPos = ui.Name.ReverseFind_PathSepar(); NamePos = (unsigned)(slashPos + 1); const int dotPos = ui.Name.ReverseFind_Dot(); if (dotPos <= slashPos) ExtensionPos = ui.Name.Len(); else { ExtensionPos = (unsigned)(dotPos + 1); if (ExtensionPos != ui.Name.Len()) { AString s; for (unsigned pos = ExtensionPos;; pos++) { const wchar_t c = ui.Name[pos]; if (c >= 0x80) break; if (c == 0) { ExtensionIndex = GetExtIndex(s); break; } s.Add_Char((char)MyCharLower_Ascii((char)c)); } } } } } }; struct CSortParam { // const CObjectVector *TreeFolders; bool SortByType; }; /* we sort files in such order: - Dir.NonAnti (name sorted) - alt streams - Dirs - Dir.Anti (reverse name sorted) */ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; /* if (u1.IsAltStream != u2.IsAltStream) return u1.IsAltStream ? 1 : -1; */ // Actually there are no dirs that time. They were stored in other steps // So that code is unused? if (u1.IsDir != u2.IsDir) return u1.IsDir ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = CompareFileNames(u1.Name, u2.Name); return -n; } // bool sortByType = *(bool *)param; const CSortParam *sortParam = (const CSortParam *)param; const bool sortByType = sortParam->SortByType; if (sortByType) { RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex) RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))) RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))) if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime) RINOZ_COMP(u1.Size, u2.Size) } /* int par1 = a1.UpdateItem->ParentFolderIndex; int par2 = a2.UpdateItem->ParentFolderIndex; const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1]; const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2]; int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd; int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd; if (b1 < b2) { if (e1 <= b2) return -1; // p2 in p1 int par = par2; for (;;) { const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; par = tf.Parent; if (par == par1) { RINOZ(CompareFileNames(u1.Name, tf.Name)); break; } } } else if (b2 < b1) { if (e2 <= b1) return 1; // p1 in p2 int par = par1; for (;;) { const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; par = tf.Parent; if (par == par2) { RINOZ(CompareFileNames(tf.Name, u2.Name)); break; } } } */ // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); RINOK(CompareFileNames(u1.Name, u2.Name)) RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient) RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive) return 0; } struct CSolidGroup { CRecordVector Indices; CRecordVector folderRefs; }; static const char * const g_Exe_Exts[] = { "dll" , "exe" , "ocx" , "sfx" , "sys" }; static const char * const g_ExeUnix_Exts[] = { "so" , "dylib" }; static bool IsExt_Exe(const wchar_t *ext) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exe_Exts); i++) if (StringsAreEqualNoCase_Ascii(ext, g_Exe_Exts[i])) return true; return false; } /* static bool IsExt_ExeUnix(const wchar_t *ext) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++) if (StringsAreEqualNoCase_Ascii(ext, g_ExeUnix_Exts[i])) return true; return false; } */ // we try to find "so" extension in such name: libstdc++.so.6.0.29 static bool IsExt_ExeUnix_NumericAllowed(const UString &path) { unsigned pos = path.Len(); unsigned dotPos = pos; for (;;) { if (pos == 0) return false; const wchar_t c = path[--pos]; if (IS_PATH_SEPAR(c)) return false; if (c == '.') { const unsigned num = (dotPos - pos) - 1; if (num < 1) return false; const wchar_t *cur = path.Ptr(pos + 1); for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++) { const char *ext = g_ExeUnix_Exts[i]; if (num == MyStringLen(ext)) if (IsString1PrefixedByString2_NoCase_Ascii(cur, ext)) return true; } const wchar_t *end; ConvertStringToUInt32(cur, &end); if ((size_t)(end - cur) != num) return false; dotPos = pos; } } } struct CAnalysis { CMyComPtr Callback; CByteBuffer Buffer; bool ParseWav; bool ParseExe; bool ParseExeUnix; bool ParseNoExt; bool ParseAll; /* bool Need_ATime; bool ATime_Defined; FILETIME ATime; */ CAnalysis(): ParseWav(false), ParseExe(false), ParseExeUnix(false), ParseNoExt(false), ParseAll(false) /* , Need_ATime(false) , ATime_Defined(false) */ {} HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode); }; static const size_t kAnalysisBufSize = 1 << 14; HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode) { filterMode.Id = 0; filterMode.Delta = 0; filterMode.Offset = 0; CFilterMode filterModeTemp = filterMode; const int slashPos = ui.Name.ReverseFind_PathSepar(); const int dotPos = ui.Name.ReverseFind_Dot(); // if (dotPos > slashPos) { bool needReadFile = ParseAll; /* if (Callback) is not supported by client, we still try to use file name extension to detect executable file */ bool probablyIsSameIsa = false; if (!needReadFile || !Callback) { const wchar_t *ext = NULL; if (dotPos > slashPos) ext = ui.Name.Ptr((unsigned)(dotPos + 1)); // 7-zip stores posix attributes in high 16 bits and sets (0x8000) flag if (ui.Attrib & 0x8000) { const unsigned st_mode = ui.Attrib >> 16; /* note: executable ".so" can be without execute permission, and symbolic link to such ".so" file is possible */ // st_mode = 00111; // for debug /* in Linux we expect such permissions: 0755 : for most executables 0644 : for some ".so" files 0777 : in WSL for all files. We can try to exclude some such 0777 cases from analysis, if there is non-executable extension. */ if ((st_mode & ( MY_LIN_S_IXUSR | MY_LIN_S_IXGRP | MY_LIN_S_IXOTH)) != 0 && MY_LIN_S_ISREG(st_mode) && (ui.Size >= (1u << 11))) { #ifndef _WIN32 probablyIsSameIsa = true; #endif needReadFile = true; } } if (!needReadFile) { if (!ext) needReadFile = ParseNoExt; else { bool isUnixExt = false; if (ParseExeUnix) isUnixExt = IsExt_ExeUnix_NumericAllowed(ui.Name); if (isUnixExt) { needReadFile = true; #ifndef _WIN32 probablyIsSameIsa = true; #endif } else if (IsExt_Exe(ext)) { needReadFile = ParseExe; #ifdef _WIN32 probablyIsSameIsa = true; #endif } else if (StringsAreEqualNoCase_Ascii(ext, "wav")) { if (!needReadFile) needReadFile = ParseWav; } } } } if (needReadFile) { BoolInt parseRes = false; if (Callback) { if (Buffer.Size() != kAnalysisBufSize) Buffer.Alloc(kAnalysisBufSize); CMyComPtr stream; HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); if (result == S_OK && stream) { /* if (Need_ATime) { // access time could be changed in analysis pass CMyComPtr getProps; stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); if (getProps) if (getProps->GetProps(NULL, NULL, &ATime, NULL, NULL) == S_OK) ATime_Defined = true; } */ size_t size = kAnalysisBufSize; result = ReadStream(stream, Buffer, &size); stream.Release(); // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK)); if (result == S_OK) { parseRes = ParseFile(Buffer, size, &filterModeTemp); } } } // Callback else if (probablyIsSameIsa) { #ifdef MY_CPU_X86_OR_AMD64 filterModeTemp.Id = k_X86; #endif #ifdef MY_CPU_ARM64 filterModeTemp.Id = k_ARM64; #endif #ifdef MY_CPU_RISCV filterModeTemp.Id = k_RISCV; #endif #ifdef MY_CPU_SPARC filterModeTemp.Id = k_SPARC; #endif parseRes = true; } if (parseRes && filterModeTemp.Id != k_Delta && filterModeTemp.Delta == 0) { /* ParseFile() sets (filterModeTemp.Delta == 0) for all methods except of k_Delta. */ // it's not k_Delta // So we call SetDelta() to set Delta filterModeTemp.SetDelta(); if (filterModeTemp.Delta > 1) { /* If file Size is not aligned, then branch filter will not work for next file in solid block. Maybe we should allow filter for non-aligned-size file in non-solid archives ? */ if (ui.Size % filterModeTemp.Delta != 0) parseRes = false; // windows exe files are not aligned for 4 KiB. /* else if (filterModeTemp.Id == k_ARM64 && filterModeTemp.Offset != 0) { if (ui.Size % (1 << 12) != 0) { // If Size is not aligned for 4 KiB, then Offset will not work for next file in solid block. // so we place such file in group with (Offset==0). filterModeTemp.Offset = 0; } } */ } } if (!parseRes) filterModeTemp.ClearFilterMode(); } } filterMode = filterModeTemp; return S_OK; } static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m) { m.Id = methodID; m.NumStreams = numStreams; } // we add bond for mode.Methods[0] that is filter static HRESULT AddBondForFilter(CCompressionMethodMode &mode) { for (unsigned c = 1; c < mode.Methods.Size(); c++) { if (!mode.IsThereBond_to_Coder(c)) { CBond2 bond; bond.OutCoder = 0; bond.OutStream = 0; bond.InCoder = c; mode.Bonds.Add(bond); return S_OK; } } return E_INVALIDARG; } /* static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode) { if (!mode.Bonds.IsEmpty()) return AddBondForFilter(mode); return S_OK; } */ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) { // mode.Methods[0] must be k_BCJ2 method ! // mode.Methods[1] : we expect that there is at least one method after BCJ2 CMethodFull m; GetMethodFull(k_LZMA, 1, m); m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20); m.AddProp32(NCoderPropID::kNumFastBytes, 128); m.AddProp32(NCoderPropID::kNumThreads, 1); m.AddProp32(NCoderPropID::kLitPosBits, 2); m.AddProp32(NCoderPropID::kLitContextBits, 0); // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); const unsigned methodIndex = mode.Methods.Size(); if (mode.Bonds.IsEmpty()) { for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++) { CBond2 bond; bond.OutCoder = i; bond.OutStream = 0; bond.InCoder = i + 1; mode.Bonds.Add(bond); } } mode.Methods.Add(m); mode.Methods.Add(m); RINOK(AddBondForFilter(mode)) CBond2 bond; bond.OutCoder = 0; // index of BCJ2 coder bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); return S_OK; } static HRESULT MakeExeMethod(CCompressionMethodMode &mode, const CFilterMode &filterMode, const bool bcj2_IsAllowed, const CUIntVector &disabledFilterIDs) { if (mode.Filter_was_Inserted) { // filter was inserted, but bond for that filter was not added still. const CMethodFull &m = mode.Methods[0]; if (m.Id == k_BCJ2) return AddBcj2Methods(mode); if (!m.IsSimpleCoder()) return E_NOTIMPL; if (mode.Bonds.IsEmpty()) return S_OK; return AddBondForFilter(mode); } if (filterMode.Id == 0) return S_OK; unsigned nextCoder; const bool useBcj2 = bcj2_IsAllowed && Is86Filter(filterMode.Id) && disabledFilterIDs.FindInSorted(k_BCJ2) < 0; if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0) { // required filter is disabled, // but we still can use information about data alignment. #if 0 // 1 for debug // we can return here, if we want default lzma properties return S_OK; #else // we will try to change lzma/lzma2 properties nextCoder = 0; if (!mode.Bonds.IsEmpty()) for (unsigned c = 0;; c++) { if (c == mode.Methods.Size()) return S_OK; if (!mode.IsThereBond_to_Coder(c)) { nextCoder = c; break; } } #endif } else { // we insert new filter method: CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item { // we move all coder indexes in bonds up for 1 position: FOR_VECTOR (k, mode.Bonds) { CBond2 &bond = mode.Bonds[k]; bond.InCoder++; bond.OutCoder++; } } if (useBcj2) { GetMethodFull(k_BCJ2, 4, m); return AddBcj2Methods(mode); } GetMethodFull(filterMode.Id, 1, m); if (filterMode.Id == k_Delta) m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); else if (filterMode.Id == k_ARM64 || filterMode.Id == k_RISCV) { // if (filterMode.Offset != 0) m.AddProp32( NCoderPropID::kDefaultProp, // NCoderPropID::kBranchOffset, filterMode.Offset); } nextCoder = 1; if (!mode.Bonds.IsEmpty()) { RINOK(AddBondForFilter(mode)) nextCoder = mode.Bonds.Back().InCoder; } } if (nextCoder >= mode.Methods.Size()) { // we don't expect that case, if there was non-filter method. // but we return S_OK to support filter-only case. return S_OK; } int alignBits = -1; { const UInt32 delta = filterMode.Delta; if (delta == 0 || delta > 16) { // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); } else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; // else alignBits = 0; /* alignBits=0 is default mode for lzma/lzma2. So we don't set alignBits=0 here. */ } if (alignBits <= 0) return S_OK; // (alignBits > 0) CMethodFull &nextMethod = mode.Methods[nextCoder]; if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) if (!nextMethod.Are_Lzma_Model_Props_Defined()) { if (alignBits > 2 || filterMode.Id == k_Delta) nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u; nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); } return S_OK; } static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2) { file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined; file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; // file2.IsAux = false; file2.StartPosDefined = false; // file2.StartPos = 0; } static void UpdateItem_To_FileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { UpdateItem_To_FileItem2(ui, file2); file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); // file.IsAltStream = ui.IsAltStream; } Z7_CLASS_IMP_COM_2( CRepackInStreamWithSizes , ISequentialInStream , ICompressGetSubStreamSize ) CMyComPtr _stream; UInt64 _size; const CBoolVector *_extractStatuses; UInt32 _startIndex; public: const CDbEx *_db; void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses) { _startIndex = startIndex; _extractStatuses = extractStatuses; _size = 0; _stream = stream; } UInt64 GetSize() const { return _size; } }; Z7_COM7F_IMF(CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize; const HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return result; } Z7_COM7F_IMF(CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)) { *value = 0; if (subStream >= _extractStatuses->Size()) return S_FALSE; // E_FAIL; const unsigned index = (unsigned)subStream; if ((*_extractStatuses)[index]) { const CFileItem &fi = _db->Files[_startIndex + index]; if (fi.HasStream) *value = fi.Size; } return S_OK; } class CRepackStreamBase { protected: bool _needWrite; bool _fileIsOpen; bool _calcCrc; UInt32 _crc; UInt64 _rem; const CBoolVector *_extractStatuses; UInt32 _startIndex; unsigned _currentIndex; HRESULT OpenFile(); HRESULT CloseFile(); HRESULT ProcessEmptyFiles(); public: const CDbEx *_db; CMyComPtr _opCallback; CMyComPtr _extractCallback; HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses); HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } }; HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses) { _startIndex = startIndex; _extractStatuses = extractStatuses; _currentIndex = 0; _fileIsOpen = false; return ProcessEmptyFiles(); } HRESULT CRepackStreamBase::OpenFile() { UInt32 arcIndex = _startIndex + _currentIndex; const CFileItem &fi = _db->Files[arcIndex]; _needWrite = (*_extractStatuses)[_currentIndex]; if (_opCallback) { RINOK(_opCallback->ReportOperation( NEventIndexType::kInArcIndex, arcIndex, _needWrite ? NUpdateNotifyOp::kRepack : NUpdateNotifyOp::kSkip)) } _crc = CRC_INIT_VAL; _calcCrc = (fi.CrcDefined && !fi.IsDir); _fileIsOpen = true; _rem = fi.Size; return S_OK; } const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002; HRESULT CRepackStreamBase::CloseFile() { UInt32 arcIndex = _startIndex + _currentIndex; const CFileItem &fi = _db->Files[arcIndex]; _fileIsOpen = false; _currentIndex++; if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) return S_OK; if (_extractCallback) { RINOK(_extractCallback->ReportExtractResult( NEventIndexType::kInArcIndex, arcIndex, NExtract::NOperationResult::kCRCError)) } // return S_FALSE; return k_My_HRESULT_CRC_ERROR; } HRESULT CRepackStreamBase::ProcessEmptyFiles() { while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) { RINOK(OpenFile()) RINOK(CloseFile()) } return S_OK; } #ifndef Z7_ST class CFolderOutStream2 Z7_final: public CRepackStreamBase, public ISequentialOutStream, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(ISequentialOutStream) public: CMyComPtr _stream; }; Z7_COM7F_IMF(CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_fileIsOpen) { UInt32 cur = (size < _rem ? size : (UInt32)_rem); HRESULT result = S_OK; if (_needWrite) result = _stream->Write(data, cur, &cur); if (_calcCrc) _crc = CrcUpdate(_crc, data, cur); if (processedSize) *processedSize += cur; data = (const Byte *)data + cur; size -= cur; _rem -= cur; if (_rem == 0) { RINOK(CloseFile()) RINOK(ProcessEmptyFiles()) } RINOK(result) if (cur == 0) break; continue; } RINOK(ProcessEmptyFiles()) if (_currentIndex == _extractStatuses->Size()) { // we don't support write cut here return E_FAIL; } RINOK(OpenFile()) } return S_OK; } #endif static const UInt32 kTempBufSize = 1 << 16; class CFolderInStream2 Z7_final: public CRepackStreamBase, public ISequentialInStream, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(ISequentialInStream) Byte *_buf; public: CMyComPtr _inStream; HRESULT Result; CFolderInStream2(): Result(S_OK) { _buf = new Byte[kTempBufSize]; } ~CFolderInStream2() { delete []_buf; } void Init() { Result = S_OK; } }; Z7_COM7F_IMF(CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_fileIsOpen) { UInt32 cur = (size < _rem ? size : (UInt32)_rem); void *buf; if (_needWrite) buf = data; else { buf = _buf; if (cur > kTempBufSize) cur = kTempBufSize; } const HRESULT result = _inStream->Read(buf, cur, &cur); _crc = CrcUpdate(_crc, buf, cur); _rem -= cur; if (_needWrite) { data = (Byte *)data + cur; size -= cur; if (processedSize) *processedSize += cur; } if (result != S_OK) Result = result; if (_rem == 0) { RINOK(CloseFile()) RINOK(ProcessEmptyFiles()) } RINOK(result) if (cur == 0) return E_FAIL; continue; } RINOK(ProcessEmptyFiles()) if (_currentIndex == _extractStatuses->Size()) { return S_OK; } RINOK(OpenFile()) } return S_OK; } class CThreadDecoder Z7_final #ifndef Z7_ST : public CVirtThread #endif { public: CDecoder Decoder; CThreadDecoder(bool multiThreadMixer): Decoder(multiThreadMixer) { #ifndef Z7_ST if (multiThreadMixer) { MtMode = false; NumThreads = 1; FosSpec = new CFolderOutStream2; Fos = FosSpec; Result = E_FAIL; } #endif // UnpackSize = 0; // send_UnpackSize = false; } #ifndef Z7_ST bool dataAfterEnd_Error; HRESULT Result; CMyComPtr InStream; CFolderOutStream2 *FosSpec; CMyComPtr Fos; UInt64 StartPos; const CFolders *Folders; unsigned FolderIndex; // bool send_UnpackSize; // UInt64 UnpackSize; #ifndef Z7_NO_CRYPTO CMyComPtr getTextPassword; #endif DECL_EXTERNAL_CODECS_LOC_VARS_DECL #ifndef Z7_ST bool MtMode; UInt32 NumThreads; #endif ~CThreadDecoder() Z7_DESTRUCTOR_override { /* WaitThreadFinish() will be called in ~CVirtThread(). But we need WaitThreadFinish() call before destructors of this class members. */ CVirtThread::WaitThreadFinish(); } private: virtual void Execute() Z7_override; #endif }; #ifndef Z7_ST void CThreadDecoder::Execute() { try { #ifndef Z7_NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; UString password; #endif dataAfterEnd_Error = false; Result = Decoder.Decode( EXTERNAL_CODECS_LOC_VARS InStream, StartPos, *Folders, FolderIndex, // send_UnpackSize ? &UnpackSize : NULL, NULL, // unpackSize : FULL unpack Fos, NULL, // compressProgress NULL // *inStreamMainRes , dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS #ifndef Z7_ST , MtMode, NumThreads, 0 // MemUsage #endif ); } catch(...) { Result = E_FAIL; } /* if (Result == S_OK) Result = FosSpec->CheckFinishedState(); */ FosSpec->_stream.Release(); } #endif #ifndef Z7_NO_CRYPTO Z7_CLASS_IMP_NOQIB_1( CCryptoGetTextPassword , ICryptoGetTextPassword ) public: UString Password; }; Z7_COM7F_IMF(CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)) { return StringToBstr(Password, password); } #endif static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2) { file = inDb.Files[index]; file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime); file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime); file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime); file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos); file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib); file2.IsAnti = inDb.IsItemAnti(index); // file2.IsAux = inDb.IsItemAux(index); } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CDbEx *db, CObjectVector &updateItems, // const CObjectVector &treeFolders, // const CUniqBlocks &secureBlocks, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; Z7_DECL_CMyComPtr_QI_FROM( IArchiveUpdateCallbackFile, opCallback, updateCallback) Z7_DECL_CMyComPtr_QI_FROM( IArchiveExtractCallbackMessage2, extractCallback, updateCallback) /* Z7_DECL_CMyComPtr_QI_FROM( IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback) */ // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); CMyComPtr v_StreamSetRestriction; { Z7_DECL_CMyComPtr_QI_FROM( IOutStream, outStream, seqOutStream) if (!outStream) return E_NOTIMPL; const UInt64 sfxBlockSize = (db && !options.RemoveSfxBlock) ? db->ArcInfo.StartPosition: 0; seqOutStream->QueryInterface(IID_IStreamSetRestriction, (void **)&v_StreamSetRestriction); if (v_StreamSetRestriction) { UInt64 offset = 0; RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &offset)) RINOK(v_StreamSetRestriction->SetRestriction( outStream ? offset + sfxBlockSize : 0, outStream ? offset + sfxBlockSize + k_StartHeadersRewriteSize : 0)) } outStream.Release(); if (sfxBlockSize != 0) { RINOK(WriteRange(inStream, seqOutStream, 0, sfxBlockSize, NULL)) } } CIntArr fileIndexToUpdateIndexMap; UInt64 complexity = 0; bool isThere_UnknownSize = false; UInt64 inSizeForReduce2 = 0; #ifndef Z7_NO_CRYPTO bool needEncryptedRepack = false; #endif CRecordVector filters; CObjectVector groups; #ifndef Z7_ST bool thereAreRepacks = false; #endif bool useFilters = options.UseFilters; if (useFilters) { const CCompressionMethodMode &method = *options.Method; FOR_VECTOR (i, method.Methods) { /* IsFilterMethod() knows only built-in codecs FIXME: we should check IsFilter status for external filters too */ if (IsFilterMethod(method.Methods[i].Id)) { useFilters = false; break; } } } if (db) { fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); unsigned i; for (i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap[i] = -1; for (i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[(unsigned)index] = (int)i; } for (i = 0; i < db->NumFolders; i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; const CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; UInt64 repackSize = 0; for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) { if (fi >= db->Files.Size()) return E_FAIL; const CFileItem &file = db->Files[fi]; if (file.HasStream) { indexInFolder++; const int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) { numCopyItems++; repackSize += file.Size; } } } if (numCopyItems == 0) continue; CFolderRepack rep; rep.FolderIndex = i; rep.NumCopyFiles = numCopyItems; CFolderEx f; db->ParseFolderEx(i, f); #ifndef Z7_NO_CRYPTO const bool isEncrypted = f.IsEncrypted(); #endif const bool needCopy = (numCopyItems == numUnpackStreams); const bool extractFilter = (useFilters || needCopy); const unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter); while (groupIndex >= groups.Size()) groups.AddNew(); groups[groupIndex].folderRefs.Add(rep); if (needCopy) complexity += db->GetFolderFullPackSize(i); else { #ifndef Z7_ST thereAreRepacks = true; #endif complexity += repackSize; if (inSizeForReduce2 < repackSize) inSizeForReduce2 = repackSize; #ifndef Z7_NO_CRYPTO if (isEncrypted) needEncryptedRepack = true; #endif } } } UInt64 inSizeForReduce = 0; { const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); FOR_VECTOR (i, updateItems) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.Size == (UInt64)(Int64)-1) isThere_UnknownSize = true; else { complexity += ui.Size; if (isSolid) inSizeForReduce += ui.Size; else if (inSizeForReduce < ui.Size) inSizeForReduce = ui.Size; } } } } if (isThere_UnknownSize) inSizeForReduce = (UInt64)(Int64)-1; else RINOK(updateCallback->SetTotal(complexity)) if (inSizeForReduce < inSizeForReduce2) inSizeForReduce = inSizeForReduce2; CMyComPtr2_Create lps; lps->Init(updateCallback, true); #ifndef Z7_ST CStreamBinder sb; /* if (options.MultiThreadMixer) { RINOK(sb.CreateEvents()); } */ #endif CThreadDecoder threadDecoder(options.MultiThreadMixer); #ifndef Z7_ST if (options.MultiThreadMixer && thereAreRepacks) { #ifdef Z7_EXTERNAL_CODECS threadDecoder._externalCodecs = _externalCodecs; #endif const WRes wres = threadDecoder.Create(); if (wres != 0) return HRESULT_FROM_WIN32(wres); } #endif { CAnalysis analysis; // analysis.Need_ATime = options.Need_ATime; int analysisLevel = options.AnalysisLevel; // (analysisLevel < 0) means default level (5) if (analysisLevel < 0) analysisLevel = 5; if (analysisLevel != 0) { analysis.Callback = opCallback; analysis.ParseWav = true; if (analysisLevel >= 5) { analysis.ParseExe = true; analysis.ParseExeUnix = true; // analysis.ParseNoExt = true; if (analysisLevel >= 7) { analysis.ParseNoExt = true; if (analysisLevel >= 9) analysis.ParseAll = true; } } } // ---------- Split files to groups ---------- const CCompressionMethodMode &method = *options.Method; FOR_VECTOR (i, updateItems) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData || !ui.HasStream()) continue; CFilterMode2 fm; if (useFilters) { // analysis.ATime_Defined = false; RINOK(analysis.GetFilterGroup(i, ui, fm)) /* if (analysis.ATime_Defined) { ui.ATime = FILETIME_To_UInt64(analysis.ATime); ui.ATime_WasReadByAnalysis = true; } */ } fm.Encrypted = method.PasswordIsDefined; const unsigned groupIndex = GetGroup(filters, fm); while (groupIndex >= groups.Size()) groups.AddNew(); groups[groupIndex].Indices.Add(i); } } #ifndef Z7_NO_CRYPTO CCryptoGetTextPassword *getPasswordSpec = NULL; CMyComPtr getTextPassword; if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; getTextPassword = getPasswordSpec; #ifndef Z7_ST threadDecoder.getTextPassword = getPasswordSpec; #endif if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; else { Z7_DECL_CMyComPtr_QI_FROM( ICryptoGetTextPassword, getDecoderPassword, updateCallback) if (!getDecoderPassword) return E_NOTIMPL; CMyComBSTR password; RINOK(getDecoderPassword->CryptoGetTextPassword(&password)) if (password) getPasswordSpec->Password = password; } } #endif // ---------- Compress ---------- COutArchive archive; CArchiveDatabaseOut newDatabase; RINOK(archive.Create_and_WriteStartPrefix(seqOutStream)) /* CIntVector treeFolderToArcIndex; treeFolderToArcIndex.Reserve(treeFolders.Size()); for (i = 0; i < treeFolders.Size(); i++) treeFolderToArcIndex.Add(-1); // ---------- Write Tree (only AUX dirs) ---------- for (i = 1; i < treeFolders.Size(); i++) { const CTreeFolder &treeFolder = treeFolders[i]; CFileItem file; CFileItem2 file2; file2.Init(); int secureID = 0; if (treeFolder.UpdateItemIndex < 0) { // we can store virtual dir item wuthout attrib, but we want all items have attrib. file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY); file2.IsAux = true; } else { const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex]; // if item is not dir, then it's parent for alt streams. // we will write such items later if (!ui.IsDir) continue; secureID = ui.SecureIndex; if (ui.NewProps) UpdateItem_To_FileItem(ui, file, file2); else GetFile(*db, ui.IndexInArchive, file, file2); } file.Size = 0; file.HasStream = false; file.IsDir = true; file.Parent = treeFolder.Parent; treeFolderToArcIndex[i] = newDatabase.Files.Size(); newDatabase.AddFile(file, file2, treeFolder.Name); if (totalSecureDataSize != 0) newDatabase.SecureIDs.Add(secureID); } */ { /* ---------- Write non-AUX dirs and Empty files ---------- */ CUIntVector emptyRefs; unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream) continue; /* if (ui.TreeFolderIndex >= 0) continue; */ emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; UString name; if (ui.NewProps) { UpdateItem_To_FileItem(ui, file, file2); file.CrcDefined = false; name = ui.Name; } else { GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); db->GetPath((unsigned)ui.IndexInArchive, name); } /* if (totalSecureDataSize != 0) newDatabase.SecureIDs.Add(ui.SecureIndex); file.Parent = ui.ParentFolderIndex; */ newDatabase.AddFile(file, file2, name); } } lps->ProgressOffset = 0; { // ---------- Sort Filters ---------- FOR_VECTOR (i, filters) { filters[i].GroupIndex = i; } filters.Sort2(); } for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++) { const CFilterMode2 &filterMode = filters[groupIndex]; CCompressionMethodMode method = *options.Method; { const HRESULT res = MakeExeMethod(method, filterMode, // bcj2_IsAllowed: #ifdef Z7_ST false #else options.MaxFilter && options.MultiThreadMixer #endif , options.DisabledFilterIDs); RINOK(res) } if (filterMode.Encrypted) { if (!method.PasswordIsDefined) { #ifndef Z7_NO_CRYPTO if (getPasswordSpec) method.Password = getPasswordSpec->Password; #endif method.PasswordIsDefined = true; } } else { method.PasswordIsDefined = false; method.Password.Empty(); } CEncoder encoder(method); // ---------- Repack and copy old solid blocks ---------- const CSolidGroup &group = groups[filterMode.GroupIndex]; FOR_VECTOR (folderRefIndex, group.folderRefs) { const CFolderRepack &rep = group.folderRefs[folderRefIndex]; const unsigned folderIndex = rep.FolderIndex; const CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; if (rep.NumCopyFiles == numUnpackStreams) { if (opCallback) { RINOK(opCallback->ReportOperation( NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdateNotifyOp::kReplicate)) // ---------- Copy old solid block ---------- { CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { if (db->Files[fi].HasStream) { indexInFolder++; RINOK(opCallback->ReportOperation( NEventIndexType::kInArcIndex, (UInt32)fi, NUpdateNotifyOp::kReplicate)) } } } } const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, lps)) lps->ProgressOffset += packSize; const unsigned folderIndex_New = newDatabase.Folders.Size(); CFolder &folder = newDatabase.Folders.AddNew(); // v23.01: we copy FolderCrc, if FolderCrc was used if (db->FolderCRCs.ValidAndDefined(folderIndex)) newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, db->FolderCRCs.Vals[folderIndex]); db->ParseFolderInfo(folderIndex, folder); const CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; FOR_VECTOR (j, folder.PackStreams) { newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; for (; indexStart < indexEnd; indexStart++) newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]); } else { // ---------- Repack old solid block ---------- CBoolVector extractStatuses; CNum indexInFolder = 0; if (opCallback) { RINOK(opCallback->ReportOperation( NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdateNotifyOp::kRepack)) } /* We could reduce data size of decoded folder, if we don't need to repack last files in folder. But the gain in speed is small in most cases. So we unpack full folder. */ UInt64 sizeToEncode = 0; /* UInt64 importantUnpackSize = 0; unsigned numImportantFiles = 0; UInt64 decodeSize = 0; */ for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { bool needExtract = false; const CFileItem &file = db->Files[fi]; if (file.HasStream) { indexInFolder++; const int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) needExtract = true; // decodeSize += file.Size; } extractStatuses.Add(needExtract); if (needExtract) { sizeToEncode += file.Size; /* numImportantFiles = extractStatuses.Size(); importantUnpackSize = decodeSize; */ } } // extractStatuses.DeleteFrom(numImportantFiles); unsigned startPackIndex = newDatabase.PackSizes.Size(); UInt64 curUnpackSize; { CMyComPtr sbInStream; CRepackStreamBase *repackBase; CFolderInStream2 *FosSpec2 = NULL; CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; { #ifndef Z7_ST if (options.MultiThreadMixer) { repackBase = threadDecoder.FosSpec; CMyComPtr sbOutStream; sb.CreateStreams2(sbInStream, sbOutStream); RINOK(sb.Create_ReInit()) threadDecoder.FosSpec->_stream = sbOutStream; threadDecoder.InStream = inStream; threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); threadDecoder.Folders = (const CFolders *)db; threadDecoder.FolderIndex = folderIndex; // threadDecoder.UnpackSize = importantUnpackSize; // threadDecoder.send_UnpackSize = true; } else #endif { FosSpec2 = new CFolderInStream2; FosSpec2->Init(); sbInStream = FosSpec2; repackBase = FosSpec2; #ifndef Z7_NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; UString password; #endif CMyComPtr decodedStream; bool dataAfterEnd_Error = false; const HRESULT res = threadDecoder.Decoder.Decode( EXTERNAL_CODECS_LOC_VARS inStream, db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);, *db, folderIndex, // &importantUnpackSize, // *unpackSize NULL, // *unpackSize : FULL unpack NULL, // *outStream NULL, // *compressProgress &decodedStream , dataAfterEnd_Error Z7_7Z_DECODER_CRYPRO_VARS #ifndef Z7_ST , false // mtMode , 1 // numThreads , 0 // memUsage #endif ); RINOK(res) if (!decodedStream) return E_FAIL; FosSpec2->_inStream = decodedStream; } repackBase->_db = db; repackBase->_opCallback = opCallback; repackBase->_extractCallback = extractCallback; UInt32 startIndex = db->FolderStartFileIndex[folderIndex]; RINOK(repackBase->Init(startIndex, &extractStatuses)) inStreamSizeCountSpec->_db = db; inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses); #ifndef Z7_ST if (options.MultiThreadMixer) { WRes wres = threadDecoder.Start(); if (wres != 0) return HRESULT_FROM_WIN32(wres); } #endif } // curUnpackSize = sizeToEncode; HRESULT encodeRes = encoder.Encode1( EXTERNAL_CODECS_LOC_VARS inStreamSizeCount, // NULL, &inSizeForReduce, sizeToEncode, // expectedDataSize newDatabase.Folders.AddNew(), // newDatabase.CoderUnpackSizes, curUnpackSize, archive.SeqStream, newDatabase.PackSizes, lps); if (encodeRes == k_My_HRESULT_CRC_ERROR) return E_FAIL; curUnpackSize = inStreamSizeCountSpec->GetSize(); if (encodeRes == S_OK) { encoder.Encode_Post(curUnpackSize, newDatabase.CoderUnpackSizes); } #ifndef Z7_ST if (options.MultiThreadMixer) { // 16.00: hang was fixed : for case if decoding was not finished. // We close CBinderInStream and it calls CStreamBinder::CloseRead() inStreamSizeCount.Release(); sbInStream.Release(); { const WRes wres = threadDecoder.WaitExecuteFinish(); if (wres != 0) return HRESULT_FROM_WIN32(wres); } const HRESULT decodeRes = threadDecoder.Result; // if (res == k_My_HRESULT_CRC_ERROR) if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error) { if (extractCallback) { RINOK(extractCallback->ReportExtractResult( NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex], // NEventIndexType::kBlockIndex, (UInt32)folderIndex, (decodeRes != S_OK ? NExtract::NOperationResult::kDataError : NExtract::NOperationResult::kDataAfterEnd))) } if (decodeRes != S_OK) return E_FAIL; } RINOK(decodeRes) if (encodeRes == S_OK) if (sb.ProcessedSize != sizeToEncode) encodeRes = E_FAIL; } else #endif { if (FosSpec2->Result == S_FALSE) { if (extractCallback) { RINOK(extractCallback->ReportExtractResult( NEventIndexType::kBlockIndex, (UInt32)folderIndex, NExtract::NOperationResult::kDataError)) } return E_FAIL; } RINOK(FosSpec2->Result) } RINOK(encodeRes) RINOK(repackBase->CheckFinishedState()) if (curUnpackSize != sizeToEncode) return E_FAIL; } for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += curUnpackSize; } newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { if (db->Files[fi].HasStream) { indexInFolder++; const int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; if (ui.NewData) continue; UString name; CFileItem file; CFileItem2 file2; GetFile(*db, fi, file, file2); if (ui.NewProps) { UpdateItem_To_FileItem2(ui, file2); file.IsDir = ui.IsDir; name = ui.Name; } else db->GetPath(fi, name); /* file.Parent = ui.ParentFolderIndex; if (ui.TreeFolderIndex >= 0) treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); if (totalSecureDataSize != 0) newDatabase.SecureIDs.Add(ui.SecureIndex); */ newDatabase.AddFile(file, file2, name); } } } } // ---------- Compress files to new solid blocks ---------- const unsigned numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector refItems; refItems.ClearAndSetSize(numFiles); // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1 const bool sortByType = options.UseTypeSorting; unsigned i; for (i = 0; i < numFiles; i++) refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); CSortParam sortParam; // sortParam.TreeFolders = &treeFolders; sortParam.SortByType = sortByType; refItems.Sort(CompareUpdateItems, (void *)&sortParam); CObjArray indices(numFiles); for (i = 0; i < numFiles; i++) { const UInt32 index = refItems[i].Index; indices[i] = index; /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProps) UpdateItem_To_FileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } for (i = 0; i < numFiles;) { UInt64 totalSize = 0; unsigned numSubFiles; const wchar_t *prevExtension = NULL; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { const int slashPos = ui.Name.ReverseFind_PathSepar(); const int dotPos = ui.Name.ReverseFind_Dot(); const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); if (numSubFiles == 0) prevExtension = ext; else if (!StringsAreEqualNoCase(ext, prevExtension)) break; } } if (numSubFiles < 1) numSubFiles = 1; RINOK(lps->SetCur()) /* const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size(); if (opCallback) { RINOK(opCallback->ReportOperation( NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdateNotifyOp::kAdd)); } */ CMyComPtr2_Create inStreamSpec; // solidInStream; // inStreamSpec->_reportArcProp = reportArcProp; inStreamSpec->Need_CTime = options.Need_CTime; inStreamSpec->Need_ATime = options.Need_ATime; inStreamSpec->Need_MTime = options.Need_MTime; inStreamSpec->Need_Attrib = options.Need_Attrib; // inStreamSpec->Need_Crc = options.Need_Crc; inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); unsigned startPackIndex = newDatabase.PackSizes.Size(); // UInt64 curFolderUnpackSize = totalSize; // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug const UInt64 expectedDataSize = totalSize; // const unsigned folderIndex_New = newDatabase.Folders.Size(); RINOK(encoder.Encode1( EXTERNAL_CODECS_LOC_VARS inStreamSpec, // NULL, &inSizeForReduce, expectedDataSize, // expected size newDatabase.Folders.AddNew(), // newDatabase.CoderUnpackSizes, curFolderUnpackSize, archive.SeqStream, newDatabase.PackSizes, lps)) if (!inStreamSpec->WasFinished()) return E_FAIL; /* if (inStreamSpec->Need_FolderCrc) newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, inStreamSpec->GetFolderCrc()); */ const UInt64 curFolderUnpackSize = inStreamSpec->Get_TotalSize_for_Coder(); encoder.Encode_Post(curFolderUnpackSize, newDatabase.CoderUnpackSizes); UInt64 packSize = 0; // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex; for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) packSize += newDatabase.PackSizes[startPackIndex]; lps->OutSize += packSize; // for () // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); CNum numUnpackStreams = 0; UInt64 skippedSize = 0; UInt64 procSize = 0; // unsigned numProcessedFiles = 0; for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; UString name; if (ui.NewProps) { UpdateItem_To_FileItem(ui, file, file2); name = ui.Name; } else { GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); db->GetPath((unsigned)ui.IndexInArchive, name); } if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { // we don't add file here skippedSize += ui.Size; continue; // comment it for debug // name += ".locked"; // for debug } // if (inStreamSpec->Need_Crc) file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; procSize += file.Size; // if (file.Size >= 0) // for debug: test purposes if (file.Size != 0) { file.CrcDefined = true; // inStreamSpec->Need_Crc; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } if (inStreamSpec->TimesDefined[subIndex]) { if (inStreamSpec->Need_CTime) { file2.CTimeDefined = true; file2.CTime = inStreamSpec->CTimes[subIndex]; } if (inStreamSpec->Need_ATime // && !ui.ATime_WasReadByAnalysis ) { file2.ATimeDefined = true; file2.ATime = inStreamSpec->ATimes[subIndex]; } if (inStreamSpec->Need_MTime) { file2.MTimeDefined = true; file2.MTime = inStreamSpec->MTimes[subIndex]; } if (inStreamSpec->Need_Attrib) { file2.AttribDefined = true; file2.Attrib = inStreamSpec->Attribs[subIndex]; } } /* file.Parent = ui.ParentFolderIndex; if (ui.TreeFolderIndex >= 0) treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); if (totalSecureDataSize != 0) newDatabase.SecureIDs.Add(ui.SecureIndex); */ /* if (reportArcProp) { RINOK(ReportItemProps(reportArcProp, ui.IndexInClient, file.Size, file.CrcDefined ? &file.Crc : NULL)) } */ // numProcessedFiles++; newDatabase.AddFile(file, file2, name); } /* // for debug: // we can write crc to folders area, if folder contains only one file if (numUnpackStreams == 1 && numSubFiles == 1) { const CFileItem &file = newDatabase.Files.Back(); if (file.CrcDefined) newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, file.Crc); } */ /* // it's optional check to ensure that sizes are correct if (inStreamSpec->TotalSize_for_Coder != curFolderUnpackSize) return E_FAIL; */ // if (inStreamSpec->AlignLog == 0) { if (procSize != curFolderUnpackSize) return E_FAIL; } // else { /* { const CFolder &old = newDatabase.Folders.Back(); CFolder &folder = newDatabase.Folders.AddNew(); { const unsigned numBonds = old.Bonds.Size(); folder.Bonds.SetSize(numBonds + 1); for (unsigned k = 0; k < numBonds; k++) folder.Bonds[k] = old.Bonds[k]; CBond &bond = folder.Bonds[numBonds]; bond.PackIndex = 0; bond.UnpackIndex = 0; } { const unsigned numCoders = old.Coders.Size(); folder.Coders.SetSize(numCoders + 1); for (unsigned k = 0; k < numCoders; k++) folder.Coders[k] = old.Coders[k]; CCoderInfo &cod = folder.Coders[numCoders]; cod.Props.Alloc(1); cod.Props[0] = (Byte)inStreamSpec->AlignLog; cod.NumStreams = 1; } { const unsigned numPackStreams = old.Coders.Size(); folder.Coders.SetSize(numPackStreams); for (unsigned k = 0; k < numPackStreams; k++) folder.PackStreams[k] = old.PackStreams[k]; } } newDatabase.Folders.Delete(newDatabase.Folders.Size() - 2); */ } lps->InSize += procSize; // lps->InSize += curFolderUnpackSize; // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; if (skippedSize != 0 && complexity >= skippedSize) { complexity -= skippedSize; RINOK(updateCallback->SetTotal(complexity)) } /* if (reportArcProp) { PROPVARIANT prop; prop.vt = VT_EMPTY; prop.wReserved1 = 0; { NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numProcessedFiles); RINOK(reportArcProp->ReportProp( NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumSubFiles, &prop)); } { NWindows::NCOM::PropVarEm_Set_UInt64(&prop, curFolderUnpackSize); RINOK(reportArcProp->ReportProp( NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidSize, &prop)); } { NWindows::NCOM::PropVarEm_Set_UInt64(&prop, packSize); RINOK(reportArcProp->ReportProp( NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidPackSize, &prop)); } { NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numStreams); RINOK(reportArcProp->ReportProp( NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumStreams, &prop)); } RINOK(reportArcProp->ReportFinished(NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdate::NOperationResult::kOK)); } */ /* if (opCallback) { RINOK(opCallback->ReportOperation( NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdateNotifyOp::kOpFinished)); } */ } } RINOK(lps->SetCur()) /* fileIndexToUpdateIndexMap.ClearAndFree(); groups.ClearAndFree(); */ /* for (i = 0; i < newDatabase.Files.Size(); i++) { CFileItem &file = newDatabase.Files[i]; file.Parent = treeFolderToArcIndex[file.Parent]; } if (totalSecureDataSize != 0) { newDatabase.SecureBuf.SetCapacity(totalSecureDataSize); size_t pos = 0; newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size()); for (i = 0; i < secureBlocks.Sorted.Size(); i++) { const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]]; size_t size = buf.GetCapacity(); if (size != 0) memcpy(newDatabase.SecureBuf + pos, buf, size); newDatabase.SecureSizes.Add((UInt32)size); pos += size; } } */ { const unsigned numFolders = newDatabase.Folders.Size(); if (newDatabase.NumUnpackStreamsVector.Size() != numFolders || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) return E_FAIL; newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders); } updateItems.ClearAndFree(); newDatabase.ReserveDown(); if (opCallback) RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader)) RINOK(archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS newDatabase, options.HeaderMethod, options.HeaderOptions)) if (v_StreamSetRestriction) RINOK(v_StreamSetRestriction->SetRestriction(0, 0)) return S_OK; } }} tmp41wklro_/CPP/7zip/Archive/7z/7zUpdate.h0000444000175000001440000000733614620120460021255 0ustar nabijaczleweliusers// 7zUpdate.h #ifndef ZIP7_INC_7Z_UPDATE_H #define ZIP7_INC_7Z_UPDATE_H #include "../IArchive.h" // #include "../../Common/UniqBlocks.h" #include "7zCompressionMode.h" #include "7zIn.h" namespace NArchive { namespace N7z { /* struct CTreeFolder { UString Name; int Parent; CIntVector SubFolders; int UpdateItemIndex; int SortIndex; int SortIndexEnd; CTreeFolder(): UpdateItemIndex(-1) {} }; */ struct CUpdateItem { int IndexInArchive; unsigned IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; /* bool IsAltStream; int ParentFolderIndex; int TreeFolderIndex; */ // that code is not used in 9.26 // int ParentSortIndex; // int ParentSortIndexEnd; UInt32 Attrib; bool NewData; bool NewProps; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; // bool ATime_WasReadByAnalysis; // int SecureIndex; // 0 means (no_security) bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes CUpdateItem(): // ParentSortIndex(-1), // IsAltStream(false), IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) // , ATime_WasReadByAnalysis(false) // SecureIndex(0) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); } // unsigned GetExtensionPos() const; // UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; // use additional filters for some files bool MaxFilter; // use BCJ2 filter instead of BCJ int AnalysisLevel; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool UseTypeSorting; bool RemoveSfxBlock; bool MultiThreadMixer; bool Need_CTime; bool Need_ATime; bool Need_MTime; bool Need_Attrib; // bool Need_Crc; CHeaderOptions HeaderOptions; CUIntVector DisabledFilterIDs; void Add_DisabledFilter_for_id(UInt32 id, const CUIntVector &enabledFilters) { if (enabledFilters.FindInSorted(id) < 0) DisabledFilterIDs.AddToUniqueSorted(id); } void SetFilterSupporting_ver_enabled_disabled( UInt32 compatVer, const CUIntVector &enabledFilters, const CUIntVector &disabledFilters) { DisabledFilterIDs = disabledFilters; if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters); if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters); } CUpdateOptions(): Method(NULL), HeaderMethod(NULL), UseFilters(false), MaxFilter(false), AnalysisLevel(-1), NumSolidFiles((UInt64)(Int64)(-1)), NumSolidBytes((UInt64)(Int64)(-1)), SolidExtension(false), UseTypeSorting(true), RemoveSfxBlock(false), MultiThreadMixer(true), Need_CTime(false), Need_ATime(false), Need_MTime(false), Need_Attrib(false) // , Need_Crc(true) { DisabledFilterIDs.Add(k_RISCV); } }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CDbEx *db, CObjectVector &updateItems, // const CObjectVector &treeFolders, // treeFolders[0] is root // const CUniqBlocks &secureBlocks, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif tmp41wklro_/CPP/7zip/Archive/7z/StdAfx.cpp0000444000175000001440000000004610144137330021266 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Archive/7z/StdAfx.h0000444000175000001440000000036114360505460020742 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Archive/Archive.def0000444000175000001440000000037614412530660021105 0ustar nabijaczleweliusersEXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE GetIsArc PRIVATE SetCodecs PRIVATE SetLargePageMode PRIVATE SetCaseSensitive PRIVATE GetModuleProp PRIVATE tmp41wklro_/CPP/7zip/Archive/Archive2.def0000444000175000001440000000060514412521640021160 0ustar nabijaczleweliusersEXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE GetIsArc PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE CreateDecoder PRIVATE CreateEncoder PRIVATE GetHashers PRIVATE SetCodecs PRIVATE SetLargePageMode PRIVATE SetCaseSensitive PRIVATE GetModuleProp PRIVATE tmp41wklro_/CPP/7zip/Archive/ArchiveExports.cpp0000444000175000001440000001176014407030460022512 0ustar nabijaczleweliusers// ArchiveExports.cpp #include "StdAfx.h" #include "../../../C/7zVersion.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" static const unsigned kNumArcsMax = 72; static unsigned g_NumArcs = 0; static unsigned g_DefaultArcIndex = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) throw() { if (g_NumArcs < kNumArcsMax) { const char *p = arcInfo->Name; if (p[0] == '7' && p[1] == 'z' && p[2] == 0) g_DefaultArcIndex = g_NumArcs; g_Arcs[g_NumArcs++] = arcInfo; } // else throw 1; } Z7_DEFINE_GUID(CLSID_CArchiveHandler, k_7zip_GUID_Data1, k_7zip_GUID_Data2, k_7zip_GUID_Data3_Common, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != NULL) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropStrFromBin((const char *)&guid, sizeof(guid), value); } static int FindFormatCalssId(const GUID *clsid) { GUID cls = *clsid; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; const Byte id = CLS_ARC_ID_ITEM(*clsid); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->Id == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { const int needIn = (*iid == IID_IInArchive); const int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; const int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::PropVariant_Clear(value); if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch (propID) { case NArchive::NHandlerPropID::kName: prop = arc.Name; break; case NArchive::NHandlerPropID::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.Id; return SetPropGUID(clsId, value); } case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break; case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break; case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break; case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break; case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; case NArchive::NHandlerPropID::kTimeFlags: prop = (UInt32)arc.TimeFlags; break; case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; case NArchive::NHandlerPropID::kSignature: if (arc.SignatureSize != 0 && !arc.IsMultiSignature()) return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); break; case NArchive::NHandlerPropID::kMultiSignature: if (arc.SignatureSize != 0 && arc.IsMultiSignature()) return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); break; } prop.Detach(value); return S_OK; COM_TRY_END } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(g_DefaultArcIndex, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats); STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc); STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) { *isArc = NULL; if (formatIndex >= g_NumArcs) return E_INVALIDARG; *isArc = g_Arcs[formatIndex]->IsArc; return S_OK; } tmp41wklro_/CPP/7zip/Archive/Common/0000700000175000001440000000000014706260545020266 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Archive/Common/CoderMixer2.cpp0000444000175000001440000007034114504600000023106 0ustar nabijaczleweliusers// CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" #ifdef USE_MIXER_ST Z7_COM7F_IMF(CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessed = 0; HRESULT result = S_OK; if (_stream) result = _stream->Read(data, size, &realProcessed); _size += realProcessed; if (size != 0 && realProcessed == 0) _wasFinished = true; if (processedSize) *processedSize = realProcessed; return result; } Z7_COM7F_IMF(COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)) { HRESULT result = S_OK; if (_stream) result = _stream->Write(data, size, &size); _size += size; if (processedSize) *processedSize = size; return result; } Z7_COM7F_IMF(COutStreamCalcSize::OutStreamFinish()) { HRESULT result = S_OK; if (_stream) { CMyComPtr outStreamFinish; _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish); if (outStreamFinish) result = outStreamFinish->OutStreamFinish(); } return result; } #endif namespace NCoderMixer2 { static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { v.ClearAndSetSize(size); bool *p = &v[0]; for (unsigned i = 0; i < size; i++) p[i] = false; } HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const { if (Coder) { if (PackSizePointers.IsEmpty() || !PackSizePointers[0]) return S_OK; CMyComPtr getInStreamProcessedSize; Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); // if (!getInStreamProcessedSize) return E_FAIL; if (getInStreamProcessedSize) { UInt64 processed; RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)) if (processed != (UInt64)(Int64)-1) { const UInt64 size = PackSizes[0]; if (processed < size && Finish) dataAfterEnd_Error = true; if (processed > size) { // InternalPackSizeError = true; // return S_FALSE; } } } } else if (Coder2) { CMyComPtr getInStreamProcessedSize2; Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2); if (getInStreamProcessedSize2) FOR_VECTOR (i, PackSizePointers) { if (!PackSizePointers[i]) continue; UInt64 processed; RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed)) if (processed != (UInt64)(Int64)-1) { const UInt64 size = PackSizes[i]; if (processed < size && Finish) dataAfterEnd_Error = true; else if (processed > size) { // InternalPackSizeError = true; // return S_FALSE; } } } } return S_OK; } class CBondsChecks { CBoolVector _coderUsed; bool Init(); bool CheckCoder(unsigned coderIndex); public: const CBindInfo *BindInfo; bool Check(); }; bool CBondsChecks::CheckCoder(unsigned coderIndex) { const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex]; if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex]) return false; _coderUsed[coderIndex] = true; const UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; for (unsigned i = 0; i < coder.NumStreams; i++) { UInt32 ind = start + i; if (BindInfo->IsStream_in_PackStreams(ind)) continue; const int bond = BindInfo->FindBond_for_PackStream(ind); if (bond < 0) return false; if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex)) return false; } return true; } bool CBondsChecks::Check() { BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size()); if (!CheckCoder(BindInfo->UnpackCoder)) return false; FOR_VECTOR(i, _coderUsed) if (!_coderUsed[i]) return false; return true; } void CBindInfo::ClearMaps() { Coder_to_Stream.Clear(); Stream_to_Coder.Clear(); } bool CBindInfo::CalcMapsAndCheck() { ClearMaps(); UInt32 numStreams = 0; if (Coders.Size() == 0) return false; if (Coders.Size() - 1 != Bonds.Size()) return false; FOR_VECTOR(i, Coders) { Coder_to_Stream.Add(numStreams); const CCoderStreamsInfo &c = Coders[i]; for (unsigned j = 0; j < c.NumStreams; j++) Stream_to_Coder.Add(i); numStreams += c.NumStreams; } if (numStreams != GetNum_Bonds_and_PackStreams()) return false; CBondsChecks bc; bc.BindInfo = this; return bc.Check(); } void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { Finish = finish; if (unpackSize) { UnpackSize = *unpackSize; UnpackSizePointer = &UnpackSize; } else { UnpackSize = 0; UnpackSizePointer = NULL; } PackSizes.ClearAndSetSize((unsigned)NumStreams); PackSizePointers.ClearAndSetSize((unsigned)NumStreams); for (unsigned i = 0; i < NumStreams; i++) { if (packSizes && packSizes[i]) { PackSizes[i] = *(packSizes[i]); PackSizePointers[i] = &PackSizes[i]; } else { PackSizes[i] = 0; PackSizePointers[i] = NULL; } } } bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) { if (coderIndex == _bi.UnpackCoder) return true; const int bond = _bi.FindBond_for_UnpackStream(coderIndex); if (bond < 0) throw 20150213; /* UInt32 coderIndex, coderStreamIndex; _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex); */ const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex]; if (!IsFilter_Vector[nextCoder]) return false; return Is_UnpackSize_Correct_for_Coder(nextCoder); } bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) { if (_bi.IsStream_in_PackStreams(streamIndex)) return true; const int bond = _bi.FindBond_for_PackStream(streamIndex); if (bond < 0) throw 20150213; const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex; if (!IsFilter_Vector[nextCoder]) return false; return Is_PackSize_Correct_for_Coder(nextCoder); } bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) { const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) if (!Is_PackSize_Correct_for_Stream(startIndex + i)) return false; return true; } bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) { if (IsExternal_Vector[coderIndex]) return true; const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) { const UInt32 si = startIndex + i; if (_bi.IsStream_in_PackStreams(si)) continue; const int bond = _bi.FindBond_for_PackStream(si); if (bond < 0) throw 20150213; if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex)) return true; } return false; } #ifdef USE_MIXER_ST CMixerST::CMixerST(bool encodeMode): CMixer(encodeMode) {} CMixerST::~CMixerST() {} void CMixerST::AddCoder(const CCreatedCoder &cod) { IsFilter_Vector.Add(cod.IsFilter); IsExternal_Vector.Add(cod.IsExternal); // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; CCoderST &c2 = _coders.AddNew(); c2.NumStreams = cod.NumStreams; c2.Coder = cod.Coder; c2.Coder2 = cod.Coder2; /* if (isFilter) { c2.CanRead = true; c2.CanWrite = true; } else */ { IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2); { Z7_DECL_CMyComPtr_QI_FROM(ISequentialInStream, s, unk) c2.CanRead = (s != NULL); } { Z7_DECL_CMyComPtr_QI_FROM(ISequentialOutStream, s, unk) c2.CanWrite = (s != NULL); } } } CCoder &CMixerST::GetCoder(unsigned index) { return _coders[index]; } HRESULT CMixerST::ReInit2() { return S_OK; } HRESULT CMixerST::GetInStream2( ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 outStreamIndex, ISequentialInStream **inStreamRes) { UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0; if (EncodeMode) { _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex); if (coderStreamIndex != 0) return E_NOTIMPL; } const CCoder &coder = _coders[coderIndex]; CMyComPtr seqInStream; coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream); if (!seqInStream) return E_NOTIMPL; const UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; const UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex]; bool isSet = false; if (numInStreams == 1) { CMyComPtr setStream; coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); if (setStream) { CMyComPtr seqInStream2; RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)) RINOK(setStream->SetInStream(seqInStream2)) isSet = true; } } if (!isSet && numInStreams != 0) { CMyComPtr setStream2; coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); if (!setStream2) return E_NOTIMPL; for (UInt32 i = 0; i < numInStreams; i++) { CMyComPtr seqInStream2; RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2)) RINOK(setStream2->SetInStream2(i, seqInStream2)) } } *inStreamRes = seqInStream.Detach(); return S_OK; } HRESULT CMixerST::GetInStream( ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 inStreamIndex, ISequentialInStream **inStreamRes) { CMyComPtr seqInStream; { int index = -1; if (EncodeMode) { if (_bi.UnpackCoder == inStreamIndex) index = 0; } else index = _bi.FindStream_in_PackStreams(inStreamIndex); if (index >= 0) { seqInStream = inStreams[(unsigned)index]; *inStreamRes = seqInStream.Detach(); return S_OK; } } const int bond = FindBond_for_Stream( true, // forInputStream inStreamIndex); if (bond < 0) return E_INVALIDARG; RINOK(GetInStream2(inStreams, /* inSizes, */ _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream)) while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.InStreamSpec) return E_NOTIMPL; CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize; bs.StreamRef = spec; bs.InStreamSpec = spec; spec->SetStream(seqInStream); spec->Init(); seqInStream = bs.InStreamSpec; *inStreamRes = seqInStream.Detach(); return S_OK; } HRESULT CMixerST::GetOutStream( ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) { CMyComPtr seqOutStream; { int index = -1; if (!EncodeMode) { if (_bi.UnpackCoder == outStreamIndex) index = 0; } else index = _bi.FindStream_in_PackStreams(outStreamIndex); if (index >= 0) { seqOutStream = outStreams[(unsigned)index]; *outStreamRes = seqOutStream.Detach(); return S_OK; } } const int bond = FindBond_for_Stream( false, // forInputStream outStreamIndex); if (bond < 0) return E_INVALIDARG; const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; if (!EncodeMode) _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); CCoder &coder = _coders[coderIndex]; /* if (!coder.Coder) return E_NOTIMPL; */ coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); if (!seqOutStream) return E_NOTIMPL; const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; bool isSet = false; if (numOutStreams == 1) { CMyComPtr setOutStream; coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (setOutStream) { CMyComPtr seqOutStream2; RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)) RINOK(setOutStream->SetOutStream(seqOutStream2)) isSet = true; } } if (!isSet && numOutStreams != 0) { return E_NOTIMPL; /* CMyComPtr setStream2; coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); if (!setStream2) return E_NOTIMPL; for (UInt32 i = 0; i < numOutStreams; i++) { CMyComPtr seqOutStream2; RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2)) RINOK(setStream2->SetOutStream2(i, seqOutStream2)) } */ } while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.OutStreamSpec) return E_NOTIMPL; COutStreamCalcSize *spec = new COutStreamCalcSize; bs.StreamRef = (ISequentialOutStream *)spec; bs.OutStreamSpec = spec; spec->SetStream(seqOutStream); spec->Init(); seqOutStream = bs.OutStreamSpec; *outStreamRes = seqOutStream.Detach(); return S_OK; } static HRESULT GetError(HRESULT res, HRESULT res2) { if (res == res2) return res; if (res == S_OK) return res2; if (res == k_My_HRESULT_WritingWasCut) { if (res2 != S_OK) return res2; } return res; } HRESULT CMixerST::FinishStream(UInt32 streamIndex) { { int index = -1; if (!EncodeMode) { if (_bi.UnpackCoder == streamIndex) index = 0; } else index = _bi.FindStream_in_PackStreams(streamIndex); if (index >= 0) return S_OK; } const int bond = FindBond_for_Stream( false, // forInputStream streamIndex); if (bond < 0) return E_INVALIDARG; const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; if (!EncodeMode) _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); CCoder &coder = _coders[coderIndex]; CMyComPtr finish; coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish); HRESULT res = S_OK; if (finish) { res = finish->OutStreamFinish(); } return GetError(res, FinishCoder(coderIndex)); } HRESULT CMixerST::FinishCoder(UInt32 coderIndex) { CCoder &coder = _coders[coderIndex]; const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; HRESULT res = S_OK; for (unsigned i = 0; i < numOutStreams; i++) res = GetError(res, FinishStream(startIndex + i)); return res; } void CMixerST::SelectMainCoder(bool useFirst) { unsigned ci = _bi.UnpackCoder; int firstNonFilter = -1; unsigned firstAllowed = ci; for (;;) { const CCoderST &coder = _coders[ci]; // break; if (ci != _bi.UnpackCoder) if (EncodeMode ? !coder.CanWrite : !coder.CanRead) { firstAllowed = ci; firstNonFilter = -2; } if (coder.NumStreams != 1) break; const UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; if (EncodeMode ? !coder.CanRead : !coder.CanWrite) break; if (firstNonFilter == -1 && !IsFilter_Vector[ci]) firstNonFilter = (int)ci; ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } if (useFirst) ci = firstAllowed; else if (firstNonFilter >= 0) ci = (unsigned)firstNonFilter; MainCoderIndex = ci; } HRESULT CMixerST::Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) { // InternalPackSizeError = false; dataAfterEnd_Error = false; _binderStreams.Clear(); const unsigned ci = MainCoderIndex; const CCoder &mainCoder = _coders[MainCoderIndex]; CObjectVector< CMyComPtr > seqInStreams; CObjectVector< CMyComPtr > seqOutStreams; const UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; const UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; const UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; const UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci]; UInt32 i; for (i = 0; i < numInStreams; i++) { CMyComPtr seqInStream; RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)) seqInStreams.Add(seqInStream); } for (i = 0; i < numOutStreams; i++) { CMyComPtr seqOutStream; RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)) seqOutStreams.Add(seqOutStream); } CRecordVector< ISequentialInStream * > seqInStreamsSpec; CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; for (i = 0; i < numInStreams; i++) seqInStreamsSpec.Add(seqInStreams[i]); for (i = 0; i < numOutStreams; i++) seqOutStreamsSpec.Add(seqOutStreams[i]); for (i = 0; i < _coders.Size(); i++) { if (i == ci) continue; CCoder &coder = _coders[i]; if (EncodeMode) { CMyComPtr initEncoder; coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder); if (initEncoder) { RINOK(initEncoder->InitEncoder()) } } else { CMyComPtr setOutStreamSize; coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); if (setOutStreamSize) { RINOK(setOutStreamSize->SetOutStreamSize( EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer)) } } } const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : mainCoder.PackSizePointers.ConstData(); const UInt64 * const *outSizes2 = EncodeMode ? mainCoder.PackSizePointers.ConstData() : &mainCoder.UnpackSizePointer; HRESULT res; if (mainCoder.Coder) { res = mainCoder.Coder->Code( seqInStreamsSpec[0], seqOutStreamsSpec[0], isSizes2[0], outSizes2[0], progress); } else { res = mainCoder.Coder2->Code( seqInStreamsSpec.ConstData(), isSizes2, numInStreams, seqOutStreamsSpec.ConstData(), outSizes2, numOutStreams, progress); } if (res == k_My_HRESULT_WritingWasCut) res = S_OK; if (res == S_OK || res == S_FALSE) { res = GetError(res, FinishCoder(ci)); } for (i = 0; i < _binderStreams.Size(); i++) { const CStBinderStream &bs = _binderStreams[i]; if (bs.InStreamSpec) bs.InStreamSpec->ReleaseStream(); else bs.OutStreamSpec->ReleaseStream(); } if (res == k_My_HRESULT_WritingWasCut) res = S_OK; if (res != S_OK) return res; for (i = 0; i < _coders.Size(); i++) { RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */)) } return S_OK; } HRESULT CMixerST::GetMainUnpackStream( ISequentialInStream * const *inStreams, ISequentialInStream **inStreamRes) { CMyComPtr seqInStream; RINOK(GetInStream2(inStreams, /* inSizes, */ _bi.UnpackCoder, &seqInStream)) FOR_VECTOR (i, _coders) { CCoder &coder = _coders[i]; CMyComPtr setOutStreamSize; coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); if (setOutStreamSize) { RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)) } } *inStreamRes = seqInStream.Detach(); return S_OK; } UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const { const CStBinderStream &bs = _binderStreams[bondIndex]; if (bs.InStreamSpec) return bs.InStreamSpec->GetSize(); return bs.OutStreamSpec->GetSize(); } #endif #ifdef USE_MIXER_MT void CCoderMT::Execute() { try { Code(NULL); } catch(...) { Result = E_FAIL; } } void CCoderMT::Code(ICompressProgressInfo *progress) { unsigned numInStreams = EncodeMode ? 1 : NumStreams; unsigned numOutStreams = EncodeMode ? NumStreams : 1; InStreamPointers.ClearAndReserve(numInStreams); OutStreamPointers.ClearAndReserve(numOutStreams); unsigned i; for (i = 0; i < numInStreams; i++) InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); for (i = 0; i < numOutStreams; i++) OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers. /* if (UnpackSizePointer) UnpackSizePointer = &UnpackSize; for (i = 0; i < NumStreams; i++) if (PackSizePointers[i]) PackSizePointers[i] = &PackSizes[i]; */ CReleaser releaser(*this); if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], EncodeMode ? UnpackSizePointer : PackSizePointers[0], EncodeMode ? PackSizePointers[0] : UnpackSizePointer, progress); else Result = Coder2->Code( InStreamPointers.ConstData(), EncodeMode ? &UnpackSizePointer : PackSizePointers.ConstData(), numInStreams, OutStreamPointers.ConstData(), EncodeMode ? PackSizePointers.ConstData(): &UnpackSizePointer, numOutStreams, progress); } HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) { CMixer::SetBindInfo(bindInfo); _streamBinders.Clear(); FOR_VECTOR (i, _bi.Bonds) { // RINOK(_streamBinders.AddNew().CreateEvents()) _streamBinders.AddNew(); } return S_OK; } void CMixerMT::AddCoder(const CCreatedCoder &cod) { IsFilter_Vector.Add(cod.IsFilter); IsExternal_Vector.Add(cod.IsExternal); // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; CCoderMT &c2 = _coders.AddNew(); c2.NumStreams = cod.NumStreams; c2.Coder = cod.Coder; c2.Coder2 = cod.Coder2; c2.EncodeMode = EncodeMode; } CCoder &CMixerMT::GetCoder(unsigned index) { return _coders[index]; } HRESULT CMixerMT::ReInit2() { FOR_VECTOR (i, _streamBinders) { RINOK(_streamBinders[i].Create_ReInit()) } return S_OK; } void CMixerMT::SelectMainCoder(bool useFirst) { unsigned ci = _bi.UnpackCoder; if (!useFirst) for (;;) { if (_coders[ci].NumStreams != 1) break; if (!IsFilter_Vector[ci]) break; UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } MainCoderIndex = ci; } HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) { unsigned i; for (i = 0; i < _coders.Size(); i++) { CCoderMT &coderInfo = _coders[i]; const CCoderStreamsInfo &csi = _bi.Coders[i]; UInt32 j; const unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; const unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1; coderInfo.InStreams.Clear(); for (j = 0; j < numInStreams; j++) coderInfo.InStreams.AddNew(); coderInfo.OutStreams.Clear(); for (j = 0; j < numOutStreams; j++) coderInfo.OutStreams.AddNew(); } for (i = 0; i < _bi.Bonds.Size(); i++) { const CBond &bond = _bi.Bonds[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; { UInt32 coderIndex, coderStreamIndex; _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex); inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex; outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex; inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex; outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; } _streamBinders[i].CreateStreams2( _coders[inCoderIndex].InStreams[inCoderStreamIndex], _coders[outCoderIndex].OutStreams[outCoderStreamIndex]); CMyComPtr inSetSize, outSetSize; _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); if (inSetSize && outSetSize) { const UInt32 kBufSize = 1 << 19; inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); } } { CCoderMT &cod = _coders[_bi.UnpackCoder]; if (EncodeMode) cod.InStreams[0] = inStreams[0]; else cod.OutStreams[0] = outStreams[0]; } for (i = 0; i < _bi.PackStreams.Size(); i++) { UInt32 coderIndex, coderStreamIndex; _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex); CCoderMT &cod = _coders[coderIndex]; if (EncodeMode) cod.OutStreams[coderStreamIndex] = outStreams[i]; else cod.InStreams[coderStreamIndex] = inStreams[i]; } return S_OK; } HRESULT CMixerMT::ReturnIfError(HRESULT code) { FOR_VECTOR (i, _coders) if (_coders[i].Result == code) return code; return S_OK; } HRESULT CMixerMT::Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) { // InternalPackSizeError = false; dataAfterEnd_Error = false; Init(inStreams, outStreams); unsigned i; for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) { const WRes wres = _coders[i].Create(); if (wres != 0) return HRESULT_FROM_WIN32(wres); } for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) { const WRes wres = _coders[i].Start(); if (wres != 0) return HRESULT_FROM_WIN32(wres); } _coders[MainCoderIndex].Code(progress); WRes wres = 0; for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) { WRes wres2 = _coders[i].WaitExecuteFinish(); if (wres == 0) wres = wres2; } if (wres != 0) return HRESULT_FROM_WIN32(wres); RINOK(ReturnIfError(E_ABORT)) RINOK(ReturnIfError(E_OUTOFMEMORY)) for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != k_My_HRESULT_WritingWasCut && result != S_FALSE && result != E_FAIL) return result; } RINOK(ReturnIfError(S_FALSE)) for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != k_My_HRESULT_WritingWasCut) return result; } for (i = 0; i < _coders.Size(); i++) { RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */)) } return S_OK; } UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const { return _streamBinders[bondIndex].ProcessedSize; } #endif } tmp41wklro_/CPP/7zip/Archive/Common/CoderMixer2.h0000444000175000001440000002552014413243240022562 0ustar nabijaczleweliusers// CoderMixer2.h #ifndef ZIP7_INC_CODER_MIXER2_H #define ZIP7_INC_CODER_MIXER2_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../ICoder.h" #include "../../Common/CreateCoder.h" #ifdef Z7_ST #define USE_MIXER_ST #else #define USE_MIXER_MT #ifndef Z7_SFX #define USE_MIXER_ST #endif #endif #ifdef USE_MIXER_MT #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" #endif #ifdef USE_MIXER_ST Z7_CLASS_IMP_COM_1( CSequentialInStreamCalcSize , ISequentialInStream ) bool _wasFinished; CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; } void ReleaseStream() { _stream.Release(); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; Z7_CLASS_IMP_COM_2( COutStreamCalcSize , ISequentialOutStream , IOutStreamFinish ) CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } }; #endif namespace NCoderMixer2 { struct CBond { UInt32 PackIndex; UInt32 UnpackIndex; UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } }; struct CCoderStreamsInfo { UInt32 NumStreams; }; struct CBindInfo { CRecordVector Coders; CRecordVector Bonds; CRecordVector PackStreams; unsigned UnpackCoder; unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } int FindBond_for_PackStream(UInt32 packStream) const { FOR_VECTOR (i, Bonds) if (Bonds[i].PackIndex == packStream) return (int)i; return -1; } int FindBond_for_UnpackStream(UInt32 unpackStream) const { FOR_VECTOR (i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) return (int)i; return -1; } bool SetUnpackCoder() { bool isOk = false; FOR_VECTOR (i, Coders) { if (FindBond_for_UnpackStream(i) < 0) { if (isOk) return false; UnpackCoder = i; isOk = true; } } return isOk; } bool IsStream_in_PackStreams(UInt32 streamIndex) const { return FindStream_in_PackStreams(streamIndex) >= 0; } int FindStream_in_PackStreams(UInt32 streamIndex) const { FOR_VECTOR (i, PackStreams) if (PackStreams[i] == streamIndex) return (int)i; return -1; } // that function is used before Maps is calculated UInt32 GetStream_for_Coder(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumStreams; return streamIndex; } // ---------- Maps Section ---------- CRecordVector Coder_to_Stream; CRecordVector Stream_to_Coder; void ClearMaps(); bool CalcMapsAndCheck(); // ---------- End of Maps Section ---------- void Clear() { Coders.Clear(); Bonds.Clear(); PackStreams.Clear(); ClearMaps(); } void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { coderIndex = Stream_to_Coder[streamIndex]; coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; } }; class CCoder { Z7_CLASS_NO_COPY(CCoder) public: CMyComPtr Coder; CMyComPtr Coder2; UInt32 NumStreams; bool Finish; UInt64 UnpackSize; const UInt64 *UnpackSizePointer; CRecordVector PackSizes; CRecordVector PackSizePointers; CCoder(): Finish(false) {} void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish); HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const; IUnknown *GetUnknown() const { return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; } HRESULT QueryInterface(REFGUID iid, void** pp) const { return GetUnknown()->QueryInterface(iid, pp); } }; class CMixer { bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); protected: CBindInfo _bi; int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const { if (EncodeMode == forInputStream) return _bi.FindBond_for_UnpackStream(streamIndex); else return _bi.FindBond_for_PackStream(streamIndex); } CBoolVector IsFilter_Vector; CBoolVector IsExternal_Vector; bool EncodeMode; public: unsigned MainCoderIndex; // bool InternalPackSizeError; CMixer(bool encodeMode): EncodeMode(encodeMode), MainCoderIndex(0) // , InternalPackSizeError(false) {} virtual ~CMixer() {} /* Sequence of calling: SetBindInfo(); for each coder AddCoder(); SelectMainCoder(); for each file { ReInit() for each coder SetCoderInfo(); Code(); } */ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) { _bi = bindInfo; IsFilter_Vector.Clear(); MainCoderIndex = 0; return S_OK; } virtual void AddCoder(const CCreatedCoder &cod) = 0; virtual CCoder &GetCoder(unsigned index) = 0; virtual void SelectMainCoder(bool useFirst) = 0; virtual HRESULT ReInit2() = 0; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) = 0; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); }; #ifdef USE_MIXER_ST struct CCoderST: public CCoder { bool CanRead; bool CanWrite; CCoderST(): CanRead(false), CanWrite(false) {} }; struct CStBinderStream { CSequentialInStreamCalcSize *InStreamSpec; COutStreamCalcSize *OutStreamSpec; CMyComPtr StreamRef; CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} }; class CMixerST: public IUnknown, public CMixer, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_CLASS_NO_COPY(CMixerST) HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 outStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 inStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); HRESULT FinishStream(UInt32 streamIndex); HRESULT FinishCoder(UInt32 coderIndex); public: CObjectVector _coders; CObjectVector _binderStreams; CMixerST(bool encodeMode); ~CMixerST() Z7_DESTRUCTOR_override; virtual void AddCoder(const CCreatedCoder &cod) Z7_override; virtual CCoder &GetCoder(unsigned index) Z7_override; virtual void SelectMainCoder(bool useFirst) Z7_override; virtual HRESULT ReInit2() Z7_override; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) Z7_override; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override; HRESULT GetMainUnpackStream( ISequentialInStream * const *inStreams, ISequentialInStream **inStreamRes); }; #endif #ifdef USE_MIXER_MT class CCoderMT: public CCoder, public CVirtThread { Z7_CLASS_NO_COPY(CCoderMT) CRecordVector InStreamPointers; CRecordVector OutStreamPointers; private: virtual void Execute() Z7_override; public: bool EncodeMode; HRESULT Result; CObjectVector< CMyComPtr > InStreams; CObjectVector< CMyComPtr > OutStreams; void Release() { InStreamPointers.Clear(); OutStreamPointers.Clear(); unsigned i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } class CReleaser { Z7_CLASS_NO_COPY(CReleaser) CCoderMT &_c; public: CReleaser(CCoderMT &c): _c(c) {} ~CReleaser() { _c.Release(); } }; CCoderMT(): EncodeMode(false) {} ~CCoderMT() Z7_DESTRUCTOR_override { /* WaitThreadFinish() will be called in ~CVirtThread(). But we need WaitThreadFinish() call before CCoder destructor, and before destructors of this class members. */ CVirtThread::WaitThreadFinish(); } void Code(ICompressProgressInfo *progress); }; class CMixerMT: public IUnknown, public CMixer, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_CLASS_NO_COPY(CMixerMT) CObjectVector _streamBinders; HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); // virtual ~CMixerMT() {} public: CObjectVector _coders; virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) Z7_override; virtual void AddCoder(const CCreatedCoder &cod) Z7_override; virtual CCoder &GetCoder(unsigned index) Z7_override; virtual void SelectMainCoder(bool useFirst) Z7_override; virtual HRESULT ReInit2() Z7_override; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress, bool &dataAfterEnd_Error) Z7_override; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override; CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; #endif } #endif tmp41wklro_/CPP/7zip/Archive/Common/DummyOutStream.cpp0000444000175000001440000000064414365252220023735 0ustar nabijaczleweliusers// DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" Z7_COM7F_IMF(CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize = size; HRESULT res = S_OK; if (_stream) res = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return res; } tmp41wklro_/CPP/7zip/Archive/Common/DummyOutStream.h0000444000175000001440000000100714366244420023400 0ustar nabijaczleweliusers// DummyOutStream.h #ifndef ZIP7_INC_DUMMY_OUT_STREAM_H #define ZIP7_INC_DUMMY_OUT_STREAM_H #include "../../../Common/MyCom.h" #include "../../IStream.h" Z7_CLASS_IMP_NOQIB_1( CDummyOutStream , ISequentialOutStream ) CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } }; #endif tmp41wklro_/CPP/7zip/Archive/Common/HandlerOut.cpp0000444000175000001440000001547514425736360023064 0ustar nabijaczleweliusers// HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" namespace NArchive { bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res) { if (*s == 0) { switch (prop.vt) { case VT_UI4: res = prop.ulVal; return true; case VT_UI8: res = prop.uhVal.QuadPart; return true; case VT_BSTR: s = prop.bstrVal; break; default: return false; } } else if (prop.vt != VT_EMPTY) return false; bool percentMode = false; { const wchar_t c = *s; if (MyCharLower_Ascii(c) == 'p') { percentMode = true; s++; } } const wchar_t *end; const UInt64 v = ConvertStringToUInt64(s, &end); if (s == end) return false; const wchar_t c = *end; if (percentMode) { if (c != 0) return false; res = Calc_From_Val_Percents(percentsBase, v); return true; } if (c == 0) { res = v; return true; } if (end[1] != 0) return false; if (c == '%') { res = Calc_From_Val_Percents(percentsBase, v); return true; } unsigned numBits; switch (MyCharLower_Ascii(c)) { case 'b': numBits = 0; break; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; default: return false; } const UInt64 val2 = v << numBits; if ((val2 >> numBits) != v) return false; res = val2; return true; } bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres) { hres = S_OK; if (name.IsPrefixedBy_Ascii_NoCase("mt")) { #ifndef Z7_ST _numThreads = _numProcessors; _numThreads_WasForced = false; hres = ParseMtProp2(name.Ptr(2), value, _numThreads, _numThreads_WasForced); // "mt" means "_numThreads_WasForced = false" here #endif return true; } if (name.IsPrefixedBy_Ascii_NoCase("memuse")) { UInt64 v; if (!ParseSizeString(name.Ptr(6), value, _memAvail, v)) hres = E_INVALIDARG; _memUsage_Decompress = v; _memUsage_Compress = v; _memUsage_WasSet = true; return true; } return false; } #ifndef Z7_EXTRACT_ONLY static void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value) { if (m.FindProp(propID) < 0) m.AddProp32(propID, value); } void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const { UInt32 level = _level; if (level != (UInt32)(Int32)-1) SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); } #ifndef Z7_ST static void SetMethodProp32_Replace(CMethodProps &m, PROPID propID, UInt32 value) { const int i = m.FindProp(propID); if (i >= 0) { NWindows::NCOM::CPropVariant &val = m.Props[(unsigned)i].Value; val = (UInt32)value; return; } m.AddProp32(propID, value); } void CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads) { SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); } void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads) { SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); } #endif // Z7_ST void CMultiMethodProps::InitMulti() { _level = (UInt32)(Int32)-1; _analysisLevel = -1; _crcSize = 4; _autoFilter = true; } void CMultiMethodProps::Init() { InitCommon(); InitMulti(); _methods.Clear(); _filterMethod.Clear(); } HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'x') { name.Delete(0); _level = 9; return ParsePropToUInt32(name, value, _level); } if (name.IsPrefixedBy_Ascii_NoCase("yx")) { name.Delete(0, 2); UInt32 v = 9; RINOK(ParsePropToUInt32(name, value, v)) _analysisLevel = (int)v; return S_OK; } if (name.IsPrefixedBy_Ascii_NoCase("crc")) { name.Delete(0, 3); _crcSize = 4; return ParsePropToUInt32(name, value, _crcSize); } { HRESULT hres; if (SetCommonProperty(name, value, hres)) return hres; } UInt32 number; const unsigned index = ParseStringToUInt32(name, number); const UString realName = name.Ptr(index); if (index == 0) { if (name.IsEqualTo("f")) { const HRESULT res = PROPVARIANT_to_bool(value, _autoFilter); if (res == S_OK) return res; if (value.vt != VT_BSTR) return E_INVALIDARG; return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value); } number = 0; } if (number > 64) return E_INVALIDARG; for (unsigned j = _methods.Size(); j <= number; j++) _methods.AddNew(); return _methods[number].ParseMethodFromPROPVARIANT(realName, value); } void CSingleMethodProps::Init() { InitCommon(); InitSingle(); Clear(); } HRESULT CSingleMethodProps::SetProperty(const wchar_t *name2, const PROPVARIANT &value) { // processed = false; UString name = name2; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; if (name.IsPrefixedBy_Ascii_NoCase("x")) { UInt32 a = 9; RINOK(ParsePropToUInt32(name.Ptr(1), value, a)) _level = a; AddProp_Level(a); // processed = true; return S_OK; } { HRESULT hres; if (SetCommonProperty(name, value, hres)) { // processed = true; return S_OK; } } RINOK(ParseMethodFromPROPVARIANT(name, value)) return S_OK; } HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { Init(); for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])) } return S_OK; } #endif static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) { RINOK(PROPVARIANT_to_bool(prop, dest.Val)) dest.Def = true; return S_OK; } HRESULT CHandlerTimeOptions::Parse(const UString &name, const PROPVARIANT &prop, bool &processed) { processed = true; if (name.IsEqualTo_Ascii_NoCase("tm")) { return PROPVARIANT_to_BoolPair(prop, Write_MTime); } if (name.IsEqualTo_Ascii_NoCase("ta")) { return PROPVARIANT_to_BoolPair(prop, Write_ATime); } if (name.IsEqualTo_Ascii_NoCase("tc")) { return PROPVARIANT_to_BoolPair(prop, Write_CTime); } if (name.IsPrefixedBy_Ascii_NoCase("tp")) { UInt32 v = 0; RINOK(ParsePropToUInt32(name.Ptr(2), prop, v)) Prec = v; return S_OK; } processed = false; return S_OK; } } tmp41wklro_/CPP/7zip/Archive/Common/HandlerOut.h0000444000175000001440000000706614366002640022515 0ustar nabijaczleweliusers// HandlerOut.h #ifndef ZIP7_INC_HANDLER_OUT_H #define ZIP7_INC_HANDLER_OUT_H #include "../../../Windows/System.h" #include "../../Common/MethodProps.h" namespace NArchive { bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res); class CCommonMethodProps { protected: void InitCommon() { // _Write_MTime = true; #ifndef Z7_ST _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); _numThreads_WasForced = false; #endif UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28; _memAvail = memAvail; _memUsage_Compress = memAvail; _memUsage_Decompress = memAvail; _memUsage_WasSet = NWindows::NSystem::GetRamSize(memAvail); if (_memUsage_WasSet) { _memAvail = memAvail; unsigned bits = sizeof(size_t) * 8; if (bits == 32) { const UInt32 limit2 = (UInt32)7 << 28; if (memAvail > limit2) memAvail = limit2; } // 80% - is auto usage limit in handlers // _memUsage_Compress = memAvail * 4 / 5; // _memUsage_Compress = Calc_From_Val_Percents(memAvail, 80); _memUsage_Compress = Calc_From_Val_Percents_Less100(memAvail, 80); _memUsage_Decompress = memAvail / 32 * 17; } } public: #ifndef Z7_ST UInt32 _numThreads; UInt32 _numProcessors; bool _numThreads_WasForced; #endif bool _memUsage_WasSet; UInt64 _memUsage_Compress; UInt64 _memUsage_Decompress; UInt64 _memAvail; bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres); CCommonMethodProps() { InitCommon(); } }; #ifndef Z7_EXTRACT_ONLY class CMultiMethodProps: public CCommonMethodProps { UInt32 _level; int _analysisLevel; void InitMulti(); public: UInt32 _crcSize; CObjectVector _methods; COneMethodInfo _filterMethod; bool _autoFilter; void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const; #ifndef Z7_ST static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads); static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads); #endif unsigned GetNumEmptyMethods() const { unsigned i; for (i = 0; i < _methods.Size(); i++) if (!_methods[i].IsEmpty()) break; return i; } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } int GetAnalysisLevel() const { return _analysisLevel; } void Init(); CMultiMethodProps() { InitMulti(); } HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); }; class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps { UInt32 _level; void InitSingle() { _level = (UInt32)(Int32)-1; } public: void Init(); CSingleMethodProps() { InitSingle(); } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &values); HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); }; #endif struct CHandlerTimeOptions { CBoolPair Write_MTime; CBoolPair Write_ATime; CBoolPair Write_CTime; UInt32 Prec; void Init() { Write_MTime.Init(); Write_MTime.Val = true; Write_ATime.Init(); Write_CTime.Init(); Prec = (UInt32)(Int32)-1; } CHandlerTimeOptions() { Init(); } HRESULT Parse(const UString &name, const PROPVARIANT &prop, bool &processed); }; } #endif tmp41wklro_/CPP/7zip/Archive/Common/InStreamWithCRC.cpp0000444000175000001440000000257214365252220023706 0ustar nabijaczleweliusers// InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" Z7_COM7F_IMF(CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessed = 0; HRESULT result = S_OK; if (size != 0) { if (_stream) result = _stream->Read(data, size, &realProcessed); _size += realProcessed; if (realProcessed == 0) _wasFinished = true; else _crc = CrcUpdate(_crc, data, realProcessed); } if (processedSize) *processedSize = realProcessed; return result; } Z7_COM7F_IMF(CSequentialInStreamWithCRC::GetSize(UInt64 *size)) { *size = _fullSize; return S_OK; } Z7_COM7F_IMF(CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessed = 0; HRESULT result = S_OK; if (_stream) result = _stream->Read(data, size, &realProcessed); _size += realProcessed; /* if (size != 0 && realProcessed == 0) _wasFinished = true; */ _crc = CrcUpdate(_crc, data, realProcessed); if (processedSize) *processedSize = realProcessed; return result; } Z7_COM7F_IMF(CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } tmp41wklro_/CPP/7zip/Archive/Common/InStreamWithCRC.h0000444000175000001440000000270514601255700023350 0ustar nabijaczleweliusers// InStreamWithCRC.h #ifndef ZIP7_INC_IN_STREAM_WITH_CRC_H #define ZIP7_INC_IN_STREAM_WITH_CRC_H #include "../../../../C/7zCrc.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" Z7_CLASS_IMP_NOQIB_2( CSequentialInStreamWithCRC , ISequentialInStream , IStreamGetSize ) CMyComPtr _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; UInt64 _fullSize; public: CSequentialInStreamWithCRC(): _fullSize((UInt64)(Int64)-1) {} void SetStream(ISequentialInStream *stream) { _stream = stream; } void SetFullSize(UInt64 fullSize) { _fullSize = fullSize; } void Init() { _size = 0; _crc = CRC_INIT_VAL; _wasFinished = false; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; Z7_CLASS_IMP_IInStream( CInStreamWithCRC ) CMyComPtr _stream; UInt64 _size; UInt32 _crc; // bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; // _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } // bool WasFinished() const { return _wasFinished; } }; #endif tmp41wklro_/CPP/7zip/Archive/Common/ItemNameUtils.cpp0000444000175000001440000000534014166621240023515 0ustar nabijaczleweliusers// Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR; #if WCHAR_PATH_SEPARATOR != L'/' static const wchar_t kUnixPathSepar = L'/'; #endif void ReplaceSlashes_OsToUnix #if WCHAR_PATH_SEPARATOR != L'/' (UString &name) { name.Replace(kOsPathSepar, kUnixPathSepar); } #else (UString &) {} #endif UString GetOsPath(const UString &name) { #if WCHAR_PATH_SEPARATOR != L'/' UString newName = name; newName.Replace(kUnixPathSepar, kOsPathSepar); return newName; #else return name; #endif } UString GetOsPath_Remove_TailSlash(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOsPath(name); if (newName.Back() == kOsPathSepar) newName.DeleteBack(); return newName; } void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool #if WCHAR_PATH_SEPARATOR != L'/' useBackslashReplacement #endif ) { if (name.IsEmpty()) return; #if WCHAR_PATH_SEPARATOR != L'/' { // name.Replace(kUnixPathSepar, kOsPathSepar); const unsigned len = name.Len(); for (unsigned i = 0; i < len; i++) { wchar_t c = name[i]; if (c == L'/') c = WCHAR_PATH_SEPARATOR; else if (useBackslashReplacement && c == L'\\') c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme else continue; name.ReplaceOneCharAtPos(i, c); } } #endif if (name.Back() == kOsPathSepar) name.DeleteBack(); } void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *name, unsigned len) { for (unsigned i = 0; i < len; i++) { wchar_t c = name[i]; if (c == L'/') c = L'_'; #if WCHAR_PATH_SEPARATOR != L'/' else if (c == L'\\') c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif else continue; name[i] = c; } } void NormalizeSlashes_in_FileName_for_OsPath(UString &name) { NormalizeSlashes_in_FileName_for_OsPath(name.GetBuf(), name.Len()); } bool HasTailSlash(const AString &name, UINT #if defined(_WIN32) && !defined(UNDER_CE) codePage #endif ) { if (name.IsEmpty()) return false; char c; #if defined(_WIN32) && !defined(UNDER_CE) if (codePage != CP_UTF8) c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); else #endif { c = name.Back(); } return (c == '/'); } #ifndef _WIN32 UString WinPathToOsPath(const UString &name) { UString newName = name; newName.Replace(L'\\', WCHAR_PATH_SEPARATOR); return newName; } #endif }} tmp41wklro_/CPP/7zip/Archive/Common/ItemNameUtils.h0000444000175000001440000000147714357314620023174 0ustar nabijaczleweliusers// Archive/Common/ItemNameUtils.h #ifndef ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H #define ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { void ReplaceSlashes_OsToUnix(UString &name); UString GetOsPath(const UString &name); UString GetOsPath_Remove_TailSlash(const UString &name); void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len); void NormalizeSlashes_in_FileName_for_OsPath(UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinPathToOsPath(const UString &name) { return name; } #else UString WinPathToOsPath(const UString &name); #endif }} #endif tmp41wklro_/CPP/7zip/Archive/Common/MultiStream.cpp0000444000175000001440000001141214413225200023227 0ustar nabijaczleweliusers// MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" Z7_COM7F_IMF(CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (_pos >= _totalLength) return S_OK; { unsigned left = 0, mid = _streamIndex, right = Streams.Size(); for (;;) { CSubStreamInfo &m = Streams[mid]; if (_pos < m.GlobalOffset) right = mid; else if (_pos >= m.GlobalOffset + m.Size) left = mid + 1; else break; mid = (left + right) / 2; } _streamIndex = mid; } CSubStreamInfo &s = Streams[_streamIndex]; UInt64 localPos = _pos - s.GlobalOffset; if (localPos != s.LocalPos) { RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos)) } { const UInt64 rem = s.Size - localPos; if (size > rem) size = (UInt32)rem; } const HRESULT result = s.Stream->Read(data, size, &size); _pos += size; s.LocalPos += size; if (processedSize) *processedSize = size; return result; } Z7_COM7F_IMF(CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _pos; break; case STREAM_SEEK_END: offset += _totalLength; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _pos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(ISequentialOutStream) unsigned _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr _volumeStream; COutArchive _archive; CCRC _crc; public: CFileItem _file; CUpdateOptions _options; CMyComPtr VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)) _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* #include "../../../Common/Defs.h" Z7_COM7F_IMF(COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)) RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)) subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)) RINOK(outStream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL)) subStream.Pos = _offsetPos; } const UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)) data = (const void *)((const Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (processedSize) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } Z7_COM7F_IMF(COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _absPos; break; case STREAM_SEEK_END: offset += _length; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _absPos = (UInt64)offset; _offsetPos = _absPos; _streamIndex = 0; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } */ tmp41wklro_/CPP/7zip/Archive/Common/MultiStream.h0000444000175000001440000000322114601255700022702 0ustar nabijaczleweliusers// MultiStream.h #ifndef ZIP7_INC_MULTI_STREAM_H #define ZIP7_INC_MULTI_STREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../IStream.h" #include "../../Archive/IArchive.h" Z7_CLASS_IMP_IInStream( CMultiStream ) unsigned _streamIndex; UInt64 _pos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr Stream; UInt64 Size; UInt64 GlobalOffset; UInt64 LocalPos; CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {} }; CMyComPtr updateCallbackFile; CObjectVector Streams; HRESULT Init() { UInt64 total = 0; FOR_VECTOR (i, Streams) { CSubStreamInfo &s = Streams[i]; s.GlobalOffset = total; total += s.Size; s.LocalPos = 0; { // it was already set to start // RINOK(InStream_GetPos(s.Stream, s.LocalPos)); } } _totalLength = total; _pos = 0; _streamIndex = 0; return S_OK; } }; /* Z7_CLASS_IMP_COM_1( COutMultiStream, IOutStream ) Z7_IFACE_COM7_IMP(ISequentialOutStream) unsigned _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr Stream; UInt64 Size; UInt64 Pos; }; CObjectVector Streams; public: CMyComPtr VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } }; */ #endif tmp41wklro_/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp0000444000175000001440000000064414365252220024105 0ustar nabijaczleweliusers// OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" Z7_COM7F_IMF(COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)) { HRESULT result = S_OK; if (_stream) result = _stream->Write(data, size, &size); if (_calculate) _crc = CrcUpdate(_crc, data, size); _size += size; if (processedSize) *processedSize = size; return result; } tmp41wklro_/CPP/7zip/Archive/Common/OutStreamWithCRC.h0000444000175000001440000000151614366244420023555 0ustar nabijaczleweliusers// OutStreamWithCRC.h #ifndef ZIP7_INC_OUT_STREAM_WITH_CRC_H #define ZIP7_INC_OUT_STREAM_WITH_CRC_H #include "../../../../C/7zCrc.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" Z7_CLASS_IMP_NOQIB_1( COutStreamWithCRC , ISequentialOutStream ) CMyComPtr _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void EnableCalc(bool calculate) { _calculate = calculate; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif tmp41wklro_/CPP/7zip/Archive/Common/ParseProperties.cpp0000444000175000001440000000005711523456440024126 0ustar nabijaczleweliusers// ParseProperties.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Archive/Common/ParseProperties.h0000444000175000001440000000015414357314620023572 0ustar nabijaczleweliusers// ParseProperties.h #ifndef ZIP7_INC_PARSE_PROPERTIES_H #define ZIP7_INC_PARSE_PROPERTIES_H #endif tmp41wklro_/CPP/7zip/Archive/Common/StdAfx.h0000444000175000001440000000036114360505460021632 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Archive/DllExports2.cpp0000444000175000001440000000726514407111640021733 0ustar nabijaczleweliusers// DLLExports2.cpp #include "StdAfx.h" #include "../../Common/MyWindows.h" #include "../../Common/MyInitGuid.h" #if defined(Z7_LARGE_PAGES) #include "../../../C/Alloc.h" #endif #include "../../Common/ComTry.h" #include "../../Windows/NtCheck.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" #include "../IPassword.h" #include "../Common/CreateCoder.h" #include "IArchive.h" #ifdef _WIN32 #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION return FALSE; #endif static HINSTANCE g_hInstance; extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE HANDLE #else HINSTANCE #endif hInstance, DWORD dwReason, LPVOID /*lpReserved*/); extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE HANDLE #else HINSTANCE #endif hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH"); g_hInstance = (HINSTANCE)hInstance; NT_CHECK } /* if (dwReason == DLL_PROCESS_DETACH) { OutputDebugStringA("7z.dll DLL_PROCESS_DETACH"); } */ return TRUE; } #else // _WIN32 #include "../../Common/StringConvert.h" // #include // STDAPI LibStartup(); static __attribute__((constructor)) void Init_ForceToUTF8(); static __attribute__((constructor)) void Init_ForceToUTF8() { g_ForceToUTF8 = IsNativeUTF8(); // printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0); } #endif // _WIN32 Z7_DEFINE_GUID(CLSID_CArchiveHandler, k_7zip_GUID_Data1, k_7zip_GUID_Data2, k_7zip_GUID_Data3_Common, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = NULL; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) return CreateCoder(clsid, iid, outObject); if (*iid == IID_IHasher) return CreateHasher(clsid, (IHasher **)outObject); return CreateArchiver(clsid, iid, outObject); // COM_TRY_END } STDAPI SetLargePageMode(); STDAPI SetLargePageMode() { #if defined(Z7_LARGE_PAGES) #ifdef _WIN32 SetLargePageSize(); #endif #endif return S_OK; } extern bool g_CaseSensitive; STDAPI SetCaseSensitive(Int32 caseSensitive); STDAPI SetCaseSensitive(Int32 caseSensitive) { g_CaseSensitive = (caseSensitive != 0); return S_OK; } /* UInt32 g_ClientVersion; STDAPI SetClientVersion(UInt32 version); STDAPI SetClientVersion(UInt32 version) { g_ClientVersion = version; return S_OK; } */ /* STDAPI SetProperty(Int32 id, const PROPVARIANT *value); STDAPI SetProperty(Int32 id, const PROPVARIANT *value) { return S_OK; } */ #ifdef Z7_EXTERNAL_CODECS CExternalCodecs g_ExternalCodecs; STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo); STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) { COM_TRY_BEGIN // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL"); if (compressCodecsInfo) { g_ExternalCodecs.GetCodecs = compressCodecsInfo; return g_ExternalCodecs.Load(); } g_ExternalCodecs.ClearAndRelease(); return S_OK; COM_TRY_END } #else STDAPI SetCodecs(ICompressCodecsInfo *); STDAPI SetCodecs(ICompressCodecsInfo *) { return S_OK; } #endif tmp41wklro_/CPP/7zip/Archive/IArchive.h0000444000175000001440000006203014576475540020722 0ustar nabijaczleweliusers// IArchive.h #ifndef ZIP7_INC_IARCHIVE_H #define ZIP7_INC_IARCHIVE_H #include "../IProgress.h" #include "../IStream.h" #include "../PropID.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACE_CONSTR_ARCHIVE_SUB(i, base, n) \ Z7_DECL_IFACE_7ZIP_SUB(i, base, 6, n) \ { Z7_IFACE_COM7_PURE(i) }; #define Z7_IFACE_CONSTR_ARCHIVE(i, n) \ Z7_IFACE_CONSTR_ARCHIVE_SUB(i, IUnknown, n) /* How the function in 7-Zip returns object for output parameter via pointer 1) The caller sets the value of variable before function call: PROPVARIANT : vt = VT_EMPTY BSTR : NULL IUnknown* and derived interfaces : NULL another scalar types : any non-initialized value is allowed 2) The callee in current 7-Zip code now can free input object for output parameter: PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input value stored in variable another types : the callee ignores stored value. 3) The callee writes new value to variable for output parameter and returns execution to caller. 4) The caller must free or release object returned by the callee: PROPVARIANT : VariantClear(&propvaiant) BSTR : SysFreeString(bstr) IUnknown* and derived interfaces : if (ptr) ptr->Relase() */ namespace NFileTimeType { enum EEnum { kNotDefined = -1, kWindows = 0, kUnix, kDOS, k1ns }; } namespace NArcInfoFlags { const UInt32 kKeepName = 1 << 0; // keep name of file in archive name const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams const UInt32 kNtSecure = 1 << 2; // the handler supports NT security const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive const UInt32 kMultiSignature = 1 << 4; // there are several signatures const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset const UInt32 kStartOpen = 1 << 6; // call handler for each start position const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links const UInt32 kHardLinks = 1 << 11; // the handler supports hard links const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums) const UInt32 kCTime = 1 << 14; const UInt32 kCTime_Default = 1 << 15; const UInt32 kATime = 1 << 16; const UInt32 kATime_Default = 1 << 17; const UInt32 kMTime = 1 << 18; const UInt32 kMTime_Default = 1 << 19; // const UInt32 kTTime_Reserved = 1 << 20; // const UInt32 kTTime_Reserved_Default = 1 << 21; } namespace NArcInfoTimeFlags { const unsigned kTime_Prec_Mask_bit_index = 0; const unsigned kTime_Prec_Mask_num_bits = 26; const unsigned kTime_Prec_Default_bit_index = 27; const unsigned kTime_Prec_Default_num_bits = 5; } #define TIME_PREC_TO_ARC_FLAGS_MASK(v) \ ((UInt32)1 << (NArcInfoTimeFlags::kTime_Prec_Mask_bit_index + (v))) #define TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(v) \ ((UInt32)(v) << NArcInfoTimeFlags::kTime_Prec_Default_bit_index) namespace NArchive { namespace NHandlerPropID { enum { kName = 0, // VT_BSTR kClassID, // binary GUID in VT_BSTR kExtension, // VT_BSTR kAddExtension, // VT_BSTR kUpdate, // VT_BOOL kKeepName, // VT_BOOL kSignature, // binary in VT_BSTR kMultiSignature, // binary in VT_BSTR kSignatureOffset, // VT_UI4 kAltStreams, // VT_BOOL kNtSecure, // VT_BOOL kFlags, // VT_UI4 kTimeFlags // VT_UI4 }; } namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip, kReadExternal }; } namespace NOperationResult { enum { kOK = 0, kUnsupportedMethod, kDataError, kCRCError, kUnavailable, kUnexpectedEnd, kDataAfterEnd, kIsNotArc, kHeadersError, kWrongPassword // , kMemError }; } } namespace NEventIndexType { enum { kNoIndex = 0, kInArcIndex, kBlockIndex, kOutArcIndex // kArcProp }; } namespace NUpdate { namespace NOperationResult { enum { kOK = 0 // kError = 1, // kError_FileChanged }; } } } #define Z7_IFACEM_IArchiveOpenCallback(x) \ x(SetTotal(const UInt64 *files, const UInt64 *bytes)) \ x(SetCompleted(const UInt64 *files, const UInt64 *bytes)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenCallback, 0x10) /* IArchiveExtractCallback:: 7-Zip doesn't call IArchiveExtractCallback functions GetStream() PrepareOperation() SetOperationResult() from different threads simultaneously. But 7-Zip can call functions for IProgress or ICompressProgressInfo functions from another threads simultaneously with calls for IArchiveExtractCallback interface. IArchiveExtractCallback::GetStream() UInt32 index - index of item in Archive Int32 askExtractMode (Extract::NAskMode) if (askMode != NExtract::NAskMode::kExtract) { then the callee doesn't write data to stream: (*outStream == NULL) } Out: (*outStream == NULL) - for directories (*outStream == NULL) - if link (hard link or symbolic link) was created if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract) { then the caller must skip extracting of that file. } returns: S_OK : OK S_FALSE : data error (for decoders) if (IProgress::SetTotal() was called) { IProgress::SetCompleted(completeValue) uses packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd). unpackSize - for another formats. } else { IProgress::SetCompleted(completeValue) uses packSize. } SetOperationResult() 7-Zip calls SetOperationResult at the end of extracting, so the callee can close the file, set attributes, timestamps and security information. Int32 opRes (NExtract::NOperationResult) */ // INTERFACE_IProgress(x) #define Z7_IFACEM_IArchiveExtractCallback(x) \ x(GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) \ x(PrepareOperation(Int32 askExtractMode)) \ x(SetOperationResult(Int32 opRes)) \ Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallback, IProgress, 0x20) /* v23: IArchiveExtractCallbackMessage2 can be requested from IArchiveExtractCallback object by Extract() or UpdateItems() functions to report about extracting errors ReportExtractResult() UInt32 indexType (NEventIndexType) UInt32 index Int32 opRes (NExtract::NOperationResult) */ /* before v23: #define Z7_IFACEM_IArchiveExtractCallbackMessage(x) \ x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)) Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21) */ #define Z7_IFACEM_IArchiveExtractCallbackMessage2(x) \ x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveExtractCallbackMessage2, 0x22) #define Z7_IFACEM_IArchiveOpenVolumeCallback(x) \ x(GetProperty(PROPID propID, PROPVARIANT *value)) \ x(GetStream(const wchar_t *name, IInStream **inStream)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenVolumeCallback, 0x30) #define Z7_IFACEM_IInArchiveGetStream(x) \ x(GetStream(UInt32 index, ISequentialInStream **stream)) Z7_IFACE_CONSTR_ARCHIVE(IInArchiveGetStream, 0x40) #define Z7_IFACEM_IArchiveOpenSetSubArchiveName(x) \ x(SetSubArchiveName(const wchar_t *name)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSetSubArchiveName, 0x50) /* IInArchive::Open stream if (kUseGlobalOffset), stream current position can be non 0. if (!kUseGlobalOffset), stream current position is 0. if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream if (*maxCheckStartPosition == 0), the handler must check only current position as archive start IInArchive::Extract: indices must be sorted numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" IInArchive::GetArchiveProperty: kpidOffset - start offset of archive. VT_EMPTY : means offset = 0. VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed kpidPhySize - size of archive. VT_EMPTY means unknown size. kpidPhySize is allowed to be larger than file size. In that case it must show supposed size. kpidIsDeleted: kpidIsAltStream: kpidIsAux: kpidINode: must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty. Notes: Don't call IInArchive functions for same IInArchive object from different threads simultaneously. Some IInArchive handlers will work incorrectly in that case. */ #if defined(_MSC_VER) && !defined(__clang__) #define MY_NO_THROW_DECL_ONLY Z7_COM7F_E #else #define MY_NO_THROW_DECL_ONLY #endif #define Z7_IFACEM_IInArchive(x) \ x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \ x(Close()) \ x(GetNumberOfItems(UInt32 *numItems)) \ x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \ x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) \ x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \ x(GetNumberOfProperties(UInt32 *numProps)) \ x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \ x(GetNumberOfArchiveProperties(UInt32 *numProps)) \ x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \ Z7_IFACE_CONSTR_ARCHIVE(IInArchive, 0x60) namespace NParentType { enum { kDir = 0, kAltStream }; } namespace NPropDataType { const UInt32 kMask_ZeroEnd = 1 << 4; // const UInt32 kMask_BigEndian = 1 << 5; const UInt32 kMask_Utf = 1 << 6; const UInt32 kMask_Utf8 = kMask_Utf | 0; const UInt32 kMask_Utf16 = kMask_Utf | 1; // const UInt32 kMask_Utf32 = kMask_Utf | 2; const UInt32 kNotDefined = 0; const UInt32 kRaw = 1; const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd; const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; } // UTF string (pointer to wchar_t) with zero end and little-endian. #define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1)) /* GetRawProp: Result: S_OK - even if property is not set */ #define Z7_IFACEM_IArchiveGetRawProps(x) \ x(GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)) \ x(GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \ x(GetNumRawProps(UInt32 *numProps)) \ x(GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetRawProps, 0x70) #define Z7_IFACEM_IArchiveGetRootProps(x) \ x(GetRootProp(PROPID propID, PROPVARIANT *value)) \ x(GetRootRawProp(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetRootProps, 0x71) #define Z7_IFACEM_IArchiveOpenSeq(x) \ x(OpenSeq(ISequentialInStream *stream)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSeq, 0x61) /* OpenForSize Result: S_FALSE - is not archive ? - DATA error */ /* const UInt32 kOpenFlags_RealPhySize = 1 << 0; const UInt32 kOpenFlags_NoSeek = 1 << 1; // const UInt32 kOpenFlags_BeforeExtract = 1 << 2; */ /* Flags: 0 - opens archive with IInStream, if IInStream interface is supported - if phySize is not available, it doesn't try to make full parse to get phySize kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified, the handler can return S_OK, but it doesn't check even Signature. So next Extract can be called for that sequential stream. */ /* #define Z7_IFACEM_IArchiveOpen2(x) \ x(ArcOpen2(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpen2, 0x62) */ // ---------- UPDATE ---------- /* GetUpdateItemInfo outs: *newData *newProps 0 0 - Copy data and properties from archive 0 1 - Copy data from archive, request new properties 1 0 - that combination is unused now 1 1 - Request new data and new properties. It can be used even for folders indexInArchive = -1 if there is no item in archive, or if it doesn't matter. GetStream out: Result: S_OK: (*inStream == NULL) - only for directories - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file (*inStream != NULL) - for any file, even for empty file or anti-file S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason) (*inStream == NULL) The order of calling for hard links: - GetStream() - GetProperty(kpidHardLink) SetOperationResult() Int32 opRes (NExtract::NOperationResult::kOK) */ // INTERFACE_IProgress(x) #define Z7_IFACEM_IArchiveUpdateCallback(x) \ x(GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)) \ x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \ x(GetStream(UInt32 index, ISequentialInStream **inStream)) \ x(SetOperationResult(Int32 operationResult)) \ Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback, IProgress, 0x80) // INTERFACE_IArchiveUpdateCallback(x) #define Z7_IFACEM_IArchiveUpdateCallback2(x) \ x(GetVolumeSize(UInt32 index, UInt64 *size)) \ x(GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)) \ Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) namespace NUpdateNotifyOp { enum { kAdd = 0, kUpdate, kAnalyze, kReplicate, kRepack, kSkip, kDelete, kHeader, kHashRead, kInFileChanged // , kOpFinished // , kNumDefined }; } /* IArchiveUpdateCallbackFile::ReportOperation UInt32 indexType (NEventIndexType) UInt32 index UInt32 notifyOp (NUpdateNotifyOp) */ #define Z7_IFACEM_IArchiveUpdateCallbackFile(x) \ x(GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp)) \ x(ReportOperation(UInt32 indexType, UInt32 index, UInt32 notifyOp)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackFile, 0x83) #define Z7_IFACEM_IArchiveGetDiskProperty(x) \ x(GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetDiskProperty, 0x84) /* #define Z7_IFACEM_IArchiveUpdateCallbackArcProp(x) \ x(ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)) \ x(ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)) \ x(ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)) \ x(DoNeedArcProp(PROPID propID, Int32 *answer)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackArcProp, 0x85) */ /* UpdateItems() ------------- outStream: output stream. (the handler) MUST support the case when Seek position in outStream is not ZERO. but the caller calls with empty outStream and seek position is ZERO?? archives with stub: If archive is open and the handler and (Offset > 0), then the handler knows about stub size. UpdateItems(): 1) the handler MUST copy that stub to outStream 2) the caller MUST NOT copy the stub to outStream, if "rsfx" property is set with SetProperties the handler must support the case where ISequentialOutStream *outStream */ #define Z7_IFACEM_IOutArchive(x) \ x(UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback)) \ x(GetFileTimeType(UInt32 *type)) Z7_IFACE_CONSTR_ARCHIVE(IOutArchive, 0xA0) /* ISetProperties::SetProperties() PROPVARIANT values[i].vt: VT_EMPTY VT_BOOL VT_UI4 - if 32-bit number VT_UI8 - if 64-bit number VT_BSTR */ #define Z7_IFACEM_ISetProperties(x) \ x(SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) Z7_IFACE_CONSTR_ARCHIVE(ISetProperties, 0x03) #define Z7_IFACEM_IArchiveKeepModeForNextOpen(x) \ x(KeepModeForNextOpen()) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveKeepModeForNextOpen, 0x04) /* Exe handler: the handler for executable format (PE, ELF, Mach-O). SFX archive: executable stub + some tail data. before 9.31: exe handler didn't parse SFX archives as executable format. for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */ #define Z7_IFACEM_IArchiveAllowTail(x) \ x(AllowTail(Int32 allowTail)) \ Z7_IFACE_CONSTR_ARCHIVE(IArchiveAllowTail, 0x05) namespace NRequestMemoryUseFlags { const UInt32 k_AllowedSize_WasForced = 1 << 0; // (*allowedSize) was forced by -mmemx or -smemx const UInt32 k_DefaultLimit_Exceeded = 1 << 1; // default limit of archive format was exceeded const UInt32 k_MLimit_Exceeded = 1 << 2; // -mmemx value was exceeded const UInt32 k_SLimit_Exceeded = 1 << 3; // -smemx value was exceeded const UInt32 k_NoErrorMessage = 1 << 10; // do not show error message, and show only request const UInt32 k_IsReport = 1 << 11; // only report is required, without user request const UInt32 k_SkipArc_IsExpected = 1 << 12; // NRequestMemoryAnswerFlags::k_SkipArc flag answer is expected const UInt32 k_Report_SkipArc = 1 << 13; // report about SkipArc operation // const UInt32 k_SkipBigFile_IsExpected = 1 << 14; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused) // const UInt32 k_Report_SkipBigFile = 1 << 15; // report about SkipFile operation (unused) // const UInt32 k_SkipBigFiles_IsExpected = 1 << 16; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused) // const UInt32 k_Report_SkipBigFiles = 1 << 17; // report that all big files will be skipped (unused) } namespace NRequestMemoryAnswerFlags { const UInt32 k_Allow = 1 << 0; // allow further archive extraction const UInt32 k_Stop = 1 << 1; // for exit (and return_code == E_ABORT is used) const UInt32 k_SkipArc = 1 << 2; // skip current archive extraction // const UInt32 k_SkipBigFile = 1 << 4; // skip extracting of files that exceed limit (unused) // const UInt32 k_SkipBigFiles = 1 << 5; // skip extracting of files that exceed limit (unused) const UInt32 k_Limit_Exceeded = 1 << 10; // limit was exceeded } /* *allowedSize is in/out: in : default allowed memory usage size or forced size, if it was changed by switch -mmemx. out : value specified by user or unchanged value. *answerFlags is in/out: *answerFlags must be set by caller before calling for default action, indexType : must be set with NEventIndexType::* constant (indexType == kNoIndex), if request for whole archive. index : must be set for some (indexType) types (if fileIndex , if (indexType == NEventIndexType::kInArcIndex) 0, if if (indexType == kNoIndex) path : NULL can be used for any indexType. */ #define Z7_IFACEM_IArchiveRequestMemoryUseCallback(x) \ x(RequestMemoryUse(UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path, \ UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags)) Z7_IFACE_CONSTR_ARCHIVE(IArchiveRequestMemoryUseCallback, 0x09) struct CStatProp { const char *Name; UInt32 PropID; VARTYPE vt; }; namespace NWindows { namespace NCOM { // PropVariant.cpp BSTR AllocBstrFromAscii(const char *s) throw(); }} #define IMP_IInArchive_GetProp_Base(fn, f, k) \ Z7_COM7F_IMF(CHandler::fn(UInt32 *numProps)) \ { *numProps = Z7_ARRAY_SIZE(k); return S_OK; } \ Z7_COM7F_IMF(CHandler::f(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \ { if (index >= Z7_ARRAY_SIZE(k)) return E_INVALIDARG; \ #define IMP_IInArchive_GetProp_NO_NAME(fn, f, k) \ IMP_IInArchive_GetProp_Base(fn, f, k) \ *propID = k[index]; \ *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; \ *name = NULL; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(fn, f, k) \ IMP_IInArchive_GetProp_Base(fn, f, k) \ const CStatProp &prop = k[index]; \ *propID = (PROPID)prop.PropID; \ *varType = prop.vt; \ *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \ #define IMP_IInArchive_Props \ IMP_IInArchive_GetProp_NO_NAME(GetNumberOfProperties, GetPropertyInfo, kProps) #define IMP_IInArchive_Props_WITH_NAME \ IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfProperties, GetPropertyInfo, kProps) #define IMP_IInArchive_ArcProps \ IMP_IInArchive_GetProp_NO_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps) #define IMP_IInArchive_ArcProps_NO_Table \ Z7_COM7F_IMF(CHandler::GetNumberOfArchiveProperties(UInt32 *numProps)) \ { *numProps = 0; return S_OK; } \ Z7_COM7F_IMF(CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *)) \ { return E_NOTIMPL; } \ #define IMP_IInArchive_ArcProps_NO \ IMP_IInArchive_ArcProps_NO_Table \ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value)) \ { value->vt = VT_EMPTY; return S_OK; } #define Z7_class_CHandler_final \ Z7_class_final(CHandler) #define Z7_CLASS_IMP_CHandler_IInArchive_0 \ Z7_CLASS_IMP_COM_1(CHandler, IInArchive) #define Z7_CLASS_IMP_CHandler_IInArchive_1(i1) \ Z7_CLASS_IMP_COM_2(CHandler, IInArchive, i1) #define Z7_CLASS_IMP_CHandler_IInArchive_2(i1, i2) \ Z7_CLASS_IMP_COM_3(CHandler, IInArchive, i1, i2) #define Z7_CLASS_IMP_CHandler_IInArchive_3(i1, i2, i3) \ Z7_CLASS_IMP_COM_4(CHandler, IInArchive, i1, i2, i3) #define Z7_CLASS_IMP_CHandler_IInArchive_4(i1, i2, i3, i4) \ Z7_CLASS_IMP_COM_5(CHandler, IInArchive, i1, i2, i3, i4) #define Z7_CLASS_IMP_CHandler_IInArchive_5(i1, i2, i3, i4, i5) \ Z7_CLASS_IMP_COM_6(CHandler, IInArchive, i1, i2, i3, i4, i5) #define k_IsArc_Res_NO 0 #define k_IsArc_Res_YES 1 #define k_IsArc_Res_NEED_MORE 2 // #define k_IsArc_Res_YES_LOW_PROB 3 #define API_FUNC_IsArc EXTERN_C UInt32 WINAPI #define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI extern "C" { typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size); typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc); typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats); typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value); typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); typedef HRESULT (WINAPI *Func_SetLargePageMode)(); // typedef HRESULT (WINAPI *Func_SetClientVersion)(UInt32 version); typedef IOutArchive * (*Func_CreateOutArchive)(); typedef IInArchive * (*Func_CreateInArchive)(); } /* if there is no time in archive, external MTime of archive will be used instead of _item.Time from archive. For 7-zip before 22.00 we need to return some supported value. But (kpidTimeType > kDOS) is not allowed in 7-Zip before 22.00. So we return highest precision value supported by old 7-Zip. new 7-Zip 22.00 doesn't use that value in usual cases. */ #define DECLARE_AND_SET_CLIENT_VERSION_VAR #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ NFileTimeType::kWindows /* extern UInt32 g_ClientVersion; #define GET_CLIENT_VERSION(major, minor) \ ((UInt32)(((UInt32)(major) << 16) | (UInt32)(minor))) #define DECLARE_AND_SET_CLIENT_VERSION_VAR \ UInt32 g_ClientVersion = GET_CLIENT_VERSION(MY_VER_MAJOR, MY_VER_MINOR); #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ ((UInt32)(g_ClientVersion >= GET_CLIENT_VERSION(22, 0) ? \ (UInt32)(Int32)NFileTimeType::kNotDefined : \ NFileTimeType::kWindows)) */ Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/Archive/Icons/0000700000175000001440000000000014706260545020111 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Archive/Icons/7z.ico0000444000175000001440000001114607636140464021161 0ustar nabijaczleweliusers ¨Fhî(V è~( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ """""""""""""""""""""""""""""" 0yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"0ÿš š š  š š   š š  šš š ššš šy"0ÿ   š š  š  šš š šš  ššš ššššy"0ÿš     š  šš  š š  ššš ššššššy"0ÿ  š š  š   š š  š  ššš š  ššy"0ÿ         š  š šš šš   šššš šy"0ÿ š š  š š  š š     šššš ššššy"0ÿ         š     š šš šš šš š y"0ÿ      š   š š š š  š  š  šššy"0ÿ    š             š šš ššš šy"0ÿ        š š š šš š    š  šš y"0ÿ      š       0ÿ           š  0ÿ        š    šÿÿÿÿÿÿÿÿÿÿÿÿ0ÿ              ÿÿÿÿÿÿÿÿÿÿÿÿ0ÿ          š š ÿÿÿÿÿÿÿÿÿ0ÿ              ÿÿÿÿÿÿÿÿÿ0ÿ              ÿÿÿÿÿÿÿÿÿ0ÿ             šÿÿÿÿÿÿÿÿÿ0ÿ              ÿÿÿÿÿÿÿÿÿ0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0yyyyyyyyyyyyyyyÿÿÿÿ 0ö            0ÿÿÿÿ 0ÿ          0 ÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿ        0 ÿÿÿÿÿÿÿÿÿÿÿÿ 000000000  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€Ààðÿÿ( @€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ 0yyyyyyyyyyyyy 0Ú š š š šššy 0à  š š š ššy 0à   0à   ÿÿÿÿÿÿÿÿ0à   ÿÿÿÿÿÿ0à   ÿÿÿÿÿÿ0à   ÿÿÿÿÿÿ0ÃÃÃÃÃÿÿÿÿÿÿ0yyyyyÿÿÿÿÿÿ 0ñÃàÿÿÿ 0000ÿÿÿÿÿÿÿÿ ÿÿÿÿ€€Àü( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ3333333;»»»»»»;»»»»»»;»»DDDDD;»»Oÿÿÿô;»»OÿDÿô;»»OÿDÿô;»»OÿDÿô;»»OÿôOô333OÿÿDô»»OôDDô33OÿÿÿôDDDDDÿÿÿÿ€€Àü( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ3333333333333330;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»»»»»»»»°;»»»»»»»DDDDDDDD;»»»»»»»DDDDDDDD;»»»»»»»DÿÿÿÿÿÿD;»»»»»»»DÿÿÿÿÿÿD;»»»»»»»DÿÿDOÿÿD;»»»»»»»DÿÿDOÿÿD;»»»»»»»DÿÿDOÿÿD;»»»»»»»DÿÿôDÿÿD;»»»»»»»DÿÿÿDOÿD;»»»»»»»DÿÿÿôDÿD33333333DÿDDDDÿD»»»»»»³DÿDDDDÿD;»»»»»0DÿÿÿÿÿÿD»»»»³DÿÿÿÿÿÿD33330DDDDDDDDDDDDDDDDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€Ààðÿÿtmp41wklro_/CPP/7zip/Archive/LzmaHandler.cpp0000444000175000001440000003417114567042400021752 0ustar nabijaczleweliusers// LzmaHandler.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "../../Common/ComTry.h" #include "../../Common/IntToString.h" #include "../../Windows/PropVariant.h" #include "../Common/FilterCoder.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" #include "../Compress/BcjCoder.h" #include "../Compress/LzmaDecoder.h" #include "Common/DummyOutStream.h" using namespace NWindows; namespace NArchive { namespace NLzma { static bool CheckDicSize(const Byte *p) { UInt32 dicSize = GetUi32(p); if (dicSize == 1) return true; for (unsigned i = 0; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return (dicSize == 0xFFFFFFFF); } static const Byte kProps[] = { kpidSize, kpidPackSize, kpidMethod }; static const Byte kArcProps[] = { kpidNumStreams, kpidMethod }; struct CHeader { UInt64 Size; Byte FilterID; Byte LzmaProps[5]; Byte GetProp() const { return LzmaProps[0]; } UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasSize() const { return (Size != (UInt64)(Int64)-1); } bool Parse(const Byte *buf, bool isThereFilter); }; bool CHeader::Parse(const Byte *buf, bool isThereFilter) { FilterID = 0; if (isThereFilter) FilterID = buf[0]; const Byte *sig = buf + (isThereFilter ? 1 : 0); for (int i = 0; i < 5; i++) LzmaProps[i] = sig[i]; Size = GetUi64(sig + 5); return LzmaProps[0] < 5 * 5 * 9 && FilterID < 2 && (!HasSize() || Size < ((UInt64)1 << 56)) && CheckDicSize(LzmaProps + 1); } class CDecoder Z7_final { CMyComPtr _bcjStream; CFilterCoder *_filterCoder; public: CMyComPtr2 _lzmaDecoder; ~CDecoder(); HRESULT Create(bool filtered, ISequentialInStream *inStream); HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); UInt64 GetInputProcessedSize() const { return _lzmaDecoder->GetInputProcessedSize(); } void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoder->ReleaseInStream(); } HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) { return _lzmaDecoder->ReadFromInputStream(data, size, processedSize); } }; HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) { _lzmaDecoder.Create_if_Empty(); _lzmaDecoder->FinishStream = true; if (filteredMode) { if (!_bcjStream) { _filterCoder = new CFilterCoder(false); CMyComPtr coder = _filterCoder; _filterCoder->Filter = new NCompress::NBcj::CCoder2(z7_BranchConvSt_X86_Dec); _bcjStream = _filterCoder; } } return _lzmaDecoder->SetInStream(inStream); } CDecoder::~CDecoder() { ReleaseInStream(); } HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { if (header.FilterID > 1) return E_NOTIMPL; RINOK(_lzmaDecoder->SetDecoderProperties2(header.LzmaProps, 5)) bool filteredMode = (header.FilterID == 1); if (filteredMode) { RINOK(_filterCoder->SetOutStream(outStream)) outStream = _bcjStream; RINOK(_filterCoder->SetOutStreamSize(NULL)) } const UInt64 *Size = header.HasSize() ? &header.Size : NULL; HRESULT res = _lzmaDecoder->CodeResume(outStream, Size, progress); if (filteredMode) { { HRESULT res2 = _filterCoder->OutStreamFinish(); if (res == S_OK) res = res2; } HRESULT res2 = _filterCoder->ReleaseOutStream(); if (res == S_OK) res = res2; } RINOK(res) if (header.HasSize()) if (_lzmaDecoder->GetOutputProcessedSize() != header.Size) return S_FALSE; return S_OK; } Z7_CLASS_IMP_CHandler_IInArchive_1( IArchiveOpenSeq ) bool _lzma86; bool _isArc; bool _needSeekToStart; bool _dataAfterEnd; bool _needMoreInput; bool _unsupported; bool _dataError; bool _packSize_Defined; bool _unpackSize_Defined; bool _numStreams_Defined; CHeader _header; CMyComPtr _stream; CMyComPtr _seqStream; UInt64 _packSize; UInt64 _unpackSize; UInt64 _numStreams; void GetMethod(NCOM::CPropVariant &prop); unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } public: CHandler(bool lzma86) { _lzma86 = lzma86; } }; IMP_IInArchive_Props IMP_IInArchive_ArcProps Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; case kpidMethod: GetMethod(prop); break; case kpidErrorFlags: { UInt32 v = 0; if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; if (_dataError) v |= kpv_ErrorFlags_DataError; prop = v; break; } default: break; } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = 1; return S_OK; } static char * DictSizeToString(UInt32 val, char *s) { for (unsigned i = 0; i < 32; i++) if (((UInt32)1 << i) == val) return ::ConvertUInt32ToString(i, s); char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } s = ::ConvertUInt32ToString(val, s); *s++ = c; *s = 0; return s; } static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); return ::ConvertUInt32ToString(v, s); } void CHandler::GetMethod(NCOM::CPropVariant &prop) { if (!_stream) return; char sz[64]; char *s = sz; if (_header.FilterID != 0) s = MyStpCpy(s, "BCJ "); s = MyStpCpy(s, "LZMA:"); s = DictSizeToString(_header.GetDicSize(), s); UInt32 d = _header.GetProp(); // if (d != 0x5D) { UInt32 lc = d % 9; d /= 9; UInt32 pb = d / 5; UInt32 lp = d % 5; if (lc != 3) s = AddProp32(s, "lc", lc); if (lp != 0) s = AddProp32(s, "lp", lp); if (pb != 2) s = AddProp32(s, "pb", pb); } prop = sz; } Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; case kpidMethod: GetMethod(prop); break; default: break; } prop.Detach(value); return S_OK; } API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) { const UInt32 kHeaderSize = 1 + 4 + 8; if (size < kHeaderSize) return k_IsArc_Res_NEED_MORE; if (p[0] >= 5 * 5 * 9) return k_IsArc_Res_NO; const UInt64 unpackSize = GetUi64(p + 1 + 4); if (unpackSize != (UInt64)(Int64)-1) { if (unpackSize >= ((UInt64)1 << 56)) return k_IsArc_Res_NO; } if (unpackSize != 0) { if (size < kHeaderSize + 2) return k_IsArc_Res_NEED_MORE; if (p[kHeaderSize] != 0) return k_IsArc_Res_NO; if (unpackSize != (UInt64)(Int64)-1) { if ((p[kHeaderSize + 1] & 0x80) != 0) return k_IsArc_Res_NO; } } if (!CheckDicSize(p + 1)) // return k_IsArc_Res_YES_LOW_PROB; return k_IsArc_Res_NO; return k_IsArc_Res_YES; } } API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size) { if (size < 1) return k_IsArc_Res_NEED_MORE; Byte filterID = p[0]; if (filterID != 0 && filterID != 1) return k_IsArc_Res_NO; return IsArc_Lzma(p + 1, size - 1); } } Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)) { Close(); const unsigned headerSize = GetHeaderSize(); const UInt32 kBufSize = 1 << 7; Byte buf[kBufSize]; size_t processedSize = kBufSize; RINOK(ReadStream(inStream, buf, &processedSize)) if (processedSize < headerSize + 2) return S_FALSE; if (!_header.Parse(buf, _lzma86)) return S_FALSE; const Byte *start = buf + headerSize; if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80 return S_FALSE; RINOK(InStream_GetSize_SeekToEnd(inStream, _packSize)) SizeT srcLen = (SizeT)processedSize - headerSize; if (srcLen > 10 && _header.Size == 0 // && _header.FilterID == 0 && _header.LzmaProps[0] == 0 ) return S_FALSE; const UInt32 outLimit = 1 << 11; Byte outBuf[outLimit]; SizeT outSize = outLimit; if (outSize > _header.Size) outSize = (SizeT)_header.Size; SizeT destLen = outSize; ELzmaStatus status; SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen, _header.LzmaProps, 5, LZMA_FINISH_ANY, &status, &g_Alloc); if (res != SZ_OK) if (res != SZ_ERROR_INPUT_EOF) return S_FALSE; _isArc = true; _stream = inStream; _seqStream = inStream; _needSeekToStart = true; return S_OK; } Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream)) { Close(); _isArc = true; _seqStream = stream; return S_OK; } Z7_COM7F_IMF(CHandler::Close()) { _isArc = false; _needSeekToStart = false; _dataAfterEnd = false; _needMoreInput = false; _unsupported = false; _dataError = false; _packSize_Defined = false; _unpackSize_Defined = false; _numStreams_Defined = false; _packSize = 0; _stream.Release(); _seqStream.Release(); return S_OK; } Z7_CLASS_IMP_COM_1( CCompressProgressInfoImp, ICompressProgressInfo ) CMyComPtr Callback; public: UInt64 Offset; void Init(IArchiveOpenCallback *callback) { Callback = callback; } }; Z7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)) { if (Callback) { const UInt64 files = 0; const UInt64 val = Offset + *inSize; return Callback->SetCompleted(&files, &val); } return S_OK; } Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) { COM_TRY_BEGIN if (numItems == 0) return S_OK; if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; if (_packSize_Defined) RINOK(extractCallback->SetTotal(_packSize)) Int32 opResult; { CMyComPtr realOutStream; const Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) if (!testMode && !realOutStream) return S_OK; RINOK(extractCallback->PrepareOperation(askMode)) CMyComPtr2_Create outStream; outStream->SetStream(realOutStream); outStream->Init(); realOutStream.Release(); CMyComPtr2_Create lps; lps->Init(extractCallback, true); if (_needSeekToStart) { if (!_stream) return E_FAIL; RINOK(InStream_SeekToBegin(_stream)) } else _needSeekToStart = true; CDecoder decoder; RINOK(decoder.Create(_lzma86, _seqStream)) bool firstItem = true; UInt64 packSize = 0; UInt64 unpackSize = 0; UInt64 numStreams = 0; bool dataAfterEnd = false; HRESULT hres = S_OK; for (;;) { lps->InSize = packSize; lps->OutSize = unpackSize; RINOK(lps->SetCur()) const UInt32 kBufSize = 1 + 5 + 8; Byte buf[kBufSize]; const UInt32 headerSize = GetHeaderSize(); UInt32 processed; RINOK(decoder.ReadInput(buf, headerSize, &processed)) if (processed != headerSize) { if (processed != 0) dataAfterEnd = true; break; } CHeader st; if (!st.Parse(buf, _lzma86)) { dataAfterEnd = true; break; } numStreams++; firstItem = false; hres = decoder.Code(st, outStream, lps); packSize = decoder.GetInputProcessedSize(); unpackSize = outStream->GetSize(); if (hres == E_NOTIMPL) { _unsupported = true; hres = S_FALSE; break; } if (hres == S_FALSE) break; RINOK(hres) } if (firstItem) { _isArc = false; hres = S_FALSE; } else if (hres == S_OK || hres == S_FALSE) { if (dataAfterEnd) _dataAfterEnd = true; else if (decoder._lzmaDecoder->NeedsMoreInput()) _needMoreInput = true; _packSize = packSize; _unpackSize = unpackSize; _numStreams = numStreams; _packSize_Defined = true; _unpackSize_Defined = true; _numStreams_Defined = true; } opResult = NExtract::NOperationResult::kOK; if (!_isArc) opResult = NExtract::NOperationResult::kIsNotArc; else if (_needMoreInput) opResult = NExtract::NOperationResult::kUnexpectedEnd; else if (_unsupported) opResult = NExtract::NOperationResult::kUnsupportedMethod; else if (_dataAfterEnd) opResult = NExtract::NOperationResult::kDataAfterEnd; else if (hres == S_FALSE) opResult = NExtract::NOperationResult::kDataError; else if (hres == S_OK) opResult = NExtract::NOperationResult::kOK; else return hres; // outStream.Release(); } return extractCallback->SetOperationResult(opResult); COM_TRY_END } namespace NLzmaAr { // 2, { 0x5D, 0x00 }, REGISTER_ARC_I_CLS_NO_SIG( CHandler(false), "lzma", "lzma", NULL, 0xA, 0, NArcInfoFlags::kStartOpen | NArcInfoFlags::kKeepName, IsArc_Lzma) } namespace NLzma86Ar { REGISTER_ARC_I_CLS_NO_SIG( CHandler(true), "lzma86", "lzma86", NULL, 0xB, 0, NArcInfoFlags::kKeepName, IsArc_Lzma86) } }} tmp41wklro_/CPP/7zip/Archive/SplitHandler.cpp0000444000175000001440000002012414567042400022133 0ustar nabijaczleweliusers// SplitHandler.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/MyString.h" #include "../../Windows/PropVariant.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" #include "Common/MultiStream.h" using namespace NWindows; namespace NArchive { namespace NSplit { static const Byte kProps[] = { kpidPath, kpidSize }; static const Byte kArcProps[] = { kpidNumVolumes, kpidTotalPhySize }; Z7_CLASS_IMP_CHandler_IInArchive_1( IInArchiveGetStream ) CObjectVector > _streams; CRecordVector _sizes; UString _subName; UInt64 _totalSize; HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); }; IMP_IInArchive_Props IMP_IInArchive_ArcProps Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidMainSubfile: prop = (UInt32)0; break; case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; case kpidTotalPhySize: prop = _totalSize; break; case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; default: break; } prop.Detach(value); return S_OK; } struct CSeqName { UString _unchangedPart; UString _changedPart; bool _splitStyle; bool GetNextName(UString &s) { { unsigned i = _changedPart.Len(); for (;;) { wchar_t c = _changedPart[--i]; if (_splitStyle) { if (c == 'z') { _changedPart.ReplaceOneCharAtPos(i, L'a'); if (i == 0) return false; continue; } else if (c == 'Z') { _changedPart.ReplaceOneCharAtPos(i, L'A'); if (i == 0) return false; continue; } } else { if (c == '9') { _changedPart.ReplaceOneCharAtPos(i, L'0'); if (i == 0) { _changedPart.InsertAtFront(L'1'); break; } continue; } } c++; _changedPart.ReplaceOneCharAtPos(i, c); break; } } s = _unchangedPart + _changedPart; return true; } }; HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { Close(); if (!callback) return S_FALSE; Z7_DECL_CMyComPtr_QI_FROM( IArchiveOpenVolumeCallback, volumeCallback, callback) if (!volumeCallback) return S_FALSE; UString name; { NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidName, &prop)) if (prop.vt != VT_BSTR) return S_FALSE; name = prop.bstrVal; } const int dotPos = name.ReverseFind_Dot(); const UString prefix = name.Left((unsigned)(dotPos + 1)); const UString ext = name.Ptr((unsigned)(dotPos + 1)); UString ext2 = ext; ext2.MakeLower_Ascii(); CSeqName seqName; unsigned numLetters = 2; bool splitStyle = false; if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) { splitStyle = true; while (numLetters < ext2.Len()) { if (ext2[ext2.Len() - numLetters - 1] != 'a') break; numLetters++; } } else if (ext2.Len() >= 2 && ( StringsAreEqual_Ascii(ext2.RightPtr(2), "01") || StringsAreEqual_Ascii(ext2.RightPtr(2), "00") )) { while (numLetters < ext2.Len()) { if (ext2[ext2.Len() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext2.Len()) return S_FALSE; } else return S_FALSE; seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); seqName._changedPart = ext.RightPtr(numLetters); seqName._splitStyle = splitStyle; if (prefix.Len() < 1) _subName = "file"; else _subName.SetFrom(prefix, prefix.Len() - 1); UInt64 size; { /* NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidSize, &prop)) if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; */ } RINOK(InStream_AtBegin_GetSize(stream, size)) _totalSize += size; _sizes.Add(size); _streams.Add(stream); { const UInt64 numFiles = _streams.Size(); RINOK(callback->SetCompleted(&numFiles, NULL)) } for (;;) { UString fullName; if (!seqName.GetNextName(fullName)) break; CMyComPtr nextStream; const HRESULT result = volumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!nextStream) break; RINOK(InStream_AtBegin_GetSize(nextStream, size)) _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); { const UInt64 numFiles = _streams.Size(); RINOK(callback->SetCompleted(&numFiles, NULL)) } } if (_streams.Size() == 1) { if (splitStyle) return S_FALSE; } return S_OK; } Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)) { COM_TRY_BEGIN const HRESULT res = Open2(stream, callback); if (res != S_OK) Close(); return res; COM_TRY_END } Z7_COM7F_IMF(CHandler::Close()) { _totalSize = 0; _subName.Empty(); _streams.Clear(); _sizes.Clear(); return S_OK; } Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; default: break; } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) { COM_TRY_BEGIN if (numItems == 0) return S_OK; if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; UInt64 currentTotalSize = 0; RINOK(extractCallback->SetTotal(_totalSize)) CMyComPtr outStream; const Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &outStream, askMode)) if (!testMode && !outStream) return S_OK; RINOK(extractCallback->PrepareOperation(askMode)) NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(extractCallback, false); for (unsigned i = 0;; i++) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()) if (i == _streams.Size()) break; IInStream *inStream = _streams[i]; RINOK(InStream_SeekToBegin(inStream)) RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) currentTotalSize += copyCoderSpec->TotalSize; } outStream.Release(); return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); COM_TRY_END } Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) { COM_TRY_BEGIN if (index != 0) return E_INVALIDARG; *stream = NULL; CMultiStream *streamSpec = new CMultiStream; CMyComPtr streamTemp = streamSpec; FOR_VECTOR (i, _streams) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; COM_TRY_END } REGISTER_ARC_I_NO_SIG( "Split", "001", NULL, 0xEA, 0, 0, NULL) }} tmp41wklro_/CPP/7zip/Archive/StdAfx.h0000444000175000001440000000035614360505460020406 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Archive/XzHandler.cpp0000444000175000001440000010407314601264720021447 0ustar nabijaczleweliusers// XzHandler.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../../Common/ComTry.h" #include "../../Common/Defs.h" #include "../../Common/IntToString.h" #include "../../Common/MyBuffer.h" #include "../../Common/StringToInt.h" #include "../../Windows/PropVariant.h" #include "../../Windows/System.h" #include "../Common/CWrappers.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" #include "../Compress/XzDecoder.h" #include "../Compress/XzEncoder.h" #include "IArchive.h" #include "Common/HandlerOut.h" using namespace NWindows; namespace NArchive { namespace NXz { #define k_LZMA2_Name "LZMA2" struct CBlockInfo { unsigned StreamFlags; UInt64 PackPos; UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros UInt64 UnpackPos; }; Z7_class_CHandler_final: public IInArchive, public IArchiveOpenSeq, public IInArchiveGetStream, public ISetProperties, #ifndef Z7_EXTRACT_ONLY public IOutArchive, #endif public CMyUnknownImp, #ifndef Z7_EXTRACT_ONLY public CMultiMethodProps #else public CCommonMethodProps #endif { Z7_COM_QI_BEGIN2(IInArchive) Z7_COM_QI_ENTRY(IArchiveOpenSeq) Z7_COM_QI_ENTRY(IInArchiveGetStream) Z7_COM_QI_ENTRY(ISetProperties) #ifndef Z7_EXTRACT_ONLY Z7_COM_QI_ENTRY(IOutArchive) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IInArchive) Z7_IFACE_COM7_IMP(IArchiveOpenSeq) Z7_IFACE_COM7_IMP(IInArchiveGetStream) Z7_IFACE_COM7_IMP(ISetProperties) #ifndef Z7_EXTRACT_ONLY Z7_IFACE_COM7_IMP(IOutArchive) #endif bool _stat_defined; bool _stat2_defined; bool _isArc; bool _needSeekToStart; bool _firstBlockWasRead; SRes _stat2_decode_SRes; CXzStatInfo _stat; // it's stat from backward parsing CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called const CXzStatInfo *GetStat() const { if (_stat_defined) return &_stat; if (_stat2_defined) return &_stat2; return NULL; } AString _methodsString; #ifndef Z7_EXTRACT_ONLY UInt32 _filterId; UInt64 _numSolidBytes; void InitXz() { _filterId = 0; _numSolidBytes = XZ_PROPS_BLOCK_SIZE_AUTO; } #endif void Init() { #ifndef Z7_EXTRACT_ONLY InitXz(); CMultiMethodProps::Init(); #else CCommonMethodProps::InitCommon(); #endif } HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); HRESULT Decode(NCompress::NXz::CDecoder &decoder, ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { #ifndef Z7_ST decoder._numThreads = _numThreads; #endif decoder._memUsage = _memUsage_Decompress; const HRESULT hres = decoder.Decode(seqInStream, outStream, NULL, // *outSizeLimit true, // finishStream progress); if (decoder.MainDecodeSRes_wasUsed && decoder.MainDecodeSRes != SZ_ERROR_MEM && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) { // if (!_stat2_defined) { _stat2_decode_SRes = decoder.MainDecodeSRes; _stat2 = decoder.Stat; _stat2_defined = true; } } if (hres == S_OK && progress) { // RINOK( progress->SetRatioInfo(&decoder.Stat.InSize, &decoder.Stat.OutSize); } return hres; } public: CBlockInfo *_blocks; size_t _blocksArraySize; UInt64 _maxBlocksSize; CMyComPtr _stream; CMyComPtr _seqStream; CXzBlock _firstBlock; CHandler(); ~CHandler(); HRESULT SeekToPackPos(UInt64 pos) { return InStream_SeekSet(_stream, pos); } }; CHandler::CHandler(): _blocks(NULL), _blocksArraySize(0) { #ifndef Z7_EXTRACT_ONLY InitXz(); #endif } CHandler::~CHandler() { MyFree(_blocks); } static const Byte kProps[] = { kpidSize, kpidPackSize, kpidMethod }; static const Byte kArcProps[] = { kpidMethod, kpidNumStreams, kpidNumBlocks, kpidClusterSize, kpidCharacts }; IMP_IInArchive_Props IMP_IInArchive_ArcProps static void Lzma2PropToString(AString &s, unsigned prop) { char c = 0; UInt32 size; if ((prop & 1) == 0) size = prop / 2 + 12; else { c = 'k'; size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); if (prop > 17) { size >>= 10; c = 'm'; } } s.Add_UInt32(size); if (c != 0) s.Add_Char(c); } struct CMethodNamePair { UInt32 Id; const char *Name; }; static const CMethodNamePair g_NamePairs[] = { { XZ_ID_Subblock, "SB" }, { XZ_ID_Delta, "Delta" }, { XZ_ID_X86, "BCJ" }, { XZ_ID_PPC, "PPC" }, { XZ_ID_IA64, "IA64" }, { XZ_ID_ARM, "ARM" }, { XZ_ID_ARMT, "ARMT" }, { XZ_ID_SPARC, "SPARC" }, { XZ_ID_ARM64, "ARM64" }, { XZ_ID_RISCV, "RISCV" }, { XZ_ID_LZMA2, "LZMA2" } }; static void AddMethodString(AString &s, const CXzFilter &f) { const char *p = NULL; for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++) if (g_NamePairs[i].Id == f.id) { p = g_NamePairs[i].Name; break; } char temp[32]; if (!p) { ::ConvertUInt64ToString(f.id, temp); p = temp; } s += p; if (f.propsSize > 0) { s.Add_Colon(); if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) Lzma2PropToString(s, f.props[0]); else if (f.id == XZ_ID_Delta && f.propsSize == 1) s.Add_UInt32((UInt32)f.props[0] + 1); else if (f.id == XZ_ID_ARM64 && f.propsSize == 1) s.Add_UInt32((UInt32)f.props[0] + 16 + 2); else { s.Add_Char('['); for (UInt32 bi = 0; bi < f.propsSize; bi++) { const unsigned v = f.props[bi]; s.Add_Char(GET_HEX_CHAR_UPPER(v >> 4)); s.Add_Char(GET_HEX_CHAR_UPPER(v & 15)); } s.Add_Char(']'); } } } static const char * const kChecks[] = { "NoCheck" , "CRC32" , NULL , NULL , "CRC64" , NULL , NULL , NULL , NULL , NULL , "SHA256" , NULL , NULL , NULL , NULL , NULL }; static void AddCheckString(AString &s, const CXzs &xzs) { size_t i; UInt32 mask = 0; for (i = 0; i < xzs.num; i++) mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); for (i = 0; i <= XZ_CHECK_MASK; i++) if (((mask >> i) & 1) != 0) { s.Add_Space_if_NotEmpty(); if (kChecks[i]) s += kChecks[i]; else { s += "Check-"; s.Add_UInt32((UInt32)i); } } } Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN NCOM::CPropVariant prop; const CXzStatInfo *stat = GetStat(); switch (propID) { case kpidPhySize: if (stat) prop = stat->InSize; break; case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; case kpidCharacts: if (_firstBlockWasRead) { AString s; if (XzBlock_HasPackSize(&_firstBlock)) s.Add_OptSpaced("BlockPackSize"); if (XzBlock_HasUnpackSize(&_firstBlock)) s.Add_OptSpaced("BlockUnpackSize"); if (!s.IsEmpty()) prop = s; } break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; case kpidErrorFlags: { UInt32 v = 0; SRes sres = _stat2_decode_SRes; if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; if (v != 0) prop = v; break; } case kpidMainSubfile: { // debug only, comment it: // if (_blocks) prop = (UInt32)0; break; } default: break; } prop.Detach(value); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = 1; return S_OK; } Z7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN const CXzStatInfo *stat = GetStat(); NCOM::CPropVariant prop; switch (propID) { case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; case kpidPackSize: if (stat) prop = stat->InSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; default: break; } prop.Detach(value); return S_OK; COM_TRY_END } struct COpenCallbackWrap { ICompressProgress vt; IArchiveOpenCallback *OpenCallback; HRESULT Res; // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() void Init(IArchiveOpenCallback *progress); }; static SRes OpenCallbackProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 /* outSize */) { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(COpenCallbackWrap) if (p->OpenCallback) p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) { vt.Progress = OpenCallbackProgress; OpenCallback = callback; Res = SZ_OK; } struct CXzsCPP { CXzs p; CXzsCPP() { Xzs_Construct(&p); } ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; #define kInputBufSize ((size_t)1 << 10) struct CLookToRead2_CPP: public CLookToRead2 { CLookToRead2_CPP() { buf = NULL; LookToRead2_CreateVTable(this, True // Lookahead ? ); } void Alloc(size_t allocSize) { buf = (Byte *)MyAlloc(allocSize); if (buf) this->bufSize = allocSize; } ~CLookToRead2_CPP() { MyFree(buf); } }; static HRESULT SRes_to_Open_HRESULT(SRes res) { switch (res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PROGRESS: return E_ABORT; /* case SZ_ERROR_UNSUPPORTED: case SZ_ERROR_CRC: case SZ_ERROR_DATA: case SZ_ERROR_ARCHIVE: case SZ_ERROR_NO_ARCHIVE: return S_FALSE; */ default: break; } return S_FALSE; } HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) { _needSeekToStart = true; { CXzStreamFlags st; CSeqInStreamWrap inStreamWrap; inStreamWrap.Init(inStream); SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); if (inStreamWrap.Res != S_OK) return inStreamWrap.Res; if (res != SZ_OK) return SRes_to_Open_HRESULT(res); { CXzBlock block; BoolInt isIndex; UInt32 headerSizeRes; SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); if (inStreamWrap.Res != S_OK) return inStreamWrap.Res; if (res2 != SZ_OK) { if (res2 == SZ_ERROR_INPUT_EOF) { _stat2_decode_SRes = res2; _stream = inStream; _seqStream = inStream; _isArc = true; return S_OK; } if (res2 == SZ_ERROR_ARCHIVE) return S_FALSE; } else if (!isIndex) { _firstBlockWasRead = true; _firstBlock = block; unsigned numFilters = XzBlock_GetNumFilters(&block); for (unsigned i = 0; i < numFilters; i++) { _methodsString.Add_Space_if_NotEmpty(); AddMethodString(_methodsString, block.filters[i]); } } } } RINOK(InStream_GetSize_SeekToEnd(inStream, _stat.InSize)) if (callback) { RINOK(callback->SetTotal(NULL, &_stat.InSize)) } CSeekInStreamWrap inStreamImp; inStreamImp.Init(inStream); CLookToRead2_CPP lookStream; lookStream.Alloc(kInputBufSize); if (!lookStream.buf) return E_OUTOFMEMORY; lookStream.realStream = &inStreamImp.vt; LookToRead2_INIT(&lookStream) COpenCallbackWrap openWrap; openWrap.Init(callback); CXzsCPP xzs; Int64 startPosition; SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc); if (res == SZ_ERROR_PROGRESS) return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; /* if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) res = SZ_OK; */ if (res == SZ_OK && startPosition == 0) { _stat_defined = true; _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); _stat.UnpackSize_Defined = true; _stat.NumStreams = xzs.p.num; _stat.NumStreams_Defined = true; _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); _stat.NumBlocks_Defined = true; AddCheckString(_methodsString, xzs.p); const size_t numBlocks = (size_t)_stat.NumBlocks + 1; const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo); if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1) { _blocks = (CBlockInfo *)MyAlloc(bytesAlloc); if (_blocks) { unsigned blockIndex = 0; UInt64 unpackPos = 0; for (size_t si = xzs.p.num; si != 0;) { si--; const CXzStream &str = xzs.p.streams[si]; UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE; for (size_t bi = 0; bi < str.numBlocks; bi++) { const CXzBlockSizes &bs = str.blocks[bi]; const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3); if (bs.unpackSize != 0) { if (blockIndex >= _stat.NumBlocks) return E_FAIL; CBlockInfo &block = _blocks[blockIndex++]; block.StreamFlags = str.flags; block.PackSize = bs.totalSize; // packSizeAligned; block.PackPos = packPos; block.UnpackPos = unpackPos; } packPos += packSizeAligned; unpackPos += bs.unpackSize; if (_maxBlocksSize < bs.unpackSize) _maxBlocksSize = bs.unpackSize; } } /* if (blockIndex != _stat.NumBlocks) { // there are Empty blocks; } */ if (_stat.OutSize != unpackPos) return E_FAIL; CBlockInfo &block = _blocks[blockIndex++]; block.StreamFlags = 0; block.PackSize = 0; block.PackPos = 0; block.UnpackPos = unpackPos; _blocksArraySize = blockIndex; } } } else { res = SZ_OK; } RINOK(SRes_to_Open_HRESULT(res)) _stream = inStream; _seqStream = inStream; _isArc = true; return S_OK; } Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)) { COM_TRY_BEGIN { Close(); return Open2(inStream, callback); } COM_TRY_END } Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream)) { Close(); _seqStream = stream; _isArc = true; _needSeekToStart = false; return S_OK; } Z7_COM7F_IMF(CHandler::Close()) { XzStatInfo_Clear(&_stat); XzStatInfo_Clear(&_stat2); _stat_defined = false; _stat2_defined = false; _stat2_decode_SRes = SZ_OK; _isArc = false; _needSeekToStart = false; _firstBlockWasRead = false; _methodsString.Empty(); _stream.Release(); _seqStream.Release(); MyFree(_blocks); _blocks = NULL; _blocksArraySize = 0; _maxBlocksSize = 0; return S_OK; } struct CXzUnpackerCPP2 { Byte *InBuf; // Byte *OutBuf; CXzUnpacker p; CXzUnpackerCPP2(); ~CXzUnpackerCPP2(); }; CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL) // , OutBuf(NULL) { XzUnpacker_Construct(&p, &g_Alloc); } CXzUnpackerCPP2::~CXzUnpackerCPP2() { XzUnpacker_Free(&p); MidFree(InBuf); // MidFree(OutBuf); } Z7_CLASS_IMP_IInStream( CInStream ) UInt64 _virtPos; public: UInt64 Size; UInt64 _cacheStartPos; size_t _cacheSize; CByteBuffer _cache; // UInt64 _startPos; CXzUnpackerCPP2 xz; void InitAndSeek() { _virtPos = 0; _cacheStartPos = 0; _cacheSize = 0; // _startPos = startPos; } CMyComPtr2 _handlerSpec; // ~CInStream(); }; /* CInStream::~CInStream() { // _cache.Free(); } */ static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) { size_t left = 0, right = numBlocks; for (;;) { size_t mid = (left + right) / 2; if (mid == left) return left; if (pos < blocks[mid].UnpackPos) right = mid; else left = mid; } } static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu, ISequentialInStream *seqInStream, unsigned streamFlags, UInt64 packSize, // pure size from Index record, it doesn't include pad zeros size_t unpackSize, Byte *dest // , ICompressProgressInfo *progress ) { const size_t kInBufSize = (size_t)1 << 16; XzUnpacker_Init(&xzu.p); if (!xzu.InBuf) { xzu.InBuf = (Byte *)MidAlloc(kInBufSize); if (!xzu.InBuf) return E_OUTOFMEMORY; } xzu.p.streamFlags = (UInt16)streamFlags; XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p); XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize); const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); UInt64 packRem = packSizeAligned; UInt32 inSize = 0; SizeT inPos = 0; SizeT outPos = 0; HRESULT readRes = S_OK; for (;;) { if (inPos == inSize && readRes == S_OK) { inPos = 0; inSize = 0; UInt32 rem = kInBufSize; if (rem > packRem) rem = (UInt32)packRem; if (rem != 0) readRes = seqInStream->Read(xzu.InBuf, rem, &inSize); } SizeT inLen = inSize - inPos; SizeT outLen = unpackSize - outPos; ECoderStatus status; const SRes res = XzUnpacker_Code(&xzu.p, // dest + outPos, NULL, &outLen, xzu.InBuf + inPos, &inLen, (inLen == 0), // srcFinished CODER_FINISH_END, &status); // return E_OUTOFMEMORY; // res = SZ_ERROR_CRC; if (res != SZ_OK) { if (res == SZ_ERROR_CRC) return S_FALSE; return SResToHRESULT(res); } inPos += inLen; outPos += outLen; packRem -= inLen; const BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p); if ((inLen == 0 && outLen == 0) || blockFinished) { if (packRem != 0 || !blockFinished || unpackSize != outPos) return S_FALSE; if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize) return S_FALSE; return S_OK; } } } Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { COM_TRY_BEGIN if (processedSize) *processedSize = 0; if (size == 0) return S_OK; { if (_virtPos >= Size) return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; { UInt64 rem = Size - _virtPos; if (size > rem) size = (UInt32)rem; } } if (size == 0) return S_OK; if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize) { const size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos); const CBlockInfo &block = _handlerSpec->_blocks[bi]; const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos; if (_cache.Size() < unpackSize) return E_FAIL; _cacheSize = 0; RINOK(_handlerSpec->SeekToPackPos(block.PackPos)) RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize, (size_t)unpackSize, _cache)) _cacheStartPos = block.UnpackPos; _cacheSize = (size_t)unpackSize; } { const size_t offset = (size_t)(_virtPos - _cacheStartPos); const size_t rem = _cacheSize - offset; if (size > rem) size = (UInt32)rem; memcpy(data, _cache.ConstData() + offset, size); _virtPos += size; if (processedSize) *processedSize = size; return S_OK; } COM_TRY_END } Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += Size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40; Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) { COM_TRY_BEGIN *stream = NULL; if (index != 0) return E_INVALIDARG; if (!_stat.UnpackSize_Defined || _maxBlocksSize == 0 // 18.02 || _maxBlocksSize > kMaxBlockSize_for_GetStream || _maxBlocksSize != (size_t)_maxBlocksSize) return S_FALSE; UInt64 memSize; if (!NSystem::GetRamSize(memSize)) memSize = (UInt64)(sizeof(size_t)) << 28; { if (_maxBlocksSize > memSize / 4) return S_FALSE; } CMyComPtr2 spec; spec.Create_if_Empty(); spec->_cache.Alloc((size_t)_maxBlocksSize); spec->_handlerSpec.SetFromCls(this); // spec->_handler = (IInArchive *)this; spec->Size = _stat.OutSize; spec->InitAndSeek(); *stream = spec.Detach(); return S_OK; COM_TRY_END } static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) { Int32 opRes; SRes sres = decoder.MainDecodeSRes; if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) opRes = NExtract::NOperationResult::kIsNotArc; else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) opRes = NExtract::NOperationResult::kUnexpectedEnd; else if (decoder.Stat.DataAfterEnd) opRes = NExtract::NOperationResult::kDataAfterEnd; else if (sres == SZ_ERROR_CRC) // (CrcError) opRes = NExtract::NOperationResult::kCRCError; else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported) opRes = NExtract::NOperationResult::kUnsupportedMethod; else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError) opRes = NExtract::NOperationResult::kDataError; else if (sres == SZ_ERROR_DATA) // (DataError) opRes = NExtract::NOperationResult::kDataError; else if (sres != SZ_OK) opRes = NExtract::NOperationResult::kDataError; else opRes = NExtract::NOperationResult::kOK; return opRes; } Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) { COM_TRY_BEGIN if (numItems == 0) return S_OK; if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; const CXzStatInfo *stat = GetStat(); if (stat) RINOK(extractCallback->SetTotal(stat->InSize)) UInt64 currentTotalPacked = 0; RINOK(extractCallback->SetCompleted(¤tTotalPacked)) Int32 opRes; { CMyComPtr realOutStream; const Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) if (!testMode && !realOutStream) return S_OK; RINOK(extractCallback->PrepareOperation(askMode)) CMyComPtr2_Create lps; lps->Init(extractCallback, true); if (_needSeekToStart) { if (!_stream) return E_FAIL; RINOK(InStream_SeekToBegin(_stream)) } else _needSeekToStart = true; NCompress::NXz::CDecoder decoder; const HRESULT hres = Decode(decoder, _seqStream, realOutStream, lps); if (!decoder.MainDecodeSRes_wasUsed) return hres == S_OK ? E_FAIL : hres; opRes = Get_Extract_OperationResult(decoder); if (opRes == NExtract::NOperationResult::kOK && hres != S_OK) opRes = NExtract::NOperationResult::kDataError; // realOutStream.Release(); } return extractCallback->SetOperationResult(opRes); COM_TRY_END } #ifndef Z7_EXTRACT_ONLY Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType)) { *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType; // *timeType = NFileTimeType::kUnix; return S_OK; } Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback)) { COM_TRY_BEGIN if (numItems == 0) { CSeqOutStreamWrap seqOutStream; seqOutStream.Init(outStream); SRes res = Xz_EncodeEmpty(&seqOutStream.vt); return SResToHRESULT(res); } if (numItems != 1) return E_INVALIDARG; { Z7_DECL_CMyComPtr_QI_FROM( IStreamSetRestriction, setRestriction, outStream) if (setRestriction) RINOK(setRestriction->SetRestriction(0, 0)) } Int32 newData, newProps; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)) if (IntToBool(newProps)) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)) if (prop.vt != VT_EMPTY) if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } if (IntToBool(newData)) { UInt64 dataSize; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidSize, &prop)) if (prop.vt != VT_UI8) return E_INVALIDARG; dataSize = prop.uhVal.QuadPart; } CMyComPtr2_Create encoder; CXzProps &xzProps = encoder->xzProps; CLzma2EncProps &lzma2Props = xzProps.lzma2Props; lzma2Props.lzmaProps.level = GetLevel(); xzProps.reduceSize = dataSize; /* { NCOM::CPropVariant prop = (UInt64)dataSize; RINOK(encoder->SetCoderProp(NCoderPropID::kReduceSize, prop)) } */ #ifndef Z7_ST UInt32 numThreads = _numThreads; const UInt32 kNumThreads_Max = 1024; if (numThreads > kNumThreads_Max) numThreads = kNumThreads_Max; if (!_numThreads_WasForced && _numThreads >= 1 && _memUsage_WasSet) { COneMethodInfo oneMethodInfo; if (!_methods.IsEmpty()) oneMethodInfo = _methods[0]; SetGlobalLevelTo(oneMethodInfo); const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); if (!numThreads_WasSpecifiedInMethod) { // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads); } UInt64 cs = _numSolidBytes; if (cs != XZ_PROPS_BLOCK_SIZE_AUTO) oneMethodInfo.AddProp_BlockSize2(cs); cs = oneMethodInfo.Get_Xz_BlockSize(); if (cs != XZ_PROPS_BLOCK_SIZE_AUTO && cs != XZ_PROPS_BLOCK_SIZE_SOLID) { const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); const UInt32 numBlockThreads_Original = numThreads / lzmaThreads; if (numBlockThreads_Original > 1) { UInt32 numBlockThreads = numBlockThreads_Original; { const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); for (; numBlockThreads > 1; numBlockThreads--) { UInt64 size = numBlockThreads * (lzmaMemUsage + cs); UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; if (cs < ((UInt32)1 << 26)) numPackChunks++; if (cs < ((UInt32)1 << 24)) numPackChunks++; if (cs < ((UInt32)1 << 22)) numPackChunks++; size += numPackChunks * cs; // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20)); if (size <= _memUsage_Compress) break; } } if (numBlockThreads == 0) numBlockThreads = 1; if (numBlockThreads != numBlockThreads_Original) numThreads = numBlockThreads * lzmaThreads; } } } xzProps.numTotalThreads = (int)numThreads; #endif // Z7_ST xzProps.blockSize = _numSolidBytes; if (_numSolidBytes == XZ_PROPS_BLOCK_SIZE_SOLID) { xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; } RINOK(encoder->SetCheckSize(_crcSize)) { CXzFilterProps &filter = xzProps.filterProps; if (_filterId == XZ_ID_Delta) { bool deltaDefined = false; FOR_VECTOR (j, _filterMethod.Props) { const CProp &prop = _filterMethod.Props[j]; if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) { UInt32 delta = (UInt32)prop.Value.ulVal; if (delta < 1 || delta > 256) return E_INVALIDARG; filter.delta = delta; deltaDefined = true; } else return E_INVALIDARG; } if (!deltaDefined) return E_INVALIDARG; } filter.id = _filterId; } FOR_VECTOR (i, _methods) { COneMethodInfo &m = _methods[i]; FOR_VECTOR (j, m.Props) { const CProp &prop = m.Props[j]; RINOK(encoder->SetCoderProp(prop.Id, prop.Value)) } } { CMyComPtr fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)) if (!fileInStream) return S_FALSE; { CMyComPtr streamGetSize; fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize); if (streamGetSize) { UInt64 size; if (streamGetSize->GetSize(&size) == S_OK) dataSize = size; } } RINOK(updateCallback->SetTotal(dataSize)) CMyComPtr2_Create lps; lps->Init(updateCallback, true); RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps)) } return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } if (indexInArchive != 0) return E_INVALIDARG; Z7_DECL_CMyComPtr_QI_FROM( IArchiveUpdateCallbackFile, opCallback, updateCallback) if (opCallback) { RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) } if (_stream) { const CXzStatInfo *stat = GetStat(); if (stat) { RINOK(updateCallback->SetTotal(stat->InSize)) } RINOK(InStream_SeekToBegin(_stream)) } CMyComPtr2_Create lps; lps->Init(updateCallback, true); return NCompress::CopyStream(_stream, outStream, lps); COM_TRY_END } #endif HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; #ifndef Z7_EXTRACT_ONLY if (name[0] == L's') { const wchar_t *s = name.Ptr(1); if (*s == 0) { bool useStr = false; bool isSolid; switch (value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (!StringToBool(value.bstrVal, isSolid)) useStr = true; break; default: return E_INVALIDARG; } if (!useStr) { _numSolidBytes = (isSolid ? XZ_PROPS_BLOCK_SIZE_SOLID : XZ_PROPS_BLOCK_SIZE_AUTO); return S_OK; } } return ParseSizeString(s, value, 0, // percentsBase _numSolidBytes) ? S_OK: E_INVALIDARG; } return CMultiMethodProps::SetProperty(name, value); #else { HRESULT hres; if (SetCommonProperty(name, value, hres)) return hres; } return E_INVALIDARG; #endif } Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) { COM_TRY_BEGIN Init(); for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])) } #ifndef Z7_EXTRACT_ONLY if (!_filterMethod.MethodName.IsEmpty()) { unsigned k; for (k = 0; k < Z7_ARRAY_SIZE(g_NamePairs); k++) { const CMethodNamePair &pair = g_NamePairs[k]; if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) { _filterId = pair.Id; break; } } if (k == Z7_ARRAY_SIZE(g_NamePairs)) return E_INVALIDARG; } _methods.DeleteFrontal(GetNumEmptyMethods()); if (_methods.Size() > 1) return E_INVALIDARG; if (_methods.Size() == 1) { AString &methodName = _methods[0].MethodName; if (methodName.IsEmpty()) methodName = k_LZMA2_Name; else if ( !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name) && !methodName.IsEqualTo_Ascii_NoCase("xz")) return E_INVALIDARG; } #endif return S_OK; COM_TRY_END } REGISTER_ARC_IO( "xz", "xz txz", "* .tar", 0xC, XZ_SIG, 0 , NArcInfoFlags::kKeepName , 0 , NULL) }} tmp41wklro_/CPP/7zip/Archive/XzHandler.h0000444000175000001440000000021214357314620021105 0ustar nabijaczleweliusers// XzHandler.h #ifndef ZIP7_INC_XZ_HANDLER_H #define ZIP7_INC_XZ_HANDLER_H namespace NArchive { namespace NXz { }} #endif tmp41wklro_/CPP/7zip/Asm.mak0000444000175000001440000000052214570034600016664 0ustar nabijaczleweliusers!IFDEF ASM_OBJS !IF "$(PLATFORM)" == "arm64" $(ASM_OBJS): ../../../../Asm/arm64/$(*B).S $(COMPL_ASM_CLANG) !ELSEIF "$(PLATFORM)" == "arm" $(ASM_OBJS): ../../../../Asm/arm/$(*B).asm $(COMPL_ASM) !ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" $(ASM_OBJS): ../../../../Asm/x86/$(*B).asm $(COMPL_ASM) !ENDIF !ENDIF tmp41wklro_/CPP/7zip/Bundles/0000700000175000001440000000000014706260545017051 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/Alone7z/0000700000175000001440000000000014706260545020370 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/Alone7z/Alone.dsp0000444000175000001440000012573114555143020022145 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\BenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\BenchCon.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\HashCon.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\HashCon.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # ADD CPP /D "PROG_VARIANT_R" # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common0.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CrcReg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynLimBuf.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\DynLimBuf.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\LzFindPrepare.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer2.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyLinux.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyTypes.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\MyVersion.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Sha256Prepare.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # Begin Source File SOURCE=..\..\..\Common\XzCrc64Init.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\XzCrc64Reg.cpp # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileLink.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileMapping.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileSystem.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileSystem.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\NtCheck.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Registry.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Registry.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\SecurityUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\SystemInfo.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\SystemInfo.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\MultiOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MultiOutStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\UniqBlocks.cpp # End Source File # Begin Source File SOURCE=..\..\Common\UniqBlocks.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\DeltaFilter.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Encoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Encoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\XzDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\XzDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\XzEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\XzEncoder.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File SOURCE=..\..\Archive\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\XzHandler.cpp # End Source File # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Bench.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Bench.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DirItem.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExitCode.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\HashCalc.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\HashCalc.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "Xz" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Xz.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Xz.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzCrc64.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzCrc64.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzCrc64Opt.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzEnc.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\XzIn.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrcOpt.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zStream.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zVersion.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\AesOpt.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2Enc.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindOpt.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Enc.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Enc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtCoder.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtCoder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Precomp.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256Opt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\SwapBytes.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\SwapBytes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "Crypto" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Crypto\7zAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAes.h # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.h # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAesReg.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\RandGen.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\RandGen.h # End Source File # End Group # End Target # End Project tmp41wklro_/CPP/7zip/Bundles/Alone7z/Alone.dsw0000444000175000001440000000102507344465546022163 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/Bundles/Alone7z/makefile0000444000175000001440000000661714570034600022100 0ustar nabijaczleweliusersPROG = 7zr.exe # USE_C_AES = 1 # USE_C_SHA = 1 # USE_C_CRC64 = 1 # USE_C_CRC = 1 # NO_ASM_GNU=1 # NO_ASM=1 CFLAGS = $(CFLAGS) -DZ7_PROG_VARIANT_R # CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_R COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\CrcReg.obj \ $O\DynLimBuf.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\LzFindPrepare.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\Sha256Reg.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ $O\XzCrc64Init.obj \ $O\XzCrc64Reg.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileLink.obj \ $O\FileName.obj \ $O\FileSystem.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\Registry.obj \ $O\System.obj \ $O\SystemInfo.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\MultiOutStream.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\UniqBlocks.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\LzmaHandler.obj \ $O\SplitHandler.obj \ $O\XzHandler.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Encoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ $O\XzDecoder.obj \ $O\XzEncoder.obj \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ $O\RandGen.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\MtCoder.obj \ $O\MtDec.obj \ $O\Sort.obj \ $O\SwapBytes.obj \ $O\Threads.obj \ $O\Xz.obj \ $O\XzDec.obj \ $O\XzEnc.obj \ $O\XzIn.obj \ !include "../../UI/Console/Console.mak" !include "../../Aes.mak" !include "../../Crc.mak" !include "../../Crc64.mak" !include "../../LzFindOpt.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/Alone7z/makefile.gcc0000444000175000001440000001117614555224200022627 0ustar nabijaczleweliusersPROG = 7zr CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_R # IS_X64 = 1 # USE_ASM = 1 # ST_MODE = 1 ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif include ../../LzmaDec_gcc.mak LOCAL_FLAGS_ST = MT_OBJS = ifdef ST_MODE LOCAL_FLAGS_ST = -DZ7_ST ifdef IS_MINGW MT_OBJS = \ $O/Threads.o \ endif else MT_OBJS = \ $O/LzFindMt.o \ $O/LzFindOpt.o \ $O/Threads.o \ $O/StreamBinder.o \ $O/VirtThread.o \ endif LOCAL_FLAGS_SYS = ifdef IS_MINGW LOCAL_FLAGS_SYS = \ -DZ7_DEVICE_FILE \ # -DZ7_LARGE_PAGES \ # -DZ7_LONG_PATH \ SYS_OBJS = \ $O/FileSystem.o \ $O/Registry.o \ $O/MemoryLock.o \ $O/DLL.o \ $O/DllSecur.o \ $O/resource.o \ else SYS_OBJS = \ $O/MyWindows.o \ endif LOCAL_FLAGS = \ $(LOCAL_FLAGS_ST) \ $(LOCAL_FLAGS_SYS) \ CONSOLE_OBJS = \ $O/BenchCon.o \ $O/ConsoleClose.o \ $O/ExtractCallbackConsole.o \ $O/HashCon.o \ $O/List.o \ $O/Main.o \ $O/MainAr.o \ $O/OpenCallbackConsole.o \ $O/PercentPrinter.o \ $O/UpdateCallbackConsole.o \ $O/UserInputUtils.o \ UI_COMMON_OBJS = \ $O/ArchiveCommandLine.o \ $O/ArchiveExtractCallback.o \ $O/ArchiveOpenCallback.o \ $O/Bench.o \ $O/DefaultName.o \ $O/EnumDirItems.o \ $O/Extract.o \ $O/ExtractingFilePath.o \ $O/HashCalc.o \ $O/LoadCodecs.o \ $O/OpenArchive.o \ $O/PropIDUtils.o \ $O/SetProperties.o \ $O/SortUtils.o \ $O/TempFiles.o \ $O/Update.o \ $O/UpdateAction.o \ $O/UpdateCallback.o \ $O/UpdatePair.o \ $O/UpdateProduce.o \ COMMON_OBJS = \ $O/CommandLineParser.o \ $O/CRC.o \ $O/CrcReg.o \ $O/DynLimBuf.o \ $O/IntToString.o \ $O/ListFileUtils.o \ $O/LzFindPrepare.o \ $O/MyString.o \ $O/MyVector.o \ $O/NewHandler.o \ $O/Sha256Prepare.o \ $O/Sha256Reg.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/StringConvert.o \ $O/StringToInt.o \ $O/UTFConvert.o \ $O/Wildcard.o \ $O/XzCrc64Init.o \ $O/XzCrc64Reg.o \ WIN_OBJS = \ $O/ErrorMsg.o \ $O/FileDir.o \ $O/FileFind.o \ $O/FileIO.o \ $O/FileLink.o \ $O/FileName.o \ $O/PropVariant.o \ $O/PropVariantConv.o \ $O/System.o \ $O/SystemInfo.o \ $O/TimeUtils.o \ 7ZIP_COMMON_OBJS = \ $O/CreateCoder.o \ $O/CWrappers.o \ $O/FilePathAutoRename.o \ $O/FileStreams.o \ $O/InBuffer.o \ $O/InOutTempBuffer.o \ $O/FilterCoder.o \ $O/LimitedStreams.o \ $O/MethodId.o \ $O/MethodProps.o \ $O/MultiOutStream.o \ $O/OffsetStream.o \ $O/OutBuffer.o \ $O/ProgressUtils.o \ $O/PropId.o \ $O/StreamObjects.o \ $O/StreamUtils.o \ $O/UniqBlocks.o \ AR_OBJS = \ $O/LzmaHandler.o \ $O/SplitHandler.o \ $O/XzHandler.o \ AR_COMMON_OBJS = \ $O/CoderMixer2.o \ $O/DummyOutStream.o \ $O/HandlerOut.o \ $O/InStreamWithCRC.o \ $O/ItemNameUtils.o \ $O/MultiStream.o \ $O/OutStreamWithCRC.o \ $O/ParseProperties.o \ 7Z_OBJS = \ $O/7zCompressionMode.o \ $O/7zDecode.o \ $O/7zEncode.o \ $O/7zExtract.o \ $O/7zFolderInStream.o \ $O/7zHandler.o \ $O/7zHandlerOut.o \ $O/7zHeader.o \ $O/7zIn.o \ $O/7zOut.o \ $O/7zProperties.o \ $O/7zRegister.o \ $O/7zSpecStream.o \ $O/7zUpdate.o \ COMPRESS_OBJS = \ $O/Bcj2Coder.o \ $O/Bcj2Register.o \ $O/BcjCoder.o \ $O/BcjRegister.o \ $O/BranchMisc.o \ $O/BranchRegister.o \ $O/ByteSwap.o \ $O/CopyCoder.o \ $O/CopyRegister.o \ $O/DeltaFilter.o \ $O/Lzma2Decoder.o \ $O/Lzma2Encoder.o \ $O/Lzma2Register.o \ $O/LzmaDecoder.o \ $O/LzmaEncoder.o \ $O/LzmaRegister.o \ $O/XzDecoder.o \ $O/XzEncoder.o \ CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ $O/MyAes.o \ $O/MyAesReg.o \ $O/RandGen.o \ C_OBJS = \ $O/7zCrc.o \ $O/7zCrcOpt.o \ $O/7zStream.o \ $O/Aes.o \ $O/AesOpt.o \ $O/Alloc.o \ $O/Bcj2.o \ $O/Bcj2Enc.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ $O/CpuArch.o \ $O/Delta.o \ $O/LzFind.o \ $O/Lzma2Dec.o \ $O/Lzma2DecMt.o \ $O/Lzma2Enc.o \ $O/LzmaDec.o \ $O/LzmaEnc.o \ $O/MtCoder.o \ $O/MtDec.o \ $O/Sha256.o \ $O/Sha256Opt.o \ $O/SwapBytes.o \ $O/Xz.o \ $O/XzDec.o \ $O/XzEnc.o \ $O/XzIn.o \ $O/XzCrc64.o \ $O/XzCrc64Opt.o \ OBJS = \ $(LZMA_DEC_OPT_OBJS) \ $(C_OBJS) \ $(MT_OBJS) \ $(SYS_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(COMPRESS_OBJS) \ $(CRYPTO_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(UI_COMMON_OBJS) \ $(CONSOLE_OBJS) \ include ../../7zip_gcc.mak tmp41wklro_/CPP/7zip/Bundles/Alone7z/resource.rc0000444000175000001440000000030113267314055022544 0ustar nabijaczleweliusers#include "../../../../C/7zVersion.rc" MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr") #ifndef UNDER_CE 1 24 MOVEABLE PURE "../../UI/Console/Console.manifest" #endif tmp41wklro_/CPP/7zip/Bundles/Alone7z/StdAfx.cpp0000444000175000001440000000004610144137330022260 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/Alone7z/StdAfx.h0000444000175000001440000000036114360505460021734 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Bundles/Format7zExtractR/0000700000175000001440000000000014706260545022237 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/Format7zExtractR/makefile0000444000175000001440000000362714405646640023757 0ustar nabijaczleweliusersPROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def CFLAGS = $(CFLAGS) \ -DZ7_EXTRACT_ONLY \ -DZ7_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\CrcReg.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\LzmaDec.obj \ $O\MtDec.obj \ $O\SwapBytes.obj \ $O\Threads.obj \ !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/Format7zExtractR/resource.rc0000444000175000001440000000023411553021575024416 0ustar nabijaczleweliusers#include "../../../../C/7zVersion.rc" MY_VERSION_INFO_DLL("7z Extracting Reduced Standalone Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" tmp41wklro_/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp0000444000175000001440000000004610144137330024127 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h0000444000175000001440000000036114360505460023603 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Bundles/Format7zR/0000700000175000001440000000000014706260545020704 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/Format7zR/makefile0000444000175000001440000000464514576504560022430 0ustar nabijaczleweliusersPROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def CFLAGS = $(CFLAGS) \ -DZ7_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\CrcReg.obj \ $O\IntToString.obj \ $O\LzFindPrepare.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\UniqBlocks.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Encoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\Lzma2Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\MtCoder.obj \ $O\MtDec.obj \ $O\SwapBytes.obj \ $O\Threads.obj \ !include "../../Crc.mak" !include "../../LzFindOpt.mak" !include "../../LzmaDec.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/Format7zR/resource.rc0000444000175000001440000000022011553021452023050 0ustar nabijaczleweliusers#include "../../../../C/7zVersion.rc" MY_VERSION_INFO_DLL("7z Reduced Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" tmp41wklro_/CPP/7zip/Bundles/Format7zR/StdAfx.cpp0000444000175000001440000000004610144137330022574 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/Format7zR/StdAfx.h0000444000175000001440000000036114360505460022250 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Bundles/LzmaCon/0000700000175000001440000000000014706260545020414 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp0000444000175000001440000004575314533123000023006 0ustar nabijaczleweliusers // LzmaAlone.cpp #include "StdAfx.h" // #include #if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE) #include #include #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../../C/CpuArch.h" #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/Lzma86.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include "../../../Windows/NtCheck.h" #ifndef Z7_ST #include "../../../Windows/System.h" #endif #include "../../../Common/IntToString.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../../Compress/LzmaDecoder.h" #include "../../Compress/LzmaEncoder.h" #include "../../UI/Console/BenchCon.h" #include "../../UI/Console/ConsoleClose.h" extern bool g_LargePagesMode; bool g_LargePagesMode = false; using namespace NCommandLineParser; static const unsigned kDictSizeLog = 24; #define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n" static const char * const kHelpString = "Usage: lzma [inputFile] [outputFile] [...]\n" "\n" "\n" " e : Encode file\n" " d : Decode file\n" " b : Benchmark\n" "\n" " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n" " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n" " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n" " -mc{N} : set number of cycles for match finder\n" " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n" " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n" " -pb{N} : set number of pos bits : [0, 4] : default = 2\n" " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n" " -mt{N} : set number of CPU threads\n" " -eos : write end of stream marker\n" " -si : read data from stdin\n" " -so : write data to stdout\n"; static const char * const kCantAllocate = "Cannot allocate memory"; static const char * const kReadError = "Read error"; static const char * const kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMethod, kLevel, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } #define SWFRM_3(t, mu, mi) t, mu, mi, NULL #define SWFRM_1(t) SWFRM_3(t, false, 0) #define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) #define SWFRM_STRING SWFRM_1(NSwitchType::kString) #define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) static const CSwitchForm kSwitchForms[] = { { "?", SWFRM_SIMPLE }, { "H", SWFRM_SIMPLE }, { "MM", SWFRM_STRING_SINGL(1) }, { "X", SWFRM_STRING_SINGL(1) }, { "A", SWFRM_STRING_SINGL(1) }, { "D", SWFRM_STRING_SINGL(1) }, { "FB", SWFRM_STRING_SINGL(1) }, { "MC", SWFRM_STRING_SINGL(1) }, { "LC", SWFRM_STRING_SINGL(1) }, { "LP", SWFRM_STRING_SINGL(1) }, { "PB", SWFRM_STRING_SINGL(1) }, { "MF", SWFRM_STRING_SINGL(1) }, { "MT", SWFRM_STRING }, { "EOS", SWFRM_SIMPLE }, { "SI", SWFRM_SIMPLE }, { "SO", SWFRM_SIMPLE }, { "F86", NSwitchType::kChar, false, 0, "+" } }; static void Convert_UString_to_AString(const UString &s, AString &temp) { int codePage = CP_OEMCP; /* int g_CodePage = -1; int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, temp); else */ UnicodeStringToMultiByte2(temp, s, (UINT)codePage); } static void PrintErr(const char *s) { fputs(s, stderr); } static void PrintErr_LF(const char *s) { PrintErr(s); fputc('\n', stderr); } static void PrintError(const char *s) { PrintErr("\nERROR: "); PrintErr_LF(s); } static void PrintError2(const char *s1, const UString &s2) { PrintError(s1); AString a; Convert_UString_to_AString(s2, a); PrintErr_LF(a); } static void PrintError_int(const char *s, int code) { PrintError(s); char temp[32]; ConvertInt64ToString(code, temp); PrintErr("Error code = "); PrintErr_LF(temp); } static void Print(const char *s) { fputs(s, stdout); } static void Print_UInt64(UInt64 v) { char temp[32]; ConvertUInt64ToString(v, temp); Print(temp); } static void Print_MB(UInt64 v) { Print_UInt64(v); Print(" MiB"); } static void Print_Size(const char *s, UInt64 v) { Print(s); Print_UInt64(v); Print(" ("); Print_MB(v >> 20); Print(")\n"); } static void PrintTitle() { Print(kCopyrightString); } static void PrintHelp() { PrintTitle(); Print(kHelpString); } Z7_CLASS_IMP_COM_1( CProgressPrint, ICompressProgressInfo ) UInt64 _size1; UInt64 _size2; public: CProgressPrint(): _size1(0), _size2(0) {} void ClosePrint(); }; #define BACK_STR \ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" static const char * const kBackSpaces = BACK_STR " " BACK_STR; void CProgressPrint::ClosePrint() { Print(kBackSpaces); } Z7_COM7F_IMF(CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; if (inSize) { UInt64 v1 = *inSize >> 20; UInt64 v2 = _size2; if (outSize) v2 = *outSize >> 20; if (v1 != _size1 || v2 != _size2) { _size1 = v1; _size2 = v2; ClosePrint(); Print_MB(_size1); Print(" -> "); Print_MB(_size2); } } return S_OK; } Z7_ATTR_NORETURN static void IncorrectCommand() { throw "Incorrect command"; } static UInt32 GetNumber(const wchar_t *s) { const wchar_t *end; UInt32 v = ConvertStringToUInt32(s, &end); if (*end != 0) IncorrectCommand(); return v; } static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res) { if (parser[index].ThereIs) res = GetNumber(parser[index].PostStrings[0]); } static int Error_HRESULT(const char *s, HRESULT res) { if (res == E_ABORT) { Print("\n\nBreak signaled\n"); return 255; } PrintError(s); if (res == E_OUTOFMEMORY) { PrintErr_LF(kCantAllocate); return 8; } if (res == E_INVALIDARG) { PrintErr_LF("Ununsupported parameter"); } else { char temp[32]; ConvertUInt32ToHex((UInt32)res, temp); PrintErr("Error code = 0x"); PrintErr_LF(temp); } return 1; } #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; #endif static void AddProp(CObjectVector &props2, const char *name, const wchar_t *val) { CProperty &prop = props2.AddNew(); prop.Name = name; prop.Value = val; } static int main2(int numArgs, const char *args[]) { NT_CHECK if (numArgs == 1) { PrintHelp(); return 0; } /* bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8); if (unsupportedTypes) throw "Unsupported base types. Edit Common/Types.h and recompile"; */ UStringVector commandStrings; for (int i = 1; i < numArgs; i++) commandStrings.Add(MultiByteToUnicodeString(args[i])); CParser parser; try { if (!parser.ParseStrings(kSwitchForms, Z7_ARRAY_SIZE(kSwitchForms), commandStrings)) { PrintError2(parser.ErrorMessage, parser.ErrorLine); return 1; } } catch(...) { IncorrectCommand(); } if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; if (!stdOutMode) PrintTitle(); const UStringVector ¶ms = parser.NonSwitchStrings; unsigned paramIndex = 0; if (paramIndex >= params.Size()) IncorrectCommand(); const UString &command = params[paramIndex++]; CObjectVector props2; bool dictDefined = false; UInt32 dict = (UInt32)(Int32)-1; if (parser[NKey::kDict].ThereIs) { UInt32 dictLog; const UString &s = parser[NKey::kDict].PostStrings[0]; dictLog = GetNumber(s); dict = 1 << dictLog; dictDefined = true; AddProp(props2, "d", s); } if (parser[NKey::kLevel].ThereIs) { const UString &s = parser[NKey::kLevel].PostStrings[0]; /* UInt32 level = */ GetNumber(s); AddProp(props2, "x", s); } UString mf ("BT4"); if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)(Int32)-1; #ifndef Z7_ST if (parser[NKey::kMultiThread].ThereIs) { const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = NWindows::NSystem::GetNumberOfProcessors(); else numThreads = GetNumber(s); AddProp(props2, "mt", s); } #endif if (parser[NKey::kMethod].ThereIs) { const UString &s = parser[NKey::kMethod].PostStrings[0]; if (s.IsEmpty() || s[0] != '=') IncorrectCommand(); AddProp(props2, "m", s.Ptr(1)); } if (StringsAreEqualNoCase_Ascii(command, "b")) { UInt32 numIterations = 1; if (paramIndex < params.Size()) numIterations = GetNumber(params[paramIndex++]); if (params.Size() != paramIndex) IncorrectCommand(); HRESULT res = BenchCon(props2, numIterations, stdout); if (res == S_OK) return 0; return Error_HRESULT("Benchmark error", res); } { UInt32 needParams = 3; if (stdInMode) needParams--; if (stdOutMode) needParams--; if (needParams != params.Size()) IncorrectCommand(); } if (numThreads == (UInt32)(Int32)-1) numThreads = 1; bool encodeMode = false; if (StringsAreEqualNoCase_Ascii(command, "e")) encodeMode = true; else if (!StringsAreEqualNoCase_Ascii(command, "d")) IncorrectCommand(); CMyComPtr inStream; CInFileStream *inStreamSpec = NULL; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { const UString &inputName = params[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(us2fs(inputName))) { PrintError2("Cannot open input file", inputName); return 1; } } CMyComPtr outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { const UString &outputName = params[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create_ALWAYS(us2fs(outputName))) { PrintError2("Cannot open output file", outputName); return 1; } } bool fileSizeDefined = false; UInt64 fileSize = 0; if (inStreamSpec) { if (!inStreamSpec->GetLength(fileSize)) throw "Cannot get file length"; fileSizeDefined = true; if (!stdOutMode) Print_Size("Input size: ", fileSize); } if (encodeMode && !dictDefined) { dict = 1 << kDictSizeLog; if (fileSizeDefined) { unsigned i; for (i = 16; i < kDictSizeLog; i++) if ((UInt32)((UInt32)1 << i) >= fileSize) break; dict = (UInt32)1 << i; } } if (parser[NKey::kFilter86].ThereIs) { /* -f86 switch is for x86 filtered mode: BCJ + LZMA. It uses modified header format. It's not recommended to use -f86 mode now. You can use xz format instead, if you want to use filters */ if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Cannot use stdin in this mode"; size_t inSize = (size_t)fileSize; if (inSize != fileSize) throw "File is too big"; Byte *inBuffer = NULL; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (!inBuffer) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Cannot read"; Byte *outBuffer = NULL; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16); outSize = (size_t)outSize64; if (outSize != outSize64) throw "File is too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (!outBuffer) throw kCantAllocate; } int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { PrintError_int("Encode error", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "Unpack size is too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (!outBuffer) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) { PrintError_int("Decode error", (int)res); return 1; } } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); } else { CProgressPrint *progressSpec = NULL; CMyComPtr progress; if (!stdOutMode) { progressSpec = new CProgressPrint; progress = progressSpec; } if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr encoder = encoderSpec; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) mc = GetNumber(parser[NKey::kMc].PostStrings[0]); const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const unsigned kNumPropsMax = Z7_ARRAY_SIZE(propIDs); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = const_cast((const wchar_t *)mf); props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; unsigned numProps = kNumPropsMax; if (!mcDefined) numProps--; HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps); if (res != S_OK) return Error_HRESULT("incorrect encoder properties", res); if (encoderSpec->WriteCoderProperties(outStream) != S_OK) throw kWriteError; bool fileSizeWasUsed = true; if (eos || stdInMode) { fileSize = (UInt64)(Int64)-1; fileSizeWasUsed = false; } { Byte temp[8]; for (int i = 0; i < 8; i++) temp[i]= (Byte)(fileSize >> (8 * i)); if (WriteStream(outStream, temp, 8) != S_OK) throw kWriteError; } res = encoder->Code(inStream, outStream, NULL, NULL, progress); if (progressSpec) progressSpec->ClosePrint(); if (res != S_OK) return Error_HRESULT("Encoding error", res); UInt64 processedSize = encoderSpec->GetInputProcessedSize(); if (fileSizeWasUsed && processedSize != fileSize) throw "Incorrect size of processed data"; } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr decoder = decoderSpec; decoderSpec->FinishStream = true; const unsigned kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) throw kReadError; if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) throw "SetDecoderProperties error"; UInt64 unpackSize = 0; for (unsigned i = 0; i < 8; i++) unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1); HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress); if (progressSpec) progressSpec->ClosePrint(); if (res != S_OK) { if (res == S_FALSE) { PrintError("Decoding error"); return 1; } return Error_HRESULT("Decoding error", res); } if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize()) throw "incorrect uncompressed size in header"; } } if (outStreamSpec) { if (!stdOutMode) Print_Size("Output size: ", outStreamSpec->ProcessedSize); if (outStreamSpec->Close() != S_OK) throw "File closing error"; } return 0; } int Z7_CDECL main(int numArgs, const char *args[]) { NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; try { return main2(numArgs, args); } catch (const char *s) { PrintError(s); return 1; } catch(...) { PrintError("Unknown Error"); return 1; } } tmp41wklro_/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp0000444000175000001440000003102314555152040022466 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaCon - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaCon.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaCon.mak" CFG="LzmaCon - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaCon - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaCon - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_NO_LONG_PATH" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\lzma.exe" !ELSEIF "$(CFG)" == "LzmaCon - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_NO_LONG_PATH" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaCon - Win32 Release" # Name "LzmaCon - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\NtCheck.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Registry.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Registry.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\SystemInfo.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\SystemInfo.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CrcReg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\LzFindPrepare.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer2.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyLinux.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyTypes.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\Bench.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Bench.h # End Source File # End Group # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\BenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\BenchCon.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrcOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma86.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "7zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # End Group # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # End Target # End Project tmp41wklro_/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw0000444000175000001440000000103111305300622022460 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/Bundles/LzmaCon/makefile0000444000175000001440000000236014555152040022115 0ustar nabijaczleweliusersPROG = lzma.exe MY_CONSOLE = 1 CFLAGS = $(CFLAGS) -DZ7_NO_LONG_PATH # CFLAGS = $(CFLAGS) -DZ7_ST CURRENT_OBJS = \ $O\LzmaAlone.obj \ COMPRESS_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\CrcReg.obj \ $O\IntToString.obj \ $O\LzFindPrepare.obj \ $O\MyString.obj \ $O\MyVector.obj \ $O\NewHandler.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Registry.obj \ $O\System.obj \ $O\SystemInfo.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ $O\MethodProps.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\Bench.obj \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\BenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Bra86.obj \ $O\CpuArch.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ !include "../../Crc.mak" !include "../../LzFindOpt.mak" !include "../../LzmaDec.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/LzmaCon/makefile.gcc0000444000175000001440000000351614555224200022652 0ustar nabijaczleweliusersPROG = lzma # IS_X64 = 1 # USE_ASM = 1 # ST_MODE = 1 ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif include ../../LzmaDec_gcc.mak LOCAL_FLAGS_ST = MT_OBJS = ifdef ST_MODE LOCAL_FLAGS_ST = -DZ7_ST else MT_OBJS = \ $O/LzFindMt.o \ $O/LzFindOpt.o \ $O/Threads.o \ $O/Synchronization.o \ endif LOCAL_FLAGS_SYS = ifdef IS_MINGW SYS_OBJS = \ $O/Registry.o \ $O/resource.o \ LOCAL_FLAGS_SYS = \ -DZ7_NO_LONG_PATH \ else SYS_OBJS = \ $O/FileDir.o \ $O/FileFind.o \ $O/FileName.o \ $O/MyWindows.o \ $O/TimeUtils.o \ endif LOCAL_FLAGS = \ $(LOCAL_FLAGS_ST) \ $(LOCAL_FLAGS_SYS) \ COMMON_OBJS = \ $O/CommandLineParser.o \ $O/CRC.o \ $O/CrcReg.o \ $O/IntToString.o \ $O/LzFindPrepare.o \ $O/MyString.o \ $O/MyVector.o \ $O/NewHandler.o \ $O/StringConvert.o \ $O/StringToInt.o \ $O/UTFConvert.o \ $O/Wildcard.o \ WIN_OBJS = \ $O/FileIO.o \ $O/PropVariant.o \ $O/System.o \ $O/SystemInfo.o \ COMPRESS_OBJS = \ $O/LzmaDecoder.o \ $O/LzmaEncoder.o \ $O/LzmaRegister.o \ CONSOLE_OBJS = \ $O/BenchCon.o \ $O/ConsoleClose.o \ 7ZIP_COMMON_OBJS = \ $O/CreateCoder.o \ $O/CWrappers.o \ $O/FileStreams.o \ $O/FilterCoder.o \ $O/MethodProps.o \ $O/StreamObjects.o \ $O/StreamUtils.o \ C_OBJS = \ $O/7zCrc.o \ $O/7zCrcOpt.o \ $O/Alloc.o \ $O/Bra86.o \ $O/CpuArch.o \ $O/LzFind.o \ $O/LzmaDec.o \ $O/LzmaEnc.o \ $O/Lzma86Dec.o \ $O/Lzma86Enc.o \ OBJS = \ $(LZMA_DEC_OPT_OBJS) \ $(C_OBJS) \ $(MT_OBJS) \ $(SYS_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(COMPRESS_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(CONSOLE_OBJS) \ $O/LzmaAlone.o \ $O/Bench.o \ include ../../7zip_gcc.mak tmp41wklro_/CPP/7zip/Bundles/LzmaCon/resource.rc0000444000175000001440000000011212100433211022545 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("LZMA", "lzma") tmp41wklro_/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp0000444000175000001440000000004610144137330022304 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/LzmaCon/StdAfx.h0000444000175000001440000000036114360505460021760 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Bundles/LzmaSpec/0000700000175000001440000000000014706260545020567 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp0000444000175000001440000003717712607474211023033 0ustar nabijaczleweliusers/* LzmaSpec.cpp -- LZMA Reference Decoder 2015-06-14 : Igor Pavlov : Public domain */ // This code implements LZMA file decoding according to LZMA specification. // This code is not optimized for speed. #include #ifdef _MSC_VER #pragma warning(disable : 4710) // function not inlined #pragma warning(disable : 4996) // This function or variable may be unsafe #endif typedef unsigned char Byte; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif struct CInputStream { FILE *File; UInt64 Processed; void Init() { Processed = 0; } Byte ReadByte() { int c = getc(File); if (c < 0) throw "Unexpected end of file"; Processed++; return (Byte)c; } }; struct COutStream { FILE *File; UInt64 Processed; void Init() { Processed = 0; } void WriteByte(Byte b) { if (putc(b, File) == EOF) throw "File writing error"; Processed++; } }; class COutWindow { Byte *Buf; UInt32 Pos; UInt32 Size; bool IsFull; public: unsigned TotalPos; COutStream OutStream; COutWindow(): Buf(NULL) {} ~COutWindow() { delete []Buf; } void Create(UInt32 dictSize) { Buf = new Byte[dictSize]; Pos = 0; Size = dictSize; IsFull = false; TotalPos = 0; } void PutByte(Byte b) { TotalPos++; Buf[Pos++] = b; if (Pos == Size) { Pos = 0; IsFull = true; } OutStream.WriteByte(b); } Byte GetByte(UInt32 dist) const { return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos]; } void CopyMatch(UInt32 dist, unsigned len) { for (; len > 0; len--) PutByte(GetByte(dist)); } bool CheckDistance(UInt32 dist) const { return dist <= Pos || IsFull; } bool IsEmpty() const { return Pos == 0 && !IsFull; } }; #define kNumBitModelTotalBits 11 #define kNumMoveBits 5 typedef UInt16 CProb; #define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2) #define INIT_PROBS(p) \ { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; } class CRangeDecoder { UInt32 Range; UInt32 Code; void Normalize(); public: CInputStream *InStream; bool Corrupted; bool Init(); bool IsFinishedOK() const { return Code == 0; } UInt32 DecodeDirectBits(unsigned numBits); unsigned DecodeBit(CProb *prob); }; bool CRangeDecoder::Init() { Corrupted = false; Range = 0xFFFFFFFF; Code = 0; Byte b = InStream->ReadByte(); for (int i = 0; i < 4; i++) Code = (Code << 8) | InStream->ReadByte(); if (b != 0 || Code == Range) Corrupted = true; return b == 0; } #define kTopValue ((UInt32)1 << 24) void CRangeDecoder::Normalize() { if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | InStream->ReadByte(); } } UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits) { UInt32 res = 0; do { Range >>= 1; Code -= Range; UInt32 t = 0 - ((UInt32)Code >> 31); Code += Range & t; if (Code == Range) Corrupted = true; Normalize(); res <<= 1; res += t + 1; } while (--numBits); return res; } unsigned CRangeDecoder::DecodeBit(CProb *prob) { unsigned v = *prob; UInt32 bound = (Range >> kNumBitModelTotalBits) * v; unsigned symbol; if (Code < bound) { v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits; Range = bound; symbol = 0; } else { v -= v >> kNumMoveBits; Code -= bound; Range -= bound; symbol = 1; } *prob = (CProb)v; Normalize(); return symbol; } unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc) { unsigned m = 1; unsigned symbol = 0; for (unsigned i = 0; i < numBits; i++) { unsigned bit = rc->DecodeBit(&probs[m]); m <<= 1; m += bit; symbol |= (bit << i); } return symbol; } template class CBitTreeDecoder { CProb Probs[(unsigned)1 << NumBits]; public: void Init() { INIT_PROBS(Probs); } unsigned Decode(CRangeDecoder *rc) { unsigned m = 1; for (unsigned i = 0; i < NumBits; i++) m = (m << 1) + rc->DecodeBit(&Probs[m]); return m - ((unsigned)1 << NumBits); } unsigned ReverseDecode(CRangeDecoder *rc) { return BitTreeReverseDecode(Probs, NumBits, rc); } }; #define kNumPosBitsMax 4 #define kNumStates 12 #define kNumLenToPosStates 4 #define kNumAlignBits 4 #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #define kMatchMinLen 2 class CLenDecoder { CProb Choice; CProb Choice2; CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax]; CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax]; CBitTreeDecoder<8> HighCoder; public: void Init() { Choice = PROB_INIT_VAL; Choice2 = PROB_INIT_VAL; HighCoder.Init(); for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++) { LowCoder[i].Init(); MidCoder[i].Init(); } } unsigned Decode(CRangeDecoder *rc, unsigned posState) { if (rc->DecodeBit(&Choice) == 0) return LowCoder[posState].Decode(rc); if (rc->DecodeBit(&Choice2) == 0) return 8 + MidCoder[posState].Decode(rc); return 16 + HighCoder.Decode(rc); } }; unsigned UpdateState_Literal(unsigned state) { if (state < 4) return 0; else if (state < 10) return state - 3; else return state - 6; } unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; } unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; } unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; } #define LZMA_DIC_MIN (1 << 12) class CLzmaDecoder { public: CRangeDecoder RangeDec; COutWindow OutWindow; bool markerIsMandatory; unsigned lc, pb, lp; UInt32 dictSize; UInt32 dictSizeInProperties; void DecodeProperties(const Byte *properties) { unsigned d = properties[0]; if (d >= (9 * 5 * 5)) throw "Incorrect LZMA properties"; lc = d % 9; d /= 9; pb = d / 5; lp = d % 5; dictSizeInProperties = 0; for (int i = 0; i < 4; i++) dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i); dictSize = dictSizeInProperties; if (dictSize < LZMA_DIC_MIN) dictSize = LZMA_DIC_MIN; } CLzmaDecoder(): LitProbs(NULL) {} ~CLzmaDecoder() { delete []LitProbs; } void Create() { OutWindow.Create(dictSize); CreateLiterals(); } int Decode(bool unpackSizeDefined, UInt64 unpackSize); private: CProb *LitProbs; void CreateLiterals() { LitProbs = new CProb[(UInt32)0x300 << (lc + lp)]; } void InitLiterals() { UInt32 num = (UInt32)0x300 << (lc + lp); for (UInt32 i = 0; i < num; i++) LitProbs[i] = PROB_INIT_VAL; } void DecodeLiteral(unsigned state, UInt32 rep0) { unsigned prevByte = 0; if (!OutWindow.IsEmpty()) prevByte = OutWindow.GetByte(1); unsigned symbol = 1; unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc)); CProb *probs = &LitProbs[(UInt32)0x300 * litState]; if (state >= 7) { unsigned matchByte = OutWindow.GetByte(rep0 + 1); do { unsigned matchBit = (matchByte >> 7) & 1; matchByte <<= 1; unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]); symbol = (symbol << 1) | bit; if (matchBit != bit) break; } while (symbol < 0x100); } while (symbol < 0x100) symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]); OutWindow.PutByte((Byte)(symbol - 0x100)); } CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates]; CBitTreeDecoder AlignDecoder; CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex]; void InitDist() { for (unsigned i = 0; i < kNumLenToPosStates; i++) PosSlotDecoder[i].Init(); AlignDecoder.Init(); INIT_PROBS(PosDecoders); } unsigned DecodeDistance(unsigned len) { unsigned lenState = len; if (lenState > kNumLenToPosStates - 1) lenState = kNumLenToPosStates - 1; unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); if (posSlot < 4) return posSlot; unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1); UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec); else { dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits; dist += AlignDecoder.ReverseDecode(&RangeDec); } return dist; } CProb IsMatch[kNumStates << kNumPosBitsMax]; CProb IsRep[kNumStates]; CProb IsRepG0[kNumStates]; CProb IsRepG1[kNumStates]; CProb IsRepG2[kNumStates]; CProb IsRep0Long[kNumStates << kNumPosBitsMax]; CLenDecoder LenDecoder; CLenDecoder RepLenDecoder; void Init() { InitLiterals(); InitDist(); INIT_PROBS(IsMatch); INIT_PROBS(IsRep); INIT_PROBS(IsRepG0); INIT_PROBS(IsRepG1); INIT_PROBS(IsRepG2); INIT_PROBS(IsRep0Long); LenDecoder.Init(); RepLenDecoder.Init(); } }; #define LZMA_RES_ERROR 0 #define LZMA_RES_FINISHED_WITH_MARKER 1 #define LZMA_RES_FINISHED_WITHOUT_MARKER 2 int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize) { if (!RangeDec.Init()) return LZMA_RES_ERROR; Init(); UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; unsigned state = 0; for (;;) { if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory) if (RangeDec.IsFinishedOK()) return LZMA_RES_FINISHED_WITHOUT_MARKER; unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0) { if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; DecodeLiteral(state, rep0); state = UpdateState_Literal(state); unpackSize--; continue; } unsigned len; if (RangeDec.DecodeBit(&IsRep[state]) != 0) { if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; if (OutWindow.IsEmpty()) return LZMA_RES_ERROR; if (RangeDec.DecodeBit(&IsRepG0[state]) == 0) { if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0) { state = UpdateState_ShortRep(state); OutWindow.PutByte(OutWindow.GetByte(rep0 + 1)); unpackSize--; continue; } } else { UInt32 dist; if (RangeDec.DecodeBit(&IsRepG1[state]) == 0) dist = rep1; else { if (RangeDec.DecodeBit(&IsRepG2[state]) == 0) dist = rep2; else { dist = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = dist; } len = RepLenDecoder.Decode(&RangeDec, posState); state = UpdateState_Rep(state); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = LenDecoder.Decode(&RangeDec, posState); state = UpdateState_Match(state); rep0 = DecodeDistance(len); if (rep0 == 0xFFFFFFFF) return RangeDec.IsFinishedOK() ? LZMA_RES_FINISHED_WITH_MARKER : LZMA_RES_ERROR; if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0)) return LZMA_RES_ERROR; } len += kMatchMinLen; bool isError = false; if (unpackSizeDefined && unpackSize < len) { len = (unsigned)unpackSize; isError = true; } OutWindow.CopyMatch(rep0 + 1, len); unpackSize -= len; if (isError) return LZMA_RES_ERROR; } } static void Print(const char *s) { fputs(s, stdout); } static void PrintError(const char *s) { fputs(s, stderr); } #define CONVERT_INT_TO_STR(charType, tempSize) \ void ConvertUInt64ToString(UInt64 val, char *s) { char temp[32]; unsigned i = 0; while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } *s++ = (char)('0' + (unsigned)val); while (i != 0) { i--; *s++ = temp[i]; } *s = 0; } void PrintUInt64(const char *title, UInt64 v) { Print(title); Print(" : "); char s[32]; ConvertUInt64ToString(v, s); Print(s); Print(" bytes \n"); } int main2(int numArgs, const char *args[]) { Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n"); if (numArgs == 1) Print("\nUse: lzmaSpec a.lzma outFile"); if (numArgs != 3) throw "you must specify two parameters"; CInputStream inStream; inStream.File = fopen(args[1], "rb"); inStream.Init(); if (inStream.File == 0) throw "Can't open input file"; CLzmaDecoder lzmaDecoder; lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+"); lzmaDecoder.OutWindow.OutStream.Init(); if (inStream.File == 0) throw "Can't open output file"; Byte header[13]; int i; for (i = 0; i < 13; i++) header[i] = inStream.ReadByte(); lzmaDecoder.DecodeProperties(header); printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb); printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties); printf("\nDictionary Size for decoding = %u", lzmaDecoder.dictSize); UInt64 unpackSize = 0; bool unpackSizeDefined = false; for (i = 0; i < 8; i++) { Byte b = header[5 + i]; if (b != 0xFF) unpackSizeDefined = true; unpackSize |= (UInt64)b << (8 * i); } lzmaDecoder.markerIsMandatory = !unpackSizeDefined; Print("\n"); if (unpackSizeDefined) PrintUInt64("Uncompressed Size", unpackSize); else Print("End marker is expected\n"); lzmaDecoder.RangeDec.InStream = &inStream; Print("\n"); lzmaDecoder.Create(); int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize); PrintUInt64("Read ", inStream.Processed); PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed); if (res == LZMA_RES_ERROR) throw "LZMA decoding error"; else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER) Print("Finished without end marker"); else if (res == LZMA_RES_FINISHED_WITH_MARKER) { if (unpackSizeDefined) { if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize) throw "Finished with end marker before than specified size"; Print("Warning: "); } Print("Finished with end marker"); } else throw "Internal Error"; Print("\n"); if (lzmaDecoder.RangeDec.Corrupted) { Print("\nWarning: LZMA stream is corrupted\n"); } return 0; } int #ifdef _MSC_VER __cdecl #endif main(int numArgs, const char *args[]) { try { return main2(numArgs, args); } catch (const char *s) { PrintError("\nError:\n"); PrintError(s); PrintError("\n"); return 1; } catch(...) { PrintError("\nError\n"); return 1; } } tmp41wklro_/CPP/7zip/Bundles/SFXCon/0000700000175000001440000000000014706260545020151 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/SFXCon/7z.ico0000444000175000001440000000206607723131552021215 0ustar nabijaczleweliusers è&(( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿðÿÿÿðÿðÿÿÿÿÿðÿðÿÿÿÿÿðÿðÿðÿÿÿÿðÿðÿÿÿÿÿðÿðÿÿðÿÿÿðÿÿÿÿÿÿðÿðÿÿÿðÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿððÿÿðÿððÿðððÿðÿðÿÿÿÿðÿÿðÿÿÿÿÿÿðÿÿÿÿÿÿÿÿtmp41wklro_/CPP/7zip/Bundles/SFXCon/makefile0000444000175000001440000000531714576475540021677 0ustar nabijaczleweliusersPROG = 7zCon.sfx MY_CONSOLE = 1 MY_FIXED = 1 CFLAGS = $(CFLAGS) \ -DZ7_EXTRACT_ONLY \ -DZ7_NO_READ_FROM_CODER \ -DZ7_SFX \ -DZ7_NO_LONG_PATH \ -DZ7_NO_LARGE_PAGES \ CURRENT_OBJS = \ $O\SfxCon.obj \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\MyVector.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\StringConvert.obj \ $O\UTFConvert.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ AR_OBJS = \ $O\SplitHandler.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ 7Z_OBJS = \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHandler.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ $O\PpmdDecoder.obj \ $O\PpmdRegister.obj \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\MyAes.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\LzmaDec.obj \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/SFXCon/makefile.gcc0000444000175000001440000000655114555224200022411 0ustar nabijaczleweliusersPROG = 7zCon # IS_X64 = 1 # USE_ASM = 1 # ST_MODE = 1 include ../../LzmaDec_gcc.mak LOCAL_FLAGS_ST = MT_OBJS = ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif ifdef ST_MODE LOCAL_FLAGS_ST = -DZ7_ST ifdef IS_MINGW MT_OBJS = \ $O/Threads.o \ endif else MT_OBJS = \ $O/StreamBinder.o \ $O/Synchronization.o \ $O/VirtThread.o \ $O/Threads.o \ endif LOCAL_FLAGS_SYS = ifdef IS_MINGW LOCAL_FLAGS_SYS = \ -DZ7_NO_LONG_PATH \ -DZ7_NO_LARGE_PAGES \ SYS_OBJS = \ $O/DLL.o \ $O/DllSecur.o \ $O/resource.o \ else SYS_OBJS = \ $O/MyWindows.o \ endif LOCAL_FLAGS = \ -DZ7_EXTRACT_ONLY \ -DZ7_NO_READ_FROM_CODER \ -DZ7_SFX \ $(LOCAL_FLAGS_ST) \ $(LOCAL_FLAGS_SYS) \ CURRENT_OBJS = \ $O/SfxCon.o \ CONSOLE_OBJS = \ $O/ConsoleClose.o \ $O/ExtractCallbackConsole.o \ $O/List.o \ $O/MainAr.o \ $O/OpenCallbackConsole.o \ $O/PercentPrinter.o \ $O/UserInputUtils.o \ COMMON_OBJS = \ $O/CommandLineParser.o \ $O/CRC.o \ $O/IntToString.o \ $O/MyString.o \ $O/MyVector.o \ $O/NewHandler.o \ $O/Sha256Prepare.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/StringConvert.o \ $O/UTFConvert.o \ $O/Wildcard.o \ WIN_OBJS = \ \ $O/ErrorMsg.o \ $O/FileDir.o \ $O/FileFind.o \ $O/FileIO.o \ $O/FileName.o \ $O/PropVariant.o \ $O/PropVariantConv.o \ \ $O/System.o \ $O/TimeUtils.o \ 7ZIP_COMMON_OBJS = \ $O/CreateCoder.o \ $O/CWrappers.o \ $O/FilePathAutoRename.o \ $O/FileStreams.o \ $O/InBuffer.o \ $O/FilterCoder.o \ $O/LimitedStreams.o \ $O/OutBuffer.o \ $O/ProgressUtils.o \ $O/PropId.o \ \ $O/StreamObjects.o \ $O/StreamUtils.o \ \ UI_COMMON_OBJS = \ $O/ArchiveExtractCallback.o \ $O/ArchiveOpenCallback.o \ $O/DefaultName.o \ $O/Extract.o \ $O/ExtractingFilePath.o \ $O/LoadCodecs.o \ $O/OpenArchive.o \ $O/PropIDUtils.o \ AR_OBJS = \ $O/SplitHandler.o \ AR_COMMON_OBJS = \ $O/CoderMixer2.o \ $O/ItemNameUtils.o \ $O/MultiStream.o \ $O/OutStreamWithCRC.o \ 7Z_OBJS = \ $O/7zDecode.o \ $O/7zExtract.o \ $O/7zHandler.o \ $O/7zIn.o \ $O/7zRegister.o \ COMPRESS_OBJS = \ $O/Bcj2Coder.o \ $O/Bcj2Register.o \ $O/BcjCoder.o \ $O/BcjRegister.o \ $O/BranchMisc.o \ $O/BranchRegister.o \ $O/CopyCoder.o \ $O/CopyRegister.o \ $O/DeltaFilter.o \ $O/Lzma2Decoder.o \ $O/Lzma2Register.o \ $O/LzmaDecoder.o \ $O/LzmaRegister.o \ $O/PpmdDecoder.o \ $O/PpmdRegister.o \ CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ $O/MyAes.o \ C_OBJS = \ $O/7zStream.o \ $O/Alloc.o \ $O/Bcj2.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ $O/CpuArch.o \ $O/Delta.o \ $O/Lzma2Dec.o \ $O/Lzma2DecMt.o \ $O/LzmaDec.o \ $O/MtDec.o \ $O/Ppmd7.o \ $O/Ppmd7Dec.o \ $O/Sha256.o \ $O/Sha256Opt.o \ $O/7zCrc.o \ $O/7zCrcOpt.o \ $O/Aes.o \ $O/AesOpt.o \ OBJS = \ $(LZMA_DEC_OPT_OBJS) \ $(C_OBJS) \ $(MT_OBJS) \ $(SYS_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(COMPRESS_OBJS) \ $(CRYPTO_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(UI_COMMON_OBJS) \ $(CONSOLE_OBJS) \ $(CURRENT_OBJS) \ include ../../7zip_gcc.mak tmp41wklro_/CPP/7zip/Bundles/SFXCon/resource.rc0000444000175000001440000000030314353073020022316 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx") 101 ICON "7z.ico" #ifndef UNDER_CE 1 24 MOVEABLE PURE "../../UI/Console/Console.manifest" #endif tmp41wklro_/CPP/7zip/Bundles/SFXCon/SfxCon.cpp0000444000175000001440000003167214634237200022066 0ustar nabijaczleweliusers// Main.cpp #include "StdAfx.h" #include "../../../../C/CpuArch.h" #include "../../../../C/DllSecur.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/MyException.h" #ifdef _WIN32 #include "../../../Windows/DLL.h" #else #include "../../../Common/StringConvert.h" #endif #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../UI/Common/ExitCode.h" #include "../../UI/Common/Extract.h" #include "../../UI/Console/ExtractCallbackConsole.h" #include "../../UI/Console/List.h" #include "../../UI/Console/OpenCallbackConsole.h" #include "../../MyVersion.h" using namespace NWindows; using namespace NFile; using namespace NDir; using namespace NCommandLineParser; #ifdef _WIN32 extern HINSTANCE g_hInstance; HINSTANCE g_hInstance = NULL; #endif extern int g_CodePage; int g_CodePage = -1; extern CStdOutStream *g_StdStream; static const char * const kCopyrightString = "\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n"; static const int kNumSwitches = 6; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kDisablePercents, kYes, kPassword, kOutputDir }; } namespace NRecursedType { enum EEnum { kRecursed, kWildcardOnlyRecursed, kNonRecursed }; } /* static const char kRecursedIDChar = 'R'; namespace NRecursedPostCharIndex { enum EEnum { kWildcardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kFileListID = '@'; static const char kImmediateNameID = '!'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be */ #define SWFRM_3(t, mu, mi) t, mu, mi, NULL #define SWFRM_1(t) SWFRM_3(t, false, 0) #define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) #define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) static const CSwitchForm kSwitchForms[kNumSwitches] = { { "?", SWFRM_SIMPLE }, { "H", SWFRM_SIMPLE }, { "BD", SWFRM_SIMPLE }, { "Y", SWFRM_SIMPLE }, { "P", SWFRM_STRING_SINGL(1) }, { "O", SWFRM_STRING_SINGL(1) }, }; static const int kNumCommandForms = 3; static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = { NRecursedType::kRecursed }; // static const bool kTestExtractRecursedDefault = true; // static const bool kAddRecursedDefault = false; static const char * const kUniversalWildcard = "*"; static const char * const kHelpString = "\nUsage: 7zSFX [] [...] [...]\n" "\n" "\n" // " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full pathname (default)\n" "\n" // " -bd Disable percentage indicator\n" " -o{Directory}: set Output directory\n" " -p{Password}: set Password\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError // static const char * const kIncorrectListFile = "Incorrect wildcard in listfile"; static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; // static const CSysString kFileIsNotArchiveMessageBefore = "File \""; // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; // static const char * const kProcessArchiveMessage = " archive: "; static const char * const kCantFindSFX = " cannot find sfx"; namespace NCommandType { enum EEnum { kTest = 0, kFullExtract, kList }; } static const char *g_Commands = "txl"; struct CArchiveCommand { NCommandType::EEnum CommandType; NRecursedType::EEnum DefaultRecursedType() const; }; static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString s = commandString; s.MakeLower_Ascii(); if (s.Len() != 1) return false; if (s[0] >= 0x80) return false; int index = FindCharPosInString(g_Commands, (char)s[0]); if (index < 0) return false; command.CommandType = (NCommandType::EEnum)index; return true; } NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const { return kCommandRecursedDefault[CommandType]; } static void PrintHelp(void) { g_StdOut << kHelpString; } Z7_ATTR_NORETURN static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) { g_StdOut << message << endl; throw code; } Z7_ATTR_NORETURN static void PrintHelpAndExit() // yyy { PrintHelp(); ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { /* if (!IsWildcardFilePathLegal(name)) return false; */ const bool isWildcard = DoesNameContainWildcard(name); bool recursed = false; switch (type) { case NRecursedType::kWildcardOnlyRecursed: recursed = isWildcard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } NWildcard::CCensorPathProps props; props.Recursive = recursed; wildcardCensor.AddPreItem(include, name, props); return true; } static void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { if (!AddNameToCensor(wildcardCensor, name, include, type)) ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArgs, char *args[], UStringVector &parts) { parts.Clear(); for (int i = 0; i < numArgs; i++) { UString s = MultiByteToUnicodeString(args[i]); parts.Add(s); } } #endif int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ); int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ) { #ifdef _WIN32 // do we need load Security DLLs for console program? LoadSecurityDlls(); #endif #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif #ifdef ENV_HAVE_LOCALE MY_SetLocale(); #endif g_StdOut << kCopyrightString; UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArgs, args, commandStrings); #endif #ifdef _WIN32 FString arcPath; { FString path; NDLL::MyGetModuleFileName(path); if (!MyGetFullPathName(path, arcPath)) { g_StdOut << "GetFullPathName Error"; return NExitCode::kFatalError; } } #else if (commandStrings.IsEmpty()) return NExitCode::kFatalError; const FString arcPath = us2fs(commandStrings.Front()); #endif #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif NCommandLineParser::CParser parser; try { if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings)) { g_StdOut << "Command line error:" << endl << parser.ErrorMessage << endl << parser.ErrorLine << endl; return NExitCode::kUserError; } } catch(...) { PrintHelpAndExit(); } if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; unsigned curCommandIndex = 0; CArchiveCommand command; if (nonSwitchStrings.IsEmpty()) command.CommandType = NCommandType::kFullExtract; else { const UString &cmd = nonSwitchStrings[curCommandIndex]; if (!ParseArchiveCommand(cmd, command)) { g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl; return NExitCode::kUserError; } curCommandIndex = 1; } NRecursedType::EEnum recursedType; recursedType = command.DefaultRecursedType(); NWildcard::CCensor wildcardCensor; { if (nonSwitchStrings.Size() == curCommandIndex) AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType); for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) { const UString &s = nonSwitchStrings[curCommandIndex]; if (s.IsEmpty()) throw "Empty file path"; AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType); } } const bool yesToAll = parser[NKey::kYes].ThereIs; // NExtractMode::EEnum extractMode; // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); const bool passwordEnabled = parser[NKey::kPassword].ThereIs; UString password; if (passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; if (!NFind::DoesFileExist_FollowLink(arcPath)) throw kCantFindSFX; FString outputDir; if (parser[NKey::kOutputDir].ThereIs) { outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); NName::NormalizeDirPathPrefix(outputDir); } wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); { UStringVector v1, v2; v1.Add(fs2us(arcPath)); v2.Add(fs2us(arcPath)); const NWildcard::CCensorNode &wildcardCensorHead = wildcardCensor.Pairs.Front().Head; CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef Z7_EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; { HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); } if (command.CommandType != NCommandType::kList) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr extractCallback = ecs; ecs->Init(g_StdStream, &g_StdErr, g_StdStream, false); #ifndef Z7_NO_CRYPTO ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; #endif /* COpenCallbackConsole openCallback; openCallback.Init(g_StdStream, g_StdStream); #ifndef Z7_NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif */ CExtractOptions eo; eo.StdOutMode = false; eo.YesToAll = yesToAll; eo.TestMode = command.CommandType == NCommandType::kTest; eo.PathMode = NExtract::NPathMode::kFullPaths; eo.OverwriteMode = yesToAll ? NExtract::NOverwriteMode::kOverwrite : NExtract::NOverwriteMode::kAsk; eo.OutputDir = outputDir; UString errorMessage; CDecompressStat stat; HRESULT result = Extract( codecs, CObjectVector(), CIntVector(), v1, v2, wildcardCensorHead, eo, ecs, ecs, ecs, // NULL, // hash errorMessage, stat); ecs->ClosePercents(); if (!errorMessage.IsEmpty()) { (*g_StdStream) << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } if ( 0 != ecs->NumCantOpenArcs || 0 != ecs->NumArcsWithError || 0 != ecs->NumFileErrors || 0 != ecs->NumOpenArcErrors) { if (ecs->NumCantOpenArcs != 0) (*g_StdStream) << endl << "Can't open as archive" << endl; if (ecs->NumArcsWithError != 0) (*g_StdStream) << endl << "Archive Errors" << endl; if (ecs->NumFileErrors != 0) (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; if (ecs->NumOpenArcErrors != 0) (*g_StdStream) << endl << "Open Errors: " << ecs->NumOpenArcErrors << endl; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } else { throw CSystemException(E_NOTIMPL); /* UInt64 numErrors = 0; UInt64 numWarnings = 0; HRESULT result = ListArchives( codecs, CObjectVector(), CIntVector(), false, // stdInMode v1, v2, true, // processAltStreams false, // showAltStreams wildcardCensorHead, true, // enableHeaders false, // techMode #ifndef Z7_NO_CRYPTO passwordEnabled, password, #endif numErrors, numWarnings); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); */ } } return 0; } tmp41wklro_/CPP/7zip/Bundles/SFXCon/SFXCon.dsp0000444000175000001440000005372414561355600022000 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="SFXCon" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=SFXCon - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "SFXCon.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "SFXCon.mak" CFG="SFXCon - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "SFXCon - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "SFXCon - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\7zCon.exe" /pdbtype:sept !ENDIF # Begin Target # Name "SFXCon - Win32 Release" # Name "SFXCon - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # End Group # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\SplitHandler.cpp # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\DeltaFilter.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdRegister.cpp # End Source File # End Group # Begin Group "Crypto" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Crypto\7zAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAes.h # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer2.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Sha256Prepare.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "UI" # PROP Default_Filter "" # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExitCode.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # End Group # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrcOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zStream.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\AesOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.c !IF "$(CFG)" == "SFXCon - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "SFXCon - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256Opt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "7zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # End Group # Begin Source File SOURCE=.\7z.ico # End Source File # Begin Source File SOURCE=.\SfxCon.cpp # End Source File # End Target # End Project tmp41wklro_/CPP/7zip/Bundles/SFXCon/SFXCon.dsw0000444000175000001440000000102707353741602021776 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "SFXCon"=.\SFXCon.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/Bundles/SFXCon/StdAfx.cpp0000444000175000001440000000004610144137330022041 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/SFXCon/StdAfx.h0000444000175000001440000000036114360505460021515 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Bundles/SFXSetup/0000700000175000001440000000000014706260545020532 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp0000444000175000001440000001430714533123000024741 0ustar nabijaczleweliusers// ExtractCallbackSfx.h #include "StdAfx.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariant.h" #include "ExtractCallbackSfx.h" using namespace NWindows; using namespace NFile; using namespace NDir; static LPCSTR const kCantDeleteFile = "Cannot delete output file"; static LPCSTR const kCantOpenFile = "Cannot open output file"; static LPCSTR const kUnsupportedMethod = "Unsupported Method"; void CExtractCallbackImp::Init(IInArchive *archiveHandler, const FString &directoryPath, const UString &itemDefaultName, const FILETIME &defaultMTime, UInt32 defaultAttributes) { _message.Empty(); _isCorrupt = false; _itemDefaultName = itemDefaultName; _defaultMTime = defaultMTime; _defaultAttributes = defaultAttributes; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NName::NormalizeDirPathPrefix(_directoryPath); } HRESULT CExtractCallbackImp::Open_CheckBreak() { #ifndef _NO_PROGRESS return ProgressDialog.Sync.ProcessStopAndPause(); #else return S_OK; #endif } HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) { return S_OK; } HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) { #ifndef _NO_PROGRESS return ProgressDialog.Sync.ProcessStopAndPause(); #else return S_OK; #endif } HRESULT CExtractCallbackImp::Open_Finished() { return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::SetTotal(UInt64 size)) { #ifndef _NO_PROGRESS ProgressDialog.Sync.SetProgress(size, 0); #endif return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)) { #ifndef _NO_PROGRESS RINOK(ProgressDialog.Sync.ProcessStopAndPause()) if (completeValue != NULL) ProgressDialog.Sync.SetPos(*completeValue); #endif return S_OK; } void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) { FString fullPath = _directoryPath; FOR_VECTOR (i, dirPathParts) { fullPath += us2fs(dirPathParts[i]); CreateDir(fullPath); fullPath.Add_PathSepar(); } } Z7_COM7F_IMF(CExtractCallbackImp::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) { #ifndef _NO_PROGRESS if (ProgressDialog.Sync.GetStopped()) return E_ABORT; #endif _outFileStream.Release(); UString fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)) if (prop.vt == VT_EMPTY) fullPath = _itemDefaultName; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath.SetFromBstr(prop.bstrVal); } _filePath = fullPath; } if (askExtractMode == NArchive::NExtract::NAskMode::kExtract) { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)) if (prop.vt == VT_EMPTY) _processedFileInfo.Attributes = _defaultAttributes; else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; } RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop)) _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal); bool isAnti = false; { NCOM::CPropVariant propTemp; RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp)) if (propTemp.vt == VT_BOOL) isAnti = VARIANT_BOOLToBool(propTemp.boolVal); } RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)) switch (prop.vt) { case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break; default: return E_FAIL; } UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if (pathParts.IsEmpty()) return E_FAIL; UString processedPath = fullPath; if (!_processedFileInfo.IsDir) pathParts.DeleteBack(); if (!pathParts.IsEmpty()) { if (!isAnti) CreateComplexDirectory(pathParts); } FString fullProcessedPath = _directoryPath + us2fs(processedPath); if (_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) RemoveDir(_diskFilePath); else SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); return S_OK; } NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { if (!DeleteFileAlways(fullProcessedPath)) { _message = kCantDeleteFile; return E_FAIL; } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Create_ALWAYS(fullProcessedPath)) { _message = kCantOpenFile; return E_FAIL; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)) { _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract); return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)) { switch (resultEOperationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { _outFileStream.Release(); switch (resultEOperationResult) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: _message = kUnsupportedMethod; break; default: _isCorrupt = true; } return E_FAIL; } } if (_outFileStream != NULL) { _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()) } _outFileStream.Release(); if (_extractMode) SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes); return S_OK; } tmp41wklro_/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h0000444000175000001440000000362114412474560024423 0ustar nabijaczleweliusers// ExtractCallbackSfx.h #ifndef ZIP7_INC_EXTRACT_CALLBACK_SFX_H #define ZIP7_INC_EXTRACT_CALLBACK_SFX_H #include "resource.h" #include "../../../Windows/ResourceString.h" #include "../../Archive/IArchive.h" #include "../../Common/FileStreams.h" #include "../../ICoder.h" #include "../../UI/FileManager/LangUtils.h" #ifndef _NO_PROGRESS #include "../../UI/FileManager/ProgressDialog.h" #endif #include "../../UI/Common/ArchiveOpenCallback.h" class CExtractCallbackImp Z7_final: public IArchiveExtractCallback, public IOpenCallbackUI, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IArchiveExtractCallback) Z7_IFACE_IMP(IOpenCallbackUI) CMyComPtr _archiveHandler; FString _directoryPath; UString _filePath; FString _diskFilePath; bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; bool IsDir; UInt32 Attributes; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; UString _itemDefaultName; FILETIME _defaultMTime; UInt32 _defaultAttributes; void CreateComplexDirectory(const UStringVector &dirPathParts); public: #ifndef _NO_PROGRESS CProgressDialog ProgressDialog; #endif bool _isCorrupt; UString _message; void Init(IInArchive *archiveHandler, const FString &directoryPath, const UString &itemDefaultName, const FILETIME &defaultMTime, UInt32 defaultAttributes); #ifndef _NO_PROGRESS HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread) { ProgressDialog.Create(title, thread, NULL); { ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING)); } ProgressDialog.Show(SW_SHOWNORMAL); return S_OK; } ~CExtractCallbackImp() { ProgressDialog.Destroy(); } #endif }; #endif tmp41wklro_/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp0000444000175000001440000000635614406117440024010 0ustar nabijaczleweliusers// ExtractEngine.cpp #include "StdAfx.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Thread.h" #include "../../UI/Common/OpenArchive.h" #include "../../UI/FileManager/FormatUtils.h" #include "../../UI/FileManager/LangUtils.h" #include "ExtractCallbackSfx.h" #include "ExtractEngine.h" using namespace NWindows; using namespace NFile; using namespace NDir; static LPCSTR const kCantFindArchive = "Cannot find archive file"; static LPCSTR const kCantOpenArchive = "Cannot open the file as archive"; struct CThreadExtracting { CCodecs *Codecs; FString FileName; FString DestFolder; CExtractCallbackImp *ExtractCallbackSpec; CMyComPtr ExtractCallback; CArchiveLink ArchiveLink; HRESULT Result; UString ErrorMessage; void Process2() { NFind::CFileInfo fi; if (!fi.Find(FileName)) { ErrorMessage = kCantFindArchive; Result = E_FAIL; return; } CObjectVector incl; CIntVector excl; COpenOptions options; options.codecs = Codecs; options.types = &incl; options.excludedFormats = ! options.filePath = fs2us(FileName); Result = ArchiveLink.Open2(options, ExtractCallbackSpec); if (Result != S_OK) { ErrorMessage = kCantOpenArchive; return; } FString dirPath = DestFolder; NName::NormalizeDirPathPrefix(dirPath); if (!CreateComplexDir(dirPath)) { ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, fs2us(dirPath)); Result = E_FAIL; return; } ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0); Result = ArchiveLink.GetArchive()->Extract(NULL, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); } void Process() { try { #ifndef _NO_PROGRESS CProgressCloser closer(ExtractCallbackSpec->ProgressDialog); #endif Process2(); } catch(...) { Result = E_FAIL; } } static THREAD_FUNC_DECL MyThreadFunction(void *param) { ((CThreadExtracting *)param)->Process(); return 0; } }; HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, bool showProgress, bool &isCorrupt, UString &errorMessage) { isCorrupt = false; CThreadExtracting t; t.Codecs = codecs; t.FileName = fileName; t.DestFolder = destFolder; t.ExtractCallbackSpec = new CExtractCallbackImp; t.ExtractCallback = t.ExtractCallbackSpec; #ifndef _NO_PROGRESS if (showProgress) { t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON; NWindows::CThread thread; const WRes wres = thread.Create(CThreadExtracting::MyThreadFunction, &t); if (wres != 0) return HRESULT_FROM_WIN32(wres); UString title; LangString(IDS_PROGRESS_EXTRACTING, title); t.ExtractCallbackSpec->StartProgressDialog(title, thread); } else #endif { t.Process2(); } errorMessage = t.ErrorMessage; if (errorMessage.IsEmpty()) errorMessage = t.ExtractCallbackSpec->_message; isCorrupt = t.ExtractCallbackSpec->_isCorrupt; return t.Result; } tmp41wklro_/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h0000444000175000001440000000046114357332660023454 0ustar nabijaczleweliusers// ExtractEngine.h #ifndef ZIP7_INC_EXTRACT_ENGINE_H #define ZIP7_INC_EXTRACT_ENGINE_H #include "../../UI/Common/LoadCodecs.h" HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, bool showProgress, bool &isCorrupt, UString &errorMessage); #endif tmp41wklro_/CPP/7zip/Bundles/SFXSetup/makefile0000444000175000001440000000447114576504560022253 0ustar nabijaczleweliusersPROG = 7zS.sfx MY_FIXED = 1 CFLAGS = $(CFLAGS) \ -DZ7_NO_REGISTRY \ -DZ7_EXTRACT_ONLY \ -DZ7_NO_READ_FROM_CODER \ -DZ7_SFX \ -DZ7_NO_CRYPTO \ -DZ7_NO_LONG_PATH \ -DZ7_NO_LARGE_PAGES \ CURRENT_OBJS = \ $O\SfxSetup.obj \ $O\ExtractCallbackSfx.obj \ $O\ExtractEngine.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\TextConfig.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\ResourceString.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\TimeUtils.obj \ $O\Window.obj \ WIN_CTRL_OBJS = \ $O\Dialog.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ EXPLORER_OBJS = \ $O\MyMessages.obj \ FM_OBJS = \ $O\FormatUtils.obj \ $O\ProgressDialog.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ 7Z_OBJS = \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHandler.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\LzmaDec.obj \ $O\MtDec.obj \ $O\Threads.obj \ !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/SFXSetup/resource.h0000444000175000001440000000030711564133756022544 0ustar nabijaczleweliusers#define IDI_ICON 1 #define IDS_EXTRACTION_ERROR_TITLE 7 #define IDS_EXTRACTION_ERROR_MESSAGE 8 #define IDS_CANNOT_CREATE_FOLDER 3003 #define IDS_PROGRESS_EXTRACTING 3300 tmp41wklro_/CPP/7zip/Bundles/SFXSetup/resource.rc0000444000175000001440000000064311564134451022715 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" #include "resource.h" MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx") IDI_ICON ICON "setup.ico" STRINGTABLE BEGIN IDS_EXTRACTION_ERROR_TITLE "Extraction Failed" IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt" IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" IDS_PROGRESS_EXTRACTING "Extracting" END #include "../../UI/FileManager/ProgressDialog.rc" tmp41wklro_/CPP/7zip/Bundles/SFXSetup/setup.ico0000444000175000001440000000206607431022522022366 0ustar nabijaczleweliusers è&(( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿƒ33333330{{{{{{{3·······30{{{{{{{33·······330{{{{{{{330·······330{{{{{{{330·······330{{{{{{{330ˆˆ€ƒ333333330ww€33?ÿÿÿÿÿ030ÿ÷€ƒ3?ÿÿÿÿÿó0ÿ÷€7÷ó?ÿÿÿÿÿó00ÿ÷€ƒ33333333ÿ÷€÷÷óÿÿÿÿÿÿó0ÿ÷€?7ˆˆÿøˆÿ3÷€ó‡ÿÿÿÿÿÿÿó÷€0‡ðÿÿDOÿð0÷€‡ÿöfOÿDD÷€‡ù±ÿÿnoÿüä÷€‡ù‘ÿÿfoÿüÄ÷€‡ÿÿÿÿÿÿÿÿÿ÷€‡ˆˆˆˆˆˆˆˆˆˆ‡€‡wwwwwwwwwww€‡DDDDDD@€‡DDDDDDGpwp€‡DDDDDDGpwp€‡DDDDDDDDDDD€‡wwwwwwwwwww€ˆˆˆˆˆˆˆˆˆˆˆˆ€ðÿðÿðÿðÿðð?ð?ð?ð?ðððàÀ€€Ààôüüüüüüüüüüüü( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿƒ3330{{{3···3{{{3ƒ333€3?ÿÿ0€ƒ÷3333€?ÿÿó?€3÷w÷3€ñfôO€ùæüO€ÿÿÿÿÿ€DDD€DDDpp€ˆˆˆˆˆ€ÀÀÀÀÀÀ€€Àààààààtmp41wklro_/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp0000444000175000001440000002341114576504560023033 0ustar nabijaczleweliusers// Main.cpp #include "StdAfx.h" #include "../../../../C/DllSecur.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/TextConfig.h" #include "../../../Windows/DLL.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/FileName.h" #include "../../../Windows/NtCheck.h" #include "../../../Windows/ResourceString.h" #include "../../UI/Explorer/MyMessages.h" #include "ExtractEngine.h" #include "resource.h" using namespace NWindows; using namespace NFile; using namespace NDir; extern HINSTANCE g_hInstance; HINSTANCE g_hInstance; extern bool g_DisableUserQuestions; bool g_DisableUserQuestions; static CFSTR const kTempDirPrefix = FTEXT("7zS"); #define MY_SHELL_EXECUTE static bool ReadDataString(CFSTR fileName, LPCSTR startID, LPCSTR endID, AString &stringResult) { stringResult.Empty(); NIO::CInFile inFile; if (!inFile.Open(fileName)) return false; const size_t kBufferSize = (1 << 12); Byte buffer[kBufferSize]; const unsigned signatureStartSize = MyStringLen(startID); const unsigned signatureEndSize = MyStringLen(endID); size_t numBytesPrev = 0; bool writeMode = false; UInt64 posTotal = 0; for (;;) { if (posTotal > (1 << 20)) return (stringResult.IsEmpty()); const size_t numReadBytes = kBufferSize - numBytesPrev; size_t processedSize; if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) return false; if (processedSize == 0) return true; const size_t numBytesInBuffer = numBytesPrev + processedSize; UInt32 pos = 0; for (;;) { if (writeMode) { if (pos + signatureEndSize > numBytesInBuffer) break; if (memcmp(buffer + pos, endID, signatureEndSize) == 0) return true; const Byte b = buffer[pos]; if (b == 0) return false; stringResult += (char)b; pos++; } else { if (pos + signatureStartSize > numBytesInBuffer) break; if (memcmp(buffer + pos, startID, signatureStartSize) == 0) { writeMode = true; pos += signatureStartSize; } else pos++; } } numBytesPrev = numBytesInBuffer - pos; posTotal += pos; memmove(buffer, buffer + pos, numBytesPrev); } } static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; static struct CInstallIDInit { CInstallIDInit() { kStartID[0] = ';'; kEndID[0] = ';'; } } g_CInstallIDInit; #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; #endif static void ShowErrorMessageSpec(const UString &name) { UString message = NError::MyFormatMessage(::GetLastError()); const int pos = message.Find(L"%1"); if (pos >= 0) { message.Delete((unsigned)pos, 2); message.Insert((unsigned)pos, name); } ShowErrorMessage(NULL, message); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef UNDER_CE LPWSTR #else LPSTR #endif /* lpCmdLine */,int /* nCmdShow */) { g_hInstance = (HINSTANCE)hInstance; NT_CHECK #ifdef _WIN32 LoadSecurityDlls(); #endif // InitCommonControls(); UString archiveName, switches; #ifdef MY_SHELL_EXECUTE UString executeFile, executeParameters; #endif NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); FString fullPath; NDLL::MyGetModuleFileName(fullPath); switches.Trim(); bool assumeYes = false; if (switches.IsPrefixedBy_Ascii_NoCase("-y")) { assumeYes = true; switches = switches.Ptr(2); switches.Trim(); } AString config; if (!ReadDataString(fullPath, kStartID, kEndID, config)) { if (!assumeYes) ShowErrorMessage(L"Can't load config info"); return 1; } UString dirPrefix ("." STRING_PATH_SEPARATOR); UString appLaunched; bool showProgress = true; if (!config.IsEmpty()) { CObjectVector pairs; if (!GetTextConfig(config, pairs)) { if (!assumeYes) ShowErrorMessage(L"Config failed"); return 1; } const UString friendlyName = GetTextConfigValue(pairs, "Title"); const UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt"); const UString progress = GetTextConfigValue(pairs, "Progress"); if (progress.IsEqualTo_Ascii_NoCase("no")) showProgress = false; const int index = FindTextConfigItem(pairs, "Directory"); if (index >= 0) dirPrefix = pairs[index].String; if (!installPrompt.IsEmpty() && !assumeYes) { if (MessageBoxW(NULL, installPrompt, friendlyName, MB_YESNO | MB_ICONQUESTION) != IDYES) return 0; } appLaunched = GetTextConfigValue(pairs, "RunProgram"); #ifdef MY_SHELL_EXECUTE executeFile = GetTextConfigValue(pairs, "ExecuteFile"); executeParameters = GetTextConfigValue(pairs, "ExecuteParameters"); #endif } CTempDir tempDir; if (!tempDir.Create(kTempDirPrefix)) { if (!assumeYes) ShowErrorMessage(L"Cannot create temp folder archive"); return 1; } CCodecs *codecs = new CCodecs; CMyComPtr compressCodecsInfo = codecs; { const HRESULT result = codecs->Load(); if (result != S_OK) { ShowErrorMessage(L"Cannot load codecs"); return 1; } } const FString tempDirPath = tempDir.GetPath(); // tempDirPath = L"M:\\1\\"; // to test low disk space { bool isCorrupt = false; UString errorMessage; HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress, isCorrupt, errorMessage); if (result != S_OK) { if (!assumeYes) { if (result == S_FALSE || isCorrupt) { NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage); result = E_FAIL; } if (result != E_ABORT) { if (errorMessage.IsEmpty()) errorMessage = NError::MyFormatMessage(result); ::MessageBoxW(NULL, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); } } return 1; } } #ifndef UNDER_CE CCurrentDirRestorer currentDirRestorer; if (!SetCurrentDir(tempDirPath)) return 1; #endif HANDLE hProcess = NULL; #ifdef MY_SHELL_EXECUTE if (!executeFile.IsEmpty()) { CSysString filePath (GetSystemString(executeFile)); SHELLEXECUTEINFO execInfo; execInfo.cbSize = sizeof(execInfo); execInfo.fMask = SEE_MASK_NOCLOSEPROCESS #ifndef UNDER_CE | SEE_MASK_FLAG_DDEWAIT #endif ; execInfo.hwnd = NULL; execInfo.lpVerb = NULL; execInfo.lpFile = filePath; if (!switches.IsEmpty()) { executeParameters.Add_Space_if_NotEmpty(); executeParameters += switches; } const CSysString parametersSys (GetSystemString(executeParameters)); if (parametersSys.IsEmpty()) execInfo.lpParameters = NULL; else execInfo.lpParameters = parametersSys; execInfo.lpDirectory = NULL; execInfo.nShow = SW_SHOWNORMAL; execInfo.hProcess = NULL; /* BOOL success = */ ::ShellExecuteEx(&execInfo); UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; if (result <= 32) { if (!assumeYes) ShowErrorMessage(L"Cannot open file"); return 1; } hProcess = execInfo.hProcess; } else #endif { if (appLaunched.IsEmpty()) { appLaunched = L"setup.exe"; if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) { if (!assumeYes) ShowErrorMessage(L"Cannot find setup.exe"); return 1; } } { FString s2 = tempDirPath; NName::NormalizeDirPathPrefix(s2); appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); } const UString appNameForError = appLaunched; // actually we need to rtemove parameters also appLaunched.Replace(L"%%T", fs2us(tempDirPath)); if (!switches.IsEmpty()) { appLaunched.Add_Space(); appLaunched += switches; } STARTUPINFO startupInfo; startupInfo.cb = sizeof(startupInfo); startupInfo.lpReserved = NULL; startupInfo.lpDesktop = NULL; startupInfo.lpTitle = NULL; startupInfo.dwFlags = 0; startupInfo.cbReserved2 = 0; startupInfo.lpReserved2 = NULL; PROCESS_INFORMATION processInformation; const CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched)); const BOOL createResult = CreateProcess(NULL, appLaunchedSys.Ptr_non_const(), NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */, &startupInfo, &processInformation); if (createResult == 0) { if (!assumeYes) { // we print name of exe file, if error message is // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application". ShowErrorMessageSpec(appNameForError); } return 1; } ::CloseHandle(processInformation.hThread); hProcess = processInformation.hProcess; } if (hProcess) { WaitForSingleObject(hProcess, INFINITE); ::CloseHandle(hProcess); } return 0; } tmp41wklro_/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp0000444000175000001440000004747714573273220022752 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 CFG=SFXSetup - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "SFXSetup.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "SFXSetup.mak" CFG="SFXSetup - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "SFXSetup - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 # ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "SFXSetup - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "SFXSetup - Win32 ReleaseD" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseD" # PROP BASE Intermediate_Dir "ReleaseD" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseD" # PROP Intermediate_Dir "ReleaseD" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe" # SUBTRACT BASE LINK32 /debug /nodefaultlib # ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ENDIF # Begin Target # Name "SFXSetup - Win32 Release" # Name "SFXSetup - Win32 Debug" # Name "SFXSetup - Win32 ReleaseD" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Interface" # PROP Default_Filter "" # End Group # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\DeltaFilter.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\TextConfig.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\TextConfig.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Group "Control" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Control\Dialog.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\Dialog.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ResourceString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ResourceString.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Window.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Window.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "UI" # PROP Default_Filter "" # Begin Group "Explorer" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Explorer\MyMessages.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Explorer\MyMessages.h # End Source File # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # End Group # End Group # Begin Group "File Manager" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\FileManager\FormatUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\FormatUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\LangUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ProgressDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ProgressDialog.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrcOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zStream.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "7zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # End Group # Begin Source File SOURCE=.\ExtractCallbackSfx.cpp # End Source File # Begin Source File SOURCE=.\ExtractCallbackSfx.h # End Source File # Begin Source File SOURCE=.\ExtractEngine.cpp # End Source File # Begin Source File SOURCE=.\ExtractEngine.h # End Source File # Begin Source File SOURCE=.\setup.ico # End Source File # Begin Source File SOURCE=.\SfxSetup.cpp # End Source File # End Target # End Project tmp41wklro_/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw0000444000175000001440000000103307424113776022741 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp0000444000175000001440000000004610144137330022422 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/SFXSetup/StdAfx.h0000444000175000001440000000023714401434060022071 0ustar nabijaczleweliusers// StdAfx.h #if _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../UI/FileManager/StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/SFXWin/0000700000175000001440000000000014706260545020167 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Bundles/SFXWin/7z.ico0000444000175000001440000000206607723131552021233 0ustar nabijaczleweliusers è&(( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿðÿÿÿðÿðÿÿÿÿÿðÿðÿÿÿÿÿðÿðÿðÿÿÿÿðÿðÿÿÿÿÿðÿðÿÿðÿÿÿðÿÿÿÿÿÿðÿðÿÿÿðÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿððÿÿðÿððÿðððÿðÿðÿÿÿÿðÿÿðÿÿÿÿÿÿðÿÿÿÿÿÿÿÿtmp41wklro_/CPP/7zip/Bundles/SFXWin/makefile0000444000175000001440000000613714574554260021711 0ustar nabijaczleweliusersPROG = 7z.sfx MY_FIXED = 1 CFLAGS = $(CFLAGS) \ -DZ7_NO_REGISTRY \ -DZ7_EXTRACT_ONLY \ -DZ7_NO_READ_FROM_CODER \ -DZ7_SFX \ -DZ7_NO_LONG_PATH \ -DZ7_NO_LARGE_PAGES \ !IFDEF UNDER_CE LIBS = $(LIBS) ceshell.lib Commctrl.lib !ELSE LIBS = $(LIBS) comctl32.lib comdlg32.lib !ENDIF CURRENT_OBJS = \ $O\SfxWin.obj \ GUI_OBJS = \ $O\ExtractDialog.obj \ $O\ExtractGUI.obj \ COMMON_OBJS = \ $O\CRC.obj \ $O\CommandLineParser.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\Clipboard.obj \ $O\CommonDialog.obj \ $O\DLL.obj \ $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryGlobal.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\ResourceString.obj \ $O\Shell.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\TimeUtils.obj \ $O\Window.obj \ WIN_CTRL_OBJS = \ $O\ComboBox.obj \ $O\Dialog.obj \ $O\ListView.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\CWrappers.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ EXPLORER_OBJS = \ $O\MyMessages.obj \ FM_OBJS = \ $O\BrowseDialog.obj \ $O\ComboDialog.obj \ $O\ExtractCallback.obj \ $O\FormatUtils.obj \ $O\OverwriteDialog.obj \ $O\PasswordDialog.obj \ $O\ProgressDialog2.obj \ $O\PropertyName.obj \ $O\SysIconUtils.obj \ AR_OBJS = \ $O\SplitHandler.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ 7Z_OBJS = \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHandler.obj \ $O\7zIn.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ $O\PpmdDecoder.obj \ $O\PpmdRegister.obj \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\MyAes.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\Lzma2DecMt.obj \ $O\LzmaDec.obj \ $O\MtDec.obj \ $O\Ppmd7.obj \ $O\Ppmd7Dec.obj \ $O\Threads.obj \ !include "../../Aes.mak" !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/Bundles/SFXWin/resource.h0000444000175000001440000000002511564134261022166 0ustar nabijaczleweliusers#define IDI_ICON 1 tmp41wklro_/CPP/7zip/Bundles/SFXWin/resource.rc0000444000175000001440000000322414353073020022341 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" #include "../../GuiCommon.rc" #include "../../UI/GUI/ExtractDialogRes.h" #include "../../UI/FileManager/PropertyNameRes.h" #include "resource.h" MY_VERSION_INFO_APP("7z SFX", "7z.sfx") #define xc 240 #define yc 64 IDI_ICON ICON "7z.ico" IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "7-Zip self-extracting archive" BEGIN LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 EDITTEXT IDC_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys END #ifdef UNDER_CE #undef xc #define xc 144 IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "7-Zip self-extracting archive" BEGIN LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8 EDITTEXT IDC_EXTRACT_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys END #endif #include "../../UI/FileManager/OverwriteDialog.rc" #include "../../UI/FileManager/PasswordDialog.rc" #include "../../UI/FileManager/ProgressDialog2.rc" #include "../../UI/GUI/Extract.rc" STRINGTABLE DISCARDABLE BEGIN IDS_PROP_MTIME "Modified" END #ifndef UNDER_CE 1 24 MOVEABLE PURE "../../UI/GUI/7zG.exe.manifest" #endif tmp41wklro_/CPP/7zip/Bundles/SFXWin/SfxWin.cpp0000444000175000001440000001452514574554260022133 0ustar nabijaczleweliusers// Main.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif #include "../../../../C/DllSecur.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/NtCheck.h" #include "../../../Windows/ResourceString.h" #include "../../ICoder.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../../UI/Common/Extract.h" #include "../../UI/Common/ExitCode.h" #include "../../UI/Explorer/MyMessages.h" #include "../../UI/FileManager/MyWindowsNew.h" #include "../../UI/GUI/ExtractGUI.h" #include "../../UI/GUI/ExtractRes.h" using namespace NWindows; using namespace NFile; using namespace NDir; extern HINSTANCE g_hInstance; HINSTANCE g_hInstance; extern bool g_DisableUserQuestions; bool g_DisableUserQuestions; #ifndef UNDER_CE #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // win2000 #define Z7_USE_DYN_ComCtl32Version #endif #ifdef Z7_USE_DYN_ComCtl32Version Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION static DWORD GetDllVersion(LPCTSTR dllName) { DWORD dwVersion = 0; const HINSTANCE hinstDll = LoadLibrary(dllName); if (hinstDll) { const DLLGETVERSIONPROC func_DllGetVersion = Z7_GET_PROC_ADDRESS( DLLGETVERSIONPROC, hinstDll, "DllGetVersion"); if (func_DllGetVersion) { DLLVERSIONINFO dvi; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); const HRESULT hr = func_DllGetVersion(&dvi); if (SUCCEEDED(hr)) dwVersion = (DWORD)MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); } FreeLibrary(hinstDll); } return dwVersion; } #endif #endif extern bool g_LVN_ITEMACTIVATE_Support; bool g_LVN_ITEMACTIVATE_Support = true; static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!"; static void ErrorMessageForHRESULT(HRESULT res) { ShowErrorMessage(HResultToMessage(res)); } static int APIENTRY WinMain2() { // OleInitialize is required for ProgressBar in TaskBar. #ifndef UNDER_CE OleInitialize(NULL); #endif #ifndef UNDER_CE #ifdef Z7_USE_DYN_ComCtl32Version { const DWORD g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); } #endif #endif UString password; bool assumeYes = false; bool outputFolderDefined = false; FString outputFolder; UStringVector commandStrings; NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif FOR_VECTOR (i, commandStrings) { const UString &s = commandStrings[i]; if (s.Len() > 1 && s[0] == '-') { const wchar_t c = MyCharLower_Ascii(s[1]); if (c == 'y') { assumeYes = true; if (s.Len() != 2) { ShowErrorMessage(L"Bad command"); return 1; } } else if (c == 'o') { outputFolder = us2fs(s.Ptr(2)); NName::NormalizeDirPathPrefix(outputFolder); outputFolderDefined = !outputFolder.IsEmpty(); } else if (c == 'p') { password = s.Ptr(2); } } } g_DisableUserQuestions = assumeYes; FString path; NDLL::MyGetModuleFileName(path); FString fullPath; if (!MyGetFullPathName(path, fullPath)) { ShowErrorMessage(L"Error 1329484"); return 1; } CCodecs *codecs = new CCodecs; CMyComPtr compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) { ErrorMessageForHRESULT(result); return 1; } // COpenCallbackGUI openCallback; // openCallback.PasswordIsDefined = !password.IsEmpty(); // openCallback.Password = password; CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr extractCallback = ecs; ecs->Init(); #ifndef Z7_NO_CRYPTO ecs->PasswordIsDefined = !password.IsEmpty(); ecs->Password = password; #endif CExtractOptions eo; FString dirPrefix; if (!GetOnlyDirPrefix(path, dirPrefix)) { ShowErrorMessage(L"Error 1329485"); return 1; } eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; eo.YesToAll = assumeYes; eo.OverwriteMode = assumeYes ? NExtract::NOverwriteMode::kOverwrite : NExtract::NOverwriteMode::kAsk; eo.PathMode = NExtract::NPathMode::kFullPaths; eo.TestMode = false; UStringVector v1, v2; v1.Add(fs2us(fullPath)); v2.Add(fs2us(fullPath)); NWildcard::CCensorNode wildcardCensor; wildcardCensor.Add_Wildcard(); bool messageWasDisplayed = false; result = ExtractGUI(codecs, CObjectVector(), CIntVector(), v1, v2, wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs); if (result == S_OK) { if (!ecs->IsOK()) return NExitCode::kFatalError; return 0; } if (result == E_ABORT) return NExitCode::kUserBreak; if (!messageWasDisplayed) { if (result == S_FALSE) ShowErrorMessage(L"Error in archive"); else ErrorMessageForHRESULT(result); } if (result == E_OUTOFMEMORY) return NExitCode::kMemoryError; return NExitCode::kFatalError; } #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError; #endif int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef UNDER_CE LPWSTR #else LPSTR #endif /* lpCmdLine */, int /* nCmdShow */) { g_hInstance = (HINSTANCE)hInstance; NT_CHECK try { #ifdef _WIN32 LoadSecurityDlls(); #endif return WinMain2(); } catch(const CNewException &) { ErrorMessageForHRESULT(E_OUTOFMEMORY); return NExitCode::kMemoryError; } catch(...) { ShowErrorMessage(kUnknownExceptionMessage); return NExitCode::kFatalError; } } tmp41wklro_/CPP/7zip/Bundles/SFXWin/SFXWin.dsp0000444000175000001440000005772414573273220022040 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="SFXWin" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 CFG=SFXWin - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "SFXWin.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "SFXWin.mak" CFG="SFXWin - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "SFXWin - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "SFXWin - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "SFXWin - Win32 ReleaseD" (based on "Win32 (x86) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "SFXWin - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "SFXWin - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zsfx.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "SFXWin - Win32 ReleaseD" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "SFXWin___Win32_ReleaseD" # PROP BASE Intermediate_Dir "SFXWin___Win32_ReleaseD" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "SFXWin___Win32_ReleaseD" # PROP Intermediate_Dir "SFXWin___Win32_ReleaseD" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zD.sfx" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ENDIF # Begin Target # Name "SFXWin - Win32 Release" # Name "SFXWin - Win32 Debug" # Name "SFXWin - Win32 ReleaseD" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\SplitHandler.cpp # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\DeltaFilter.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdRegister.cpp # End Source File # End Group # Begin Group "Crypto" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Crypto\7zAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAes.h # End Source File # Begin Source File SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.h # End Source File # End Group # Begin Group "Dialogs" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\FileManager\BrowseDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\BrowseDialog.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ComboDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ComboDialog.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\OverwriteDialog.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\PasswordDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\PasswordDialog.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ProgressDialog2.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CWrappers.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "File Manager" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\FileManager\ExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\ExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\FormatUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\FormatUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\PropertyName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\PropertyName.h # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\SysIconUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\FileManager\SysIconUtils.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Group "Control" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Control\ComboBox.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\ComboBox.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\Dialog.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\Dialog.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\ListView.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Control\ListView.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\Windows\Clipboard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Clipboard.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\CommonDialog.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\CommonDialog.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ErrorMsg.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryGlobal.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryGlobal.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\ResourceString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\ResourceString.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Shell.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Shell.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Window.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Window.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Sha256Prepare.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "UI" # PROP Default_Filter "" # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # End Group # Begin Group "GUI" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\GUI\ExtractDialog.cpp # End Source File # Begin Source File SOURCE=..\..\UI\GUI\ExtractDialog.h # End Source File # Begin Source File SOURCE=..\..\UI\GUI\ExtractGUI.cpp # End Source File # Begin Source File SOURCE=..\..\UI\GUI\ExtractGUI.h # End Source File # End Group # Begin Group "Explorer" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Explorer\MyMessages.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Explorer\MyMessages.h # End Source File # End Group # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrcOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zStream.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Aes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\AesOpt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\DllSecur.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Lzma2DecMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\MtDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Ppmd7Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Sha256Opt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "7zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # End Group # Begin Source File SOURCE=.\7z.ico # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\SfxWin.cpp # End Source File # End Target # End Project tmp41wklro_/CPP/7zip/Bundles/SFXWin/SFXWin.dsw0000444000175000001440000000102707355211612022025 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "SFXWin"=.\SFXWin.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/Bundles/SFXWin/StdAfx.cpp0000444000175000001440000000004610144137330022057 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Bundles/SFXWin/StdAfx.h0000444000175000001440000000023714401434060021526 0ustar nabijaczleweliusers// StdAfx.h #if _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../UI/FileManager/StdAfx.h" tmp41wklro_/CPP/7zip/cmpl_clang.mak0000444000175000001440000000012114042311514020232 0ustar nabijaczleweliusersinclude ../../var_clang.mak include ../../warn_clang.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_clang_arm64.mak0000444000175000001440000000012714027041460021254 0ustar nabijaczleweliusersinclude ../../var_clang_arm64.mak include ../../warn_clang.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_clang_x64.mak0000444000175000001440000000012514022133325020737 0ustar nabijaczleweliusersinclude ../../var_clang_x64.mak include ../../warn_clang.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_clang_x86.mak0000444000175000001440000000012514022133341020741 0ustar nabijaczleweliusersinclude ../../var_clang_x86.mak include ../../warn_clang.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_gcc.mak0000444000175000001440000000011514030612262017706 0ustar nabijaczleweliusersinclude ../../var_gcc.mak include ../../warn_gcc.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_gcc_arm64.mak0000444000175000001440000000012314042311555020722 0ustar nabijaczleweliusersinclude ../../var_gcc_arm64.mak include ../../warn_gcc.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_gcc_x64.mak0000444000175000001440000000012114022133533020404 0ustar nabijaczleweliusersinclude ../../var_gcc_x64.mak include ../../warn_gcc.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_gcc_x86.mak0000444000175000001440000000012114022133536020413 0ustar nabijaczleweliusersinclude ../../var_gcc_x86.mak include ../../warn_gcc.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_mac_arm64.mak0000444000175000001440000000013114041756754020742 0ustar nabijaczleweliusersinclude ../../var_mac_arm64.mak include ../../warn_clang_mac.mak include makefile.gcc tmp41wklro_/CPP/7zip/cmpl_mac_x64.mak0000444000175000001440000000012714041757052020427 0ustar nabijaczleweliusersinclude ../../var_mac_x64.mak include ../../warn_clang_mac.mak include makefile.gcc tmp41wklro_/CPP/7zip/Common/0000700000175000001440000000000014706260545016705 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Common/CreateCoder.cpp0000444000175000001440000003215314405323700021572 0ustar nabijaczleweliusers// CreateCoder.cpp #include "StdAfx.h" #include "../../Windows/Defs.h" #include "../../Windows/PropVariant.h" #include "CreateCoder.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned kNumCodecsMax = 64; extern unsigned g_NumCodecs; unsigned g_NumCodecs = 0; extern const CCodecInfo *g_Codecs[]; const CCodecInfo *g_Codecs[kNumCodecsMax]; // We use g_ExternalCodecs in other stages. #ifdef Z7_EXTERNAL_CODECS /* extern CExternalCodecs g_ExternalCodecs; #define CHECK_GLOBAL_CODECS \ if (!_externalCodecs || !_externalCodecs->IsSet()) _externalCodecs = &g_ExternalCodecs; */ #define CHECK_GLOBAL_CODECS #endif void RegisterCodec(const CCodecInfo *codecInfo) throw() { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } static const unsigned kNumHashersMax = 16; extern unsigned g_NumHashers; unsigned g_NumHashers = 0; extern const CHasherInfo *g_Hashers[]; const CHasherInfo *g_Hashers[kNumHashersMax]; void RegisterHasher(const CHasherInfo *hashInfo) throw() { if (g_NumHashers < kNumHashersMax) g_Hashers[g_NumHashers++] = hashInfo; } #ifdef Z7_EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)) if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)) if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT CExternalCodecs::Load() { Codecs.Clear(); Hashers.Clear(); if (GetCodecs) { CCodecInfoEx info; UString s; UInt32 num; RINOK(GetCodecs->GetNumMethods(&num)) for (UInt32 i = 0; i < num; i++) { NWindows::NCOM::CPropVariant prop; RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)) if (prop.vt != VT_UI8) continue; // old Interface info.Id = prop.uhVal.QuadPart; prop.Clear(); info.Name.Empty(); RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)) if (prop.vt == VT_BSTR) info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) continue; RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams)) { UInt32 numUnpackStreams = 1; RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams)) if (numUnpackStreams != 1) continue; } RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)) RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)) RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter)) Codecs.Add(info); } } if (GetHashers) { UInt32 num = GetHashers->GetNumHashers(); CHasherInfoEx info; for (UInt32 i = 0; i < num; i++) { NWindows::NCOM::CPropVariant prop; RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)) if (prop.vt != VT_UI8) continue; info.Id = prop.uhVal.QuadPart; prop.Clear(); info.Name.Empty(); RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)) if (prop.vt == VT_BSTR) info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) continue; Hashers.Add(info); } } return S_OK; } #endif int FindMethod_Index( DECL_EXTERNAL_CODECS_LOC_VARS const AString &name, bool encode, CMethodId &methodId, UInt32 &numStreams, bool &isFilter) { unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if ((encode ? codec.CreateEncoder : codec.CreateDecoder) && StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; numStreams = codec.NumStreams; isFilter = codec.IsFilter; return (int)i; } } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) for (i = 0; i < _externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = _externalCodecs->Codecs[i]; if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned) && StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; numStreams = codec.NumStreams; isFilter = codec.IsFilter; return (int)(g_NumCodecs + i); } } #endif return -1; } static int FindMethod_Index( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode) { unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder)) return (int)i; } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) for (i = 0; i < _externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = _externalCodecs->Codecs[i]; if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)) return (int)(g_NumCodecs + i); } #endif return -1; } bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, AString &name) { name.Empty(); unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) for (i = 0; i < _externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = _externalCodecs->Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } bool FindHashMethod( DECL_EXTERNAL_CODECS_LOC_VARS const AString &name, CMethodId &methodId) { unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) for (i = 0; i < _externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = _externalCodecs->Hashers[i]; if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } #endif return false; } void GetHashMethods( DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector &methods) { methods.ClearAndSetSize(g_NumHashers); unsigned i; for (i = 0; i < g_NumHashers; i++) methods[i] = (*g_Hashers[i]).Id; #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) for (i = 0; i < _externalCodecs->Hashers.Size(); i++) methods.Add(_externalCodecs->Hashers[i].Id); #endif } HRESULT CreateCoder_Index( DECL_EXTERNAL_CODECS_LOC_VARS unsigned i, bool encode, CMyComPtr &filter, CCreatedCoder &cod) { cod.IsExternal = false; cod.IsFilter = false; cod.NumStreams = 1; if (i < g_NumCodecs) { const CCodecInfo &codec = *g_Codecs[i]; // if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } return S_OK; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } return S_OK; } } } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (_externalCodecs) { i -= g_NumCodecs; cod.IsExternal = true; if (i < _externalCodecs->Codecs.Size()) { const CCodecInfoEx &codec = _externalCodecs->Codecs[i]; // if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.NumStreams == 1) { const HRESULT res = _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder); if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) return res; if (cod.Coder) return res; return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter); } cod.NumStreams = codec.NumStreams; return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } else if (codec.DecoderIsAssigned) { if (codec.NumStreams == 1) { const HRESULT res = _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder); if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) return res; if (cod.Coder) return res; return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter); } cod.NumStreams = codec.NumStreams; return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } } } #endif return S_OK; } HRESULT CreateCoder_Index( DECL_EXTERNAL_CODECS_LOC_VARS unsigned index, bool encode, CCreatedCoder &cod) { CMyComPtr filter; const HRESULT res = CreateCoder_Index( EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod); if (filter) { cod.IsFilter = true; CFilterCoder *coderSpec = new CFilterCoder(encode); cod.Coder = coderSpec; coderSpec->Filter = filter; } return res; } HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &filter, CCreatedCoder &cod) { const int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode); if (index < 0) return S_OK; return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod); } HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CCreatedCoder &cod) { CMyComPtr filter; const HRESULT res = CreateCoder_Id( EXTERNAL_CODECS_LOC_VARS methodId, encode, filter, cod); if (filter) { cod.IsFilter = true; CFilterCoder *coderSpec = new CFilterCoder(encode); cod.Coder = coderSpec; coderSpec->Filter = filter; } return res; } HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &coder) { CCreatedCoder cod; const HRESULT res = CreateCoder_Id( EXTERNAL_CODECS_LOC_VARS methodId, encode, cod); coder = cod.Coder; return res; } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &filter) { CCreatedCoder cod; return CreateCoder_Id( EXTERNAL_CODECS_LOC_VARS methodId, encode, filter, cod); } HRESULT CreateHasher( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, AString &name, CMyComPtr &hasher) { name.Empty(); unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; if (codec.Id == methodId) { hasher = codec.CreateHasher(); name = codec.Name; break; } } #ifdef Z7_EXTERNAL_CODECS CHECK_GLOBAL_CODECS if (!hasher && _externalCodecs) for (i = 0; i < _externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = _externalCodecs->Hashers[i]; if (codec.Id == methodId) { name = codec.Name; return _externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher); } } #endif return S_OK; } tmp41wklro_/CPP/7zip/Common/CreateCoder.h0000444000175000001440000001262314405323700021237 0ustar nabijaczleweliusers// CreateCoder.h #ifndef ZIP7_INC_CREATE_CODER_H #define ZIP7_INC_CREATE_CODER_H #include "../../Common/MyCom.h" #include "../../Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" /* if Z7_EXTERNAL_CODECS is not defined, the code supports only codecs that are statically linked at compile-time and link-time. if Z7_EXTERNAL_CODECS is defined, the code supports also codecs from another executable modules, that can be linked dynamically at run-time: - EXE module can use codecs from external DLL files. - DLL module can use codecs from external EXE and DLL files. CExternalCodecs contains information about codecs and interfaces to create them. The order of codecs: 1) Internal codecs 2) External codecs */ #ifdef Z7_EXTERNAL_CODECS struct CCodecInfoEx { CMethodId Id; AString Name; UInt32 NumStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsFilter; // it's unused CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false), IsFilter(false) {} }; struct CHasherInfoEx { CMethodId Id; AString Name; }; #define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC \ public ISetCompressCodecsInfo, #define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC \ Z7_COM_QI_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo \ Z7_COM7F_IMP(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) #define IMPL_ISetCompressCodecsInfo2(cls) \ Z7_COM7F_IMF(cls::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) \ { COM_TRY_BEGIN _externalCodecs.GetCodecs = compressCodecsInfo; \ return _externalCodecs.Load(); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) struct CExternalCodecs { CMyComPtr GetCodecs; CMyComPtr GetHashers; CObjectVector Codecs; CObjectVector Hashers; bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; } HRESULT Load(); void ClearAndRelease() { Hashers.Clear(); Codecs.Clear(); GetHashers.Release(); GetCodecs.Release(); } ~CExternalCodecs() { GetHashers.Release(); GetCodecs.Release(); } }; extern CExternalCodecs g_ExternalCodecs; #define EXTERNAL_CODECS_VARS2 (_externalCodecs.IsSet() ? &_externalCodecs : &g_ExternalCodecs) #define EXTERNAL_CODECS_VARS2_L (&_externalCodecs) #define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs) #define DECL_EXTERNAL_CODECS_VARS CExternalCodecs _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L, #define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G, #define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *_externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS_DECL DECL_EXTERNAL_CODECS_LOC_VARS2; #define EXTERNAL_CODECS_LOC_VARS2 _externalCodecs #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC #define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS_L #define EXTERNAL_CODECS_VARS_G #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define DECL_EXTERNAL_CODECS_LOC_VARS_DECL #define EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS #endif int FindMethod_Index( DECL_EXTERNAL_CODECS_LOC_VARS const AString &name, bool encode, CMethodId &methodId, UInt32 &numStreams, bool &isFilter); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, AString &name); bool FindHashMethod( DECL_EXTERNAL_CODECS_LOC_VARS const AString &name, CMethodId &methodId); void GetHashMethods( DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector &methods); struct CCreatedCoder { CMyComPtr Coder; CMyComPtr Coder2; bool IsExternal; bool IsFilter; // = true, if Coder was created from filter UInt32 NumStreams; // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {} }; HRESULT CreateCoder_Index( DECL_EXTERNAL_CODECS_LOC_VARS unsigned codecIndex, bool encode, CMyComPtr &filter, CCreatedCoder &cod); HRESULT CreateCoder_Index( DECL_EXTERNAL_CODECS_LOC_VARS unsigned index, bool encode, CCreatedCoder &cod); HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &filter, CCreatedCoder &cod); HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CCreatedCoder &cod); HRESULT CreateCoder_Id( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &coder); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, bool encode, CMyComPtr &filter); HRESULT CreateHasher( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, AString &name, CMyComPtr &hasher); #endif tmp41wklro_/CPP/7zip/Common/CWrappers.cpp0000444000175000001440000002006614567042400021324 0ustar nabijaczleweliusers// CWrappers.c #include "StdAfx.h" #include "../../../C/Alloc.h" #include "CWrappers.h" #include "StreamUtils.h" SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw() { switch (res) { case S_OK: return SZ_OK; case E_OUTOFMEMORY: return SZ_ERROR_MEM; case E_INVALIDARG: return SZ_ERROR_PARAM; case E_ABORT: return SZ_ERROR_PROGRESS; case S_FALSE: return SZ_ERROR_DATA; case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; default: break; } return defaultRes; } HRESULT SResToHRESULT(SRes res) throw() { switch (res) { case SZ_OK: return S_OK; case SZ_ERROR_DATA: case SZ_ERROR_CRC: case SZ_ERROR_INPUT_EOF: case SZ_ERROR_ARCHIVE: case SZ_ERROR_NO_ARCHIVE: return S_FALSE; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_OUTPUT_EOF: // case SZ_ERROR_READ: // case SZ_ERROR_WRITE: // case SZ_ERROR_THREAD: // case SZ_ERROR_ARCHIVE: // case SZ_ERROR_NO_ARCHIVE: // return E_FAIL; default: break; } if (res < 0) return res; return E_FAIL; } #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) static SRes CompressProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) throw() { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CCompressProgressWrap) p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw() { vt.Progress = CompressProgress; Progress = progress; Res = SZ_OK; } static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(ISeqInStreamPtr pp, void *data, size_t *size) throw() { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInStreamWrap) UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = (p->Stream->Read(data, curSize, &curSize)); *size = curSize; p->Processed += curSize; if (p->Res == S_OK) return SZ_OK; return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); } static size_t MyWrite(ISeqOutStreamPtr pp, const void *data, size_t size) throw() { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqOutStreamWrap) if (p->Stream) { p->Res = WriteStream(p->Stream, data, size); if (p->Res != 0) return 0; } else p->Res = S_OK; p->Processed += size; return size; } void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw() { vt.Read = MyRead; Stream = stream; Processed = 0; Res = S_OK; } void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw() { vt.Write = MyWrite; Stream = stream; Res = SZ_OK; Processed = 0; } static SRes InStreamWrap_Read(ISeekInStreamPtr pp, void *data, size_t *size) throw() { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap) UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = p->Stream->Read(data, curSize, &curSize); *size = curSize; return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } static SRes InStreamWrap_Seek(ISeekInStreamPtr pp, Int64 *offset, ESzSeek origin) throw() { Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap) UInt32 moveMethod; /* we need (int)origin to eliminate the clang warning: default label in switch which covers all enumeration values [-Wcovered-switch-default */ switch ((int)origin) { case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break; case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break; default: return SZ_ERROR_PARAM; } UInt64 newPosition; p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition); *offset = (Int64)newPosition; return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } void CSeekInStreamWrap::Init(IInStream *stream) throw() { Stream = stream; vt.Read = InStreamWrap_Read; vt.Seek = InStreamWrap_Seek; Res = S_OK; } /* ---------- CByteInBufWrap ---------- */ void CByteInBufWrap::Free() throw() { ::MidFree(Buf); Buf = NULL; } bool CByteInBufWrap::Alloc(UInt32 size) throw() { if (!Buf || size != Size) { Free(); Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); Size = size; } return (Buf != NULL); } Byte CByteInBufWrap::ReadByteFromNewBlock() throw() { if (!Extra && Res == S_OK) { UInt32 avail; Res = Stream->Read(Buf, Size, &avail); Processed += (size_t)(Cur - Buf); Cur = Buf; Lim = Buf + avail; if (avail != 0) return *Cur++; } Extra = true; return 0; } // #pragma GCC diagnostic ignored "-Winvalid-offsetof" static Byte Wrap_ReadByte(IByteInPtr pp) throw() { CByteInBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt); // Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteInBufWrap) if (p->Cur != p->Lim) return *p->Cur++; return p->ReadByteFromNewBlock(); } CByteInBufWrap::CByteInBufWrap() throw(): Buf(NULL) { vt.Read = Wrap_ReadByte; } /* ---------- CByteOutBufWrap ---------- */ /* void CLookToSequentialWrap::Free() throw() { ::MidFree(BufBase); BufBase = NULL; } bool CLookToSequentialWrap::Alloc(UInt32 size) throw() { if (!BufBase || size != Size) { Free(); BufBase = (Byte *)::MidAlloc((size_t)size); Size = size; } return (BufBase != NULL); } */ /* EXTERN_C_BEGIN void CLookToSequentialWrap_Look(ILookInSeqStreamPtr pp) { CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj; if (p->Extra || p->Res != S_OK) return; { UInt32 avail; p->Res = p->Stream->Read(p->BufBase, p->Size, &avail); p->Processed += avail; pp->Buf = p->BufBase; pp->Limit = pp->Buf + avail; if (avail == 0) p->Extra = true; } } EXTERN_C_END */ /* ---------- CByteOutBufWrap ---------- */ void CByteOutBufWrap::Free() throw() { ::MidFree(Buf); Buf = NULL; } bool CByteOutBufWrap::Alloc(size_t size) throw() { if (!Buf || size != Size) { Free(); Buf = (Byte *)::MidAlloc(size); Size = size; } return (Buf != NULL); } HRESULT CByteOutBufWrap::Flush() throw() { if (Res == S_OK) { const size_t size = (size_t)(Cur - Buf); Res = WriteStream(Stream, Buf, size); if (Res == S_OK) Processed += size; // else throw 11; } Cur = Buf; // reset pointer for later Wrap_WriteByte() return Res; } static void Wrap_WriteByte(IByteOutPtr pp, Byte b) throw() { CByteOutBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt); // Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteOutBufWrap) Byte *dest = p->Cur; *dest = b; p->Cur = ++dest; if (dest == p->Lim) p->Flush(); } CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(NULL), Size(0) { vt.Write = Wrap_WriteByte; } /* ---------- CLookOutWrap ---------- */ /* void CLookOutWrap::Free() throw() { ::MidFree(Buf); Buf = NULL; } bool CLookOutWrap::Alloc(size_t size) throw() { if (!Buf || size != Size) { Free(); Buf = (Byte *)::MidAlloc(size); Size = size; } return (Buf != NULL); } static size_t LookOutWrap_GetOutBuf(ILookOutStreamPtr pp, void **buf) throw() { CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); *buf = p->Buf; return p->Size; } static size_t LookOutWrap_Write(ILookOutStreamPtr pp, size_t size) throw() { CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); if (p->Res == S_OK && size != 0) { p->Res = WriteStream(p->Stream, p->Buf, size); if (p->Res == S_OK) { p->Processed += size; return size; } } return 0; } CLookOutWrap::CLookOutWrap() throw(): Buf(NULL), Size(0) { vt.GetOutBuf = LookOutWrap_GetOutBuf; vt.Write = LookOutWrap_Write; } */ tmp41wklro_/CPP/7zip/Common/CWrappers.h0000444000175000001440000000631714424672020020773 0ustar nabijaczleweliusers// CWrappers.h #ifndef ZIP7_INC_C_WRAPPERS_H #define ZIP7_INC_C_WRAPPERS_H #include "../ICoder.h" #include "../../Common/MyCom.h" SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw(); HRESULT SResToHRESULT(SRes res) throw(); struct CCompressProgressWrap { ICompressProgress vt; ICompressProgressInfo *Progress; HRESULT Res; void Init(ICompressProgressInfo *progress) throw(); }; struct CSeqInStreamWrap { ISeqInStream vt; ISequentialInStream *Stream; HRESULT Res; UInt64 Processed; void Init(ISequentialInStream *stream) throw(); }; struct CSeekInStreamWrap { ISeekInStream vt; IInStream *Stream; HRESULT Res; void Init(IInStream *stream) throw(); }; struct CSeqOutStreamWrap { ISeqOutStream vt; ISequentialOutStream *Stream; HRESULT Res; UInt64 Processed; void Init(ISequentialOutStream *stream) throw(); }; struct CByteInBufWrap { IByteIn vt; const Byte *Cur; const Byte *Lim; Byte *Buf; UInt32 Size; ISequentialInStream *Stream; UInt64 Processed; bool Extra; HRESULT Res; CByteInBufWrap() throw(); ~CByteInBufWrap() { Free(); } void Free() throw(); bool Alloc(UInt32 size) throw(); void Init() { Lim = Cur = Buf; Processed = 0; Extra = false; Res = S_OK; } UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { if (Cur != Lim) return *Cur++; return ReadByteFromNewBlock(); } }; /* struct CLookToSequentialWrap { Byte *BufBase; UInt32 Size; ISequentialInStream *Stream; UInt64 Processed; bool Extra; HRESULT Res; CLookToSequentialWrap(): BufBase(NULL) {} ~CLookToSequentialWrap() { Free(); } void Free() throw(); bool Alloc(UInt32 size) throw(); void Init() { // Lim = Cur = Buf; Processed = 0; Extra = false; Res = S_OK; } // UInt64 GetProcessed() const { return Processed + (Cur - Buf); } Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { if (Cur != Lim) return *Cur++; return ReadByteFromNewBlock(); } }; EXTERN_C_BEGIN // void CLookToSequentialWrap_Look(ILookInSeqStream *pp); EXTERN_C_END */ struct CByteOutBufWrap { IByteOut vt; Byte *Cur; const Byte *Lim; Byte *Buf; size_t Size; ISequentialOutStream *Stream; UInt64 Processed; HRESULT Res; CByteOutBufWrap() throw(); ~CByteOutBufWrap() { Free(); } void Free() throw(); bool Alloc(size_t size) throw(); void Init() { Cur = Buf; Lim = Buf + Size; Processed = 0; Res = S_OK; } UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } HRESULT Flush() throw(); void WriteByte(Byte b) { *Cur++ = b; if (Cur == Lim) Flush(); } }; /* struct CLookOutWrap { ILookOutStream vt; Byte *Buf; size_t Size; ISequentialOutStream *Stream; UInt64 Processed; HRESULT Res; CLookOutWrap() throw(); ~CLookOutWrap() { Free(); } void Free() throw(); bool Alloc(size_t size) throw(); void Init() { Processed = 0; Res = S_OK; } }; */ #endif tmp41wklro_/CPP/7zip/Common/FilePathAutoRename.cpp0000444000175000001440000000200514553752160023072 0ustar nabijaczleweliusers// FilePathAutoRename.cpp #include "StdAfx.h" #include "../../Windows/FileFind.h" #include "FilePathAutoRename.h" using namespace NWindows; static bool MakeAutoName(const FString &name, const FString &extension, UInt32 value, FString &path) { path = name; path.Add_UInt32(value); path += extension; return NFile::NFind::DoesFileOrDirExist(path); } bool AutoRenamePath(FString &path) { const int dotPos = path.ReverseFind_Dot(); const int slashPos = path.ReverseFind_PathSepar(); FString name = path; FString extension; if (dotPos > slashPos + 1) { name.DeleteFrom((unsigned)dotPos); extension = path.Ptr((unsigned)dotPos); } name.Add_Char('_'); FString temp; UInt32 left = 1, right = (UInt32)1 << 30; while (left != right) { const UInt32 mid = (left + right) / 2; if (MakeAutoName(name, extension, mid, temp)) left = mid + 1; else right = mid; } return !MakeAutoName(name, extension, right, path); } tmp41wklro_/CPP/7zip/Common/FilePathAutoRename.h0000444000175000001440000000032314357314620022535 0ustar nabijaczleweliusers// FilePathAutoRename.h #ifndef ZIP7_INC_FILE_PATH_AUTO_RENAME_H #define ZIP7_INC_FILE_PATH_AUTO_RENAME_H #include "../../Common/MyString.h" bool AutoRenamePath(FString &fullProcessedPath); #endif tmp41wklro_/CPP/7zip/Common/FileStreams.cpp0000444000175000001440000005654414567042400021646 0ustar nabijaczleweliusers// FileStreams.cpp #include "StdAfx.h" // #include #ifndef _WIN32 #include #include #include #include #include /* inclusion of by is deprecated since glibc 2.25. Since glibc 2.3.3, macros have been aliases for three GNU-specific functions: gnu_dev_makedev(), gnu_dev_major(), and gnu_dev_minor() Warning in GCC: In the GNU C Library, "major" is defined by . For historical compatibility, it is currently defined by as well, but we plan to remove this soon. To use "major", include directly. If you did not intend to use a system-defined macro "major", you should undefine it after including */ // for major()/minor(): #if defined(__APPLE__) || defined(__DragonFly__) || \ defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #endif // _WIN32 #include "../../Windows/FileFind.h" #ifdef Z7_DEVICE_FILE #include "../../../C/Alloc.h" #include "../../Common/Defs.h" #endif #include "../PropID.h" #include "FileStreams.h" static inline HRESULT GetLastError_HRESULT() { DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); } static inline HRESULT ConvertBoolToHRESULT(bool result) { if (result) return S_OK; return GetLastError_HRESULT(); } #ifdef Z7_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; #endif CInFileStream::CInFileStream(): #ifdef Z7_DEVICE_FILE VirtPos(0), PhyPos(0), Buf(NULL), BufSize(0), #endif #ifndef _WIN32 _uid(0), _gid(0), StoreOwnerId(false), StoreOwnerName(false), #endif _info_WasLoaded(false), SupportHardLinks(false), Callback(NULL), CallbackRef(0) { } CInFileStream::~CInFileStream() { #ifdef Z7_DEVICE_FILE MidFree(Buf); #endif if (Callback) Callback->InFileStream_On_Destroy(this, CallbackRef); } Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { // printf("\nCInFileStream::Read size=%d, VirtPos=%8d\n", (unsigned)size, (int)VirtPos); #ifdef Z7_FILE_STREAMS_USE_WIN_FILE #ifdef Z7_DEVICE_FILE if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (File.IsDeviceFile) { if (File.SizeDefined) { if (VirtPos >= File.Size) return VirtPos == File.Size ? S_OK : E_FAIL; const UInt64 rem = File.Size - VirtPos; if (size > rem) size = (UInt32)rem; } for (;;) { const UInt32 mask = kClusterSize - 1; const UInt64 mask2 = ~(UInt64)mask; const UInt64 alignedPos = VirtPos & mask2; if (BufSize > 0 && BufStartPos == alignedPos) { const UInt32 pos = (UInt32)VirtPos & mask; if (pos >= BufSize) return S_OK; const UInt32 rem = MyMin(BufSize - pos, size); memcpy(data, Buf + pos, rem); VirtPos += rem; if (processedSize) *processedSize += rem; return S_OK; } bool useBuf = false; if ((VirtPos & mask) != 0 || ((size_t)(ptrdiff_t)data & mask) != 0 ) useBuf = true; else { UInt64 end = VirtPos + size; if ((end & mask) != 0) { end &= mask2; if (end <= VirtPos) useBuf = true; else size = (UInt32)(end - VirtPos); } } if (!useBuf) break; if (alignedPos != PhyPos) { UInt64 realNewPosition; const bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = realNewPosition; } BufStartPos = alignedPos; UInt32 readSize = kClusterSize; if (File.SizeDefined) readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); if (!Buf) { Buf = (Byte *)MidAlloc(kClusterSize); if (!Buf) return E_OUTOFMEMORY; } const bool result = File.Read1(Buf, readSize, BufSize); if (!result) return ConvertBoolToHRESULT(result); if (BufSize == 0) return S_OK; PhyPos += BufSize; } if (VirtPos != PhyPos) { UInt64 realNewPosition; bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = VirtPos = realNewPosition; } } #endif UInt32 realProcessedSize; const bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; #ifdef Z7_DEVICE_FILE VirtPos += realProcessedSize; PhyPos += realProcessedSize; #endif if (result) return S_OK; #else // Z7_FILE_STREAMS_USE_WIN_FILE if (processedSize) *processedSize = 0; const ssize_t res = File.read_part(data, (size_t)size); if (res != -1) { if (processedSize) *processedSize = (UInt32)res; return S_OK; } #endif // Z7_FILE_STREAMS_USE_WIN_FILE { const DWORD error = ::GetLastError(); #if 0 if (File.IsStdStream && error == ERROR_BROKEN_PIPE) return S_OK; // end of stream #endif if (Callback) return Callback->InFileStream_On_Error(CallbackRef, error); if (error == 0) return E_FAIL; return HRESULT_FROM_WIN32(error); } } #ifdef UNDER_CE Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { size_t s2 = fread(data, 1, size, stdin); int error = ferror(stdin); if (processedSize) *processedSize = s2; if (s2 <= size && error == 0) return S_OK; return E_FAIL; } #else Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { // printf("\nCStdInFileStream::Read size = %d\n", (unsigned)size); #ifdef _WIN32 DWORD realProcessedSize; UInt32 sizeTemp = (1 << 20); if (sizeTemp > size) sizeTemp = size; /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL, and it doesn't set LastError. */ /* SetLastError(0); const HANDLE h = GetStdHandle(STD_INPUT_HANDLE); if (!h || h == INVALID_HANDLE_VALUE) { if (processedSize) *processedSize = 0; if (GetLastError() == 0) SetLastError(ERROR_INVALID_HANDLE); return GetLastError_noZero_HRESULT(); } */ BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); /* printf("\nCInFileStream::Read: size=%d, processed=%8d res=%d 4rror=%3d\n", (unsigned)size, (int)realProcessedSize, (int)res, GetLastError()); */ if (processedSize) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if (processedSize) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return GetLastError_HRESULT(); if (processedSize) *processedSize = (UInt32)res; return S_OK; #endif } #endif /* bool CreateStdInStream(CMyComPtr &str) { #if 0 CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec);; if (!inStreamSpec->OpenStdIn()) return false; if (!inStreamSpec->File.IsStdPipeStream) str = inStreamLoc.Detach(); else #endif str = new CStdInFileStream; return true; } */ #if 0 bool CInFileStream::OpenStdIn() { _info_WasLoaded = false; // Sleep(100); bool res = File.AttachStdIn(); if (!res) return false; #if 1 CStreamFileProps props; if (GetProps2(&props) != S_OK) { // we can ignore that error return false; } // we can't use Size, because Size can be set for pipe streams for some value. // Seek() sees only current chunk in pipe buffer. // So Seek() can move across only current unread chunk. // But after reading that chunk. it can't move position back. // We need safe check that shows that we can use seek (non-pipe mode) // Is it safe check that shows that pipe mode was used? File.IsStdPipeStream = (props.VolID == 0); // && FILETIME_IsZero(props.CTime) // && FILETIME_IsZero(props.ATime) // && FILETIME_IsZero(props.MTime); #endif // printf("\n######## pipe=%d", (unsigned)File.IsStdPipeStream); return true; } #endif Z7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { /* printf("\nCInFileStream::Seek seekOrigin=%d, offset=%8d, VirtPos=%8d\n", (unsigned)seekOrigin, (int)offset, (int)VirtPos); */ if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef Z7_FILE_STREAMS_USE_WIN_FILE #ifdef Z7_DEVICE_FILE if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += VirtPos; break; case STREAM_SEEK_END: offset += File.Size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; VirtPos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } #endif UInt64 realNewPosition = 0; const bool result = File.Seek(offset, seekOrigin, realNewPosition); const HRESULT hres = ConvertBoolToHRESULT(result); /* 21.07: new File.Seek() in 21.07 already returns correct (realNewPosition) in case of error. So we don't need additional code below */ // if (!result) { realNewPosition = 0; File.GetPosition(realNewPosition); } #ifdef Z7_DEVICE_FILE PhyPos = VirtPos = realNewPosition; #endif if (newPosition) *newPosition = realNewPosition; return hres; #else const off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) { const HRESULT hres = GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)File.seekToCur(); return hres; } if (newPosition) *newPosition = (UInt64)res; return S_OK; #endif } Z7_COM7F_IMF(CInFileStream::GetSize(UInt64 *size)) { return ConvertBoolToHRESULT(File.GetLength(*size)); } #ifdef Z7_FILE_STREAMS_USE_WIN_FILE Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) { if (!_info_WasLoaded) { RINOK(ReloadProps()) } const BY_HANDLE_FILE_INFORMATION &info = _info; /* BY_HANDLE_FILE_INFORMATION info; if (!File.GetFileInformation(&info)) return GetLastError_HRESULT(); */ { if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; if (cTime) *cTime = info.ftCreationTime; if (aTime) *aTime = info.ftLastAccessTime; if (mTime) *mTime = info.ftLastWriteTime; if (attrib) *attrib = info.dwFileAttributes; return S_OK; } } Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props)) { if (!_info_WasLoaded) { RINOK(ReloadProps()) } const BY_HANDLE_FILE_INFORMATION &info = _info; /* BY_HANDLE_FILE_INFORMATION info; if (!File.GetFileInformation(&info)) return GetLastError_HRESULT(); */ { props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; props->VolID = info.dwVolumeSerialNumber; props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; props->FileID_High = 0; props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; props->Attrib = info.dwFileAttributes; props->CTime = info.ftCreationTime; props->ATime = info.ftLastAccessTime; props->MTime = info.ftLastWriteTime; return S_OK; } } Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) { if (!_info_WasLoaded) { RINOK(ReloadProps()) } if (!_info_WasLoaded) return S_OK; NWindows::NCOM::CPropVariant prop; #ifdef Z7_DEVICE_FILE if (File.IsDeviceFile) { switch (propID) { case kpidSize: if (File.SizeDefined) prop = File.Size; break; // case kpidAttrib: prop = (UInt32)0; break; case kpidPosixAttrib: { prop = (UInt32)NWindows::NFile::NFind::NAttributes:: Get_PosixMode_From_WinAttrib(0); /* GNU TAR by default can't extract file with MY_LIN_S_IFBLK attribute so we don't use MY_LIN_S_IFBLK here */ // prop = (UInt32)(MY_LIN_S_IFBLK | 0600); // for debug break; } /* case kpidDeviceMajor: prop = (UInt32)8; // id for SCSI type device (sda) break; case kpidDeviceMinor: prop = (UInt32)0; break; */ } } else #endif { switch (propID) { case kpidSize: { const UInt64 size = (((UInt64)_info.nFileSizeHigh) << 32) + _info.nFileSizeLow; prop = size; break; } case kpidAttrib: prop = (UInt32)_info.dwFileAttributes; break; case kpidCTime: PropVariant_SetFrom_FiTime(prop, _info.ftCreationTime); break; case kpidATime: PropVariant_SetFrom_FiTime(prop, _info.ftLastAccessTime); break; case kpidMTime: PropVariant_SetFrom_FiTime(prop, _info.ftLastWriteTime); break; case kpidPosixAttrib: prop = (UInt32)NWindows::NFile::NFind::NAttributes:: Get_PosixMode_From_WinAttrib(_info.dwFileAttributes); // | (UInt32)(1 << 21); // for debug break; } } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CInFileStream::ReloadProps()) { #ifdef Z7_DEVICE_FILE if (File.IsDeviceFile) { memset(&_info, 0, sizeof(_info)); if (File.SizeDefined) { _info.nFileSizeHigh = (DWORD)(File.Size >> 32); _info.nFileSizeLow = (DWORD)(File.Size); } _info.nNumberOfLinks = 1; _info_WasLoaded = true; return S_OK; } #endif _info_WasLoaded = File.GetFileInformation(&_info); if (!_info_WasLoaded) return GetLastError_HRESULT(); #ifdef _WIN32 #if 0 printf( "\ndwFileAttributes = %8x" "\nftCreationTime = %8x" "\nftLastAccessTime = %8x" "\nftLastWriteTime = %8x" "\ndwVolumeSerialNumber = %8x" "\nnFileSizeHigh = %8x" "\nnFileSizeLow = %8x" "\nnNumberOfLinks = %8x" "\nnFileIndexHigh = %8x" "\nnFileIndexLow = %8x \n", (unsigned)_info.dwFileAttributes, (unsigned)_info.ftCreationTime.dwHighDateTime, (unsigned)_info.ftLastAccessTime.dwHighDateTime, (unsigned)_info.ftLastWriteTime.dwHighDateTime, (unsigned)_info.dwVolumeSerialNumber, (unsigned)_info.nFileSizeHigh, (unsigned)_info.nFileSizeLow, (unsigned)_info.nNumberOfLinks, (unsigned)_info.nFileIndexHigh, (unsigned)_info.nFileIndexLow); #endif #endif return S_OK; } #elif !defined(_WIN32) Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) { // printf("\nCInFileStream::GetProps VirtPos = %8d\n", (int)VirtPos); if (!_info_WasLoaded) { RINOK(ReloadProps()) } const struct stat &st = _info; /* struct stat st; if (File.my_fstat(&st) != 0) return GetLastError_HRESULT(); */ if (size) *size = (UInt64)st.st_size; if (cTime) FiTime_To_FILETIME (ST_CTIME(st), *cTime); if (aTime) FiTime_To_FILETIME (ST_ATIME(st), *aTime); if (mTime) FiTime_To_FILETIME (ST_MTIME(st), *mTime); if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); return S_OK; } // #include Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props)) { // printf("\nCInFileStream::GetProps2 VirtPos = %8d\n", (int)VirtPos); if (!_info_WasLoaded) { RINOK(ReloadProps()) } const struct stat &st = _info; /* struct stat st; if (File.my_fstat(&st) != 0) return GetLastError_HRESULT(); */ props->Size = (UInt64)st.st_size; /* dev_t stat::st_dev: GCC:Linux long unsigned int : __dev_t Mac: int */ props->VolID = (UInt64)(Int64)st.st_dev; props->FileID_Low = st.st_ino; props->FileID_High = 0; props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); FiTime_To_FILETIME (ST_CTIME(st), props->CTime); FiTime_To_FILETIME (ST_ATIME(st), props->ATime); FiTime_To_FILETIME (ST_MTIME(st), props->MTime); /* printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" , (unsigned)(props->NumLinks) , (unsigned)(st.st_dev) , (unsigned)(st.st_ino) ); */ return S_OK; } Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) { // printf("\nCInFileStream::GetProperty VirtPos = %8d propID = %3d\n", (int)VirtPos, propID); if (!_info_WasLoaded) { RINOK(ReloadProps()) } if (!_info_WasLoaded) return S_OK; const struct stat &st = _info; NWindows::NCOM::CPropVariant prop; { switch (propID) { case kpidSize: prop = (UInt64)st.st_size; break; case kpidAttrib: prop = (UInt32)NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); break; case kpidCTime: PropVariant_SetFrom_FiTime(prop, ST_CTIME(st)); break; case kpidATime: PropVariant_SetFrom_FiTime(prop, ST_ATIME(st)); break; case kpidMTime: PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break; case kpidPosixAttrib: prop = (UInt32)st.st_mode; break; #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #endif case kpidDeviceMajor: { // printf("\nst.st_rdev = %d\n", st.st_rdev); if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) prop = (UInt32)(major(st.st_rdev)); // + 1000); // prop = (UInt32)12345678; // for debug break; } case kpidDeviceMinor: if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) prop = (UInt32)(minor(st.st_rdev)); // + 100); // prop = (UInt32)(st.st_rdev); // for debug // printf("\nst.st_rdev = %d\n", st.st_rdev); // prop = (UInt32)123456789; // for debug break; #if defined(__APPLE__) #pragma GCC diagnostic pop #endif /* case kpidDevice: if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) prop = (UInt64)(st.st_rdev); break; */ case kpidUserId: { if (StoreOwnerId) prop = (UInt32)st.st_uid; break; } case kpidGroupId: { if (StoreOwnerId) prop = (UInt32)st.st_gid; break; } case kpidUser: { if (StoreOwnerName) { const uid_t uid = st.st_uid; { if (!OwnerName.IsEmpty() && _uid == uid) prop = OwnerName; else { const passwd *pw = getpwuid(uid); if (pw) { // we can use utf-8 here. // prop = pw->pw_name; } } } } break; } case kpidGroup: { if (StoreOwnerName) { const uid_t gid = st.st_gid; { if (!OwnerGroup.IsEmpty() && _gid == gid) prop = OwnerGroup; else { const group *gr = getgrgid(gid); if (gr) { // we can use utf-8 here. // prop = gr->gr_name; } } } } break; } default: break; } } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CInFileStream::ReloadProps()) { _info_WasLoaded = (File.my_fstat(&_info) == 0); if (!_info_WasLoaded) return GetLastError_HRESULT(); return S_OK; } #endif ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } Z7_COM7F_IMF(COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { #ifdef Z7_FILE_STREAMS_USE_WIN_FILE UInt32 realProcessedSize; const bool result = File.Write(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if (processedSize) *processedSize = 0; size_t realProcessedSize; const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = (UInt32)realProcessedSize; if (res == -1) return GetLastError_HRESULT(); return S_OK; #endif } Z7_COM7F_IMF(COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef Z7_FILE_STREAMS_USE_WIN_FILE UInt64 realNewPosition = 0; const bool result = File.Seek(offset, seekOrigin, realNewPosition); if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else const off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) return GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)res; return S_OK; #endif } Z7_COM7F_IMF(COutFileStream::SetSize(UInt64 newSize)) { return ConvertBoolToHRESULT(File.SetLength_KeepPosition(newSize)); } HRESULT COutFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } #ifdef UNDER_CE Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { size_t s2 = fwrite(data, 1, size, stdout); if (processedSize) *processedSize = s2; return (s2 == size) ? S_OK : E_FAIL; } #else Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); _size += realProcessedSize; size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if (processedSize) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return GetLastError_HRESULT(); _size += (size_t)res; if (processedSize) *processedSize = (UInt32)res; return S_OK; #endif } #endif tmp41wklro_/CPP/7zip/Common/FileStreams.h0000444000175000001440000000755114601264720021305 0ustar nabijaczleweliusers// FileStreams.h #ifndef ZIP7_INC_FILE_STREAMS_H #define ZIP7_INC_FILE_STREAMS_H #ifdef _WIN32 #define Z7_FILE_STREAMS_USE_WIN_FILE #endif #include "../../Common/MyCom.h" #include "../../Common/MyString.h" #include "../../Windows/FileIO.h" #include "../IStream.h" #include "UniqBlocks.h" class CInFileStream; Z7_PURE_INTERFACES_BEGIN DECLARE_INTERFACE(IInFileStream_Callback) { virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) = 0; }; Z7_PURE_INTERFACES_END /* Z7_CLASS_IMP_COM_5( CInFileStream , IInStream , IStreamGetSize , IStreamGetProps , IStreamGetProps2 , IStreamGetProp ) */ Z7_class_final(CInFileStream) : public IInStream, public IStreamGetSize, public IStreamGetProps, public IStreamGetProps2, public IStreamGetProp, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_6( IInStream, ISequentialInStream, IStreamGetSize, IStreamGetProps, IStreamGetProps2, IStreamGetProp) Z7_IFACE_COM7_IMP(ISequentialInStream) Z7_IFACE_COM7_IMP(IInStream) public: Z7_IFACE_COM7_IMP(IStreamGetSize) private: Z7_IFACE_COM7_IMP(IStreamGetProps) public: Z7_IFACE_COM7_IMP(IStreamGetProps2) Z7_IFACE_COM7_IMP(IStreamGetProp) private: NWindows::NFile::NIO::CInFile File; public: #ifdef Z7_FILE_STREAMS_USE_WIN_FILE #ifdef Z7_DEVICE_FILE UInt64 VirtPos; UInt64 PhyPos; UInt64 BufStartPos; Byte *Buf; UInt32 BufSize; #endif #endif #ifdef _WIN32 BY_HANDLE_FILE_INFORMATION _info; #else struct stat _info; UInt32 _uid; UInt32 _gid; UString OwnerName; UString OwnerGroup; bool StoreOwnerId; bool StoreOwnerName; #endif bool _info_WasLoaded; bool SupportHardLinks; IInFileStream_Callback *Callback; UINT_PTR CallbackRef; CInFileStream(); ~CInFileStream(); void Set_PreserveATime(bool v) { File.PreserveATime = v; } bool GetLength(UInt64 &length) const throw() { return File.GetLength(length); } #if 0 bool OpenStdIn(); #endif bool Open(CFSTR fileName) { _info_WasLoaded = false; return File.Open(fileName); } bool OpenShared(CFSTR fileName, bool shareForWrite) { _info_WasLoaded = false; return File.OpenShared(fileName, shareForWrite); } }; // bool CreateStdInStream(CMyComPtr &str); Z7_CLASS_IMP_NOQIB_1( CStdInFileStream , ISequentialInStream ) }; Z7_CLASS_IMP_COM_1( COutFileStream , IOutStream ) Z7_IFACE_COM7_IMP(ISequentialOutStream) public: NWindows::NFile::NIO::COutFile File; bool Create_NEW(CFSTR fileName) { ProcessedSize = 0; return File.Create_NEW(fileName); } bool Create_ALWAYS(CFSTR fileName) { ProcessedSize = 0; return File.Create_ALWAYS(fileName); } bool Open_EXISTING(CFSTR fileName) { ProcessedSize = 0; return File.Open_EXISTING(fileName); } bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create_ALWAYS_or_Open_ALWAYS(fileName, createAlways); } HRESULT Close(); UInt64 ProcessedSize; bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const CFiTime *mTime) { return File.SetMTime(mTime); } bool SeekToBegin_bool() { #ifdef Z7_FILE_STREAMS_USE_WIN_FILE return File.SeekToBegin(); #else return File.seekToBegin() == 0; #endif } HRESULT GetSize(UInt64 *size); }; Z7_CLASS_IMP_NOQIB_1( CStdOutFileStream , ISequentialOutStream ) UInt64 _size; public: UInt64 GetSize() const { return _size; } CStdOutFileStream(): _size(0) {} }; #endif tmp41wklro_/CPP/7zip/Common/FilterCoder.cpp0000444000175000001440000003737314405332720021627 0ustar nabijaczleweliusers// FilterCoder.cpp #include "StdAfx.h" // #include #include "../../Common/Defs.h" #include "FilterCoder.h" #include "StreamUtils.h" #ifdef _WIN32 #define alignedMidBuffer_Alloc g_MidAlloc #else #define alignedMidBuffer_Alloc g_AlignedAlloc #endif CAlignedMidBuffer::~CAlignedMidBuffer() { ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf); } void CAlignedMidBuffer::AllocAligned(size_t size) { ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf); _buf = (Byte *)ISzAlloc_Alloc(&alignedMidBuffer_Alloc, size); } /* AES filters need 16-bytes alignment for HARDWARE-AES instructions. So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block. AES-CBC filters need data size aligned for 16-bytes. So the encoder can add zeros to the end of original stream. Some filters (BCJ and others) don't process data at the end of stream in some cases. So the encoder and decoder write such last bytes without change. Most filters process all data, if we send aligned size to filter. But BCJ filter can process up 4 bytes less than sent size. And ARMT filter can process 2 bytes less than sent size. */ static const UInt32 kBufSize = 1 << 21; Z7_COM7F_IMF(CFilterCoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; } Z7_COM7F_IMF(CFilterCoder::SetOutBufSize(UInt32 , UInt32 size)) { _outBufSize = size; return S_OK; } HRESULT CFilterCoder::Alloc() { UInt32 size = MyMin(_inBufSize, _outBufSize); /* minimal bufSize is 16 bytes for AES and IA64 filter. bufSize for AES must be aligned for 16 bytes. We use (1 << 12) min size to support future aligned filters. */ const UInt32 kMinSize = 1 << 12; size &= ~(UInt32)(kMinSize - 1); if (size < kMinSize) size = kMinSize; // size = (1 << 12); // + 117; // for debug if (!_buf || _bufSize != size) { AllocAligned(size); if (!_buf) return E_OUTOFMEMORY; _bufSize = size; } return S_OK; } HRESULT CFilterCoder::Init_and_Alloc() { RINOK(Filter->Init()) return Alloc(); } CFilterCoder::CFilterCoder(bool encodeMode): _bufSize(0), _inBufSize(kBufSize), _outBufSize(kBufSize), _encodeMode(encodeMode), _outSize_Defined(false), _outSize(0), _nowPos64(0) {} Z7_COM7F_IMF(CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) { RINOK(Init_and_Alloc()) /* It's expected that BCJ/ARMT filter can process up to 4 bytes less than sent data size. For such BCJ/ARMT cases with non-filtered data we: - write some filtered data to output stream - move non-written data (filtered and non-filtered data) to start of buffer - read more new data from input stream to position after end of non-filtered data - call Filter() for concatenated data in buffer. For all cases, even for cases with partial filtering (BCJ/ARMT), we try to keep real/virtual alignment for all operations (memmove, Read(), Filter(), Write()). We use (kAlignSize=64) alignmnent that is larger than (16-bytes) required for AES filter alignment. AES-CBC uses 16-bytes blocks, that is simple case for processing here, if we call Filter() for aligned size for all calls except of last call (last block). And now there are no filters that use blocks with non-power2 size, but we try to support such non-power2 filters too here at Code(). */ UInt64 prev = 0; UInt64 nowPos64 = 0; bool inputFinished = false; UInt32 readPos = 0; UInt32 filterPos = 0; while (!outSize || nowPos64 < *outSize) { HRESULT hres = S_OK; if (!inputFinished) { size_t processedSize = _bufSize - readPos; /* for AES filters we need at least max(16, kAlignSize) bytes in buffer. But we try to read full buffer to reduce the number of Filter() and Write() calls. */ hres = ReadStream(inStream, _buf + readPos, &processedSize); readPos += (UInt32)processedSize; inputFinished = (readPos != _bufSize); if (hres != S_OK) { // do we need to stop encoding after reading error? // if (_encodeMode) return hres; inputFinished = true; } } if (readPos == 0) return hres; /* we set (needMoreInput = true), if it's block-filter (like AES-CBC) that needs more data for current block filtering: We read full input buffer with Read(), and _bufSize is aligned, So the possible cases when we set (needMoreInput = true) are: 1) decode : filter needs more data after the end of input stream. another cases are possible for non-power2-block-filter, because buffer size is not aligned for filter_non_power2_block_size: 2) decode/encode : filter needs more data from non-finished input stream 3) encode : filter needs more space for zeros after the end of input stream */ bool needMoreInput = false; while (readPos != filterPos) { /* Filter() is allowed to process part of data. Here we use the loop to filter as max as possible. when we call Filter(data, size): if (size < 16), AES-CTR filter uses internal 16-byte buffer. new (since v23.00) AES-CTR filter allows (size < 16) for non-last block, but it will work less efficiently than calls with aligned (size). We still support old (before v23.00) AES-CTR filters here. We have aligned (size) for AES-CTR, if it's not last block. We have aligned (readPos) for any filter, if (!inputFinished). We also meet the requirements for (data) pointer in Filter() call: { (virtual_stream_offset % aligment_size) == (data_ptr % aligment_size) (aligment_size == 2^N) (aligment_size >= 16) } */ const UInt32 cur = Filter->Filter(_buf + filterPos, readPos - filterPos); if (cur == 0) break; const UInt32 f = filterPos + cur; if (cur > readPos - filterPos) { // AES-CBC if (hres != S_OK) break; if (!_encodeMode || cur > _bufSize - filterPos || !inputFinished) { /* (cur > _bufSize - filterPos) is unexpected for AES filter, if _bufSize is multiply of 16. But we support this case, if some future filter will use block with non-power2-size. */ needMoreInput = true; break; } /* (_encodeMode && inputFinished). We add zero bytes as pad in current block after the end of read data. */ Byte *buf = _buf; do buf[readPos] = 0; while (++readPos != f); // (readPos) now is (size_of_real_input_data + size_of_zero_pad) if (cur != Filter->Filter(buf + filterPos, cur)) return E_FAIL; } filterPos = f; } UInt32 size = filterPos; if (hres == S_OK) { /* If we need more Read() or Filter() calls, then we need to Write() some data and move unwritten data to get additional space in buffer. We try to keep alignment for data moves, Read(), Filter() and Write() calls. */ const UInt32 kAlignSize = 1 << 6; const UInt32 alignedFiltered = filterPos & ~(kAlignSize - 1); if (inputFinished) { if (!needMoreInput) size = readPos; // for risc/bcj filters in last block we write data after filterPos. else if (_encodeMode) size = alignedFiltered; // for non-power2-block-encode-filter } else size = alignedFiltered; } { UInt32 writeSize = size; if (outSize) { const UInt64 rem = *outSize - nowPos64; if (writeSize > rem) writeSize = (UInt32)rem; } RINOK(WriteStream(outStream, _buf, writeSize)) nowPos64 += writeSize; } if (hres != S_OK) return hres; if (inputFinished) { if (readPos == size) return hres; if (!_encodeMode) { // block-decode-filter (AES-CBS) has non-full last block // we don't want unaligned data move for more iterations with this error case. return S_FALSE; } } if (size == 0) { // it's unexpected that we have no any move in this iteration. return E_FAIL; } // if (size != 0) { if (filterPos < size) return E_FAIL; // filterPos = 0; else filterPos -= size; readPos -= size; if (readPos != 0) memmove(_buf, _buf + size, readPos); } // printf("\nnowPos64=%x, readPos=%x, filterPos=%x\n", (unsigned)nowPos64, (unsigned)readPos, (unsigned)filterPos); if (progress && (nowPos64 - prev) >= (1 << 22)) { prev = nowPos64; RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)) } } return S_OK; } // ---------- Write to Filter ---------- Z7_COM7F_IMF(CFilterCoder::SetOutStream(ISequentialOutStream *outStream)) { _outStream = outStream; return S_OK; } Z7_COM7F_IMF(CFilterCoder::ReleaseOutStream()) { _outStream.Release(); return S_OK; } HRESULT CFilterCoder::Flush2() { while (_convSize != 0) { UInt32 num = _convSize; if (_outSize_Defined) { const UInt64 rem = _outSize - _nowPos64; if (num > rem) num = (UInt32)rem; if (num == 0) return k_My_HRESULT_WritingWasCut; } UInt32 processed = 0; const HRESULT res = _outStream->Write(_buf + _convPos, num, &processed); if (processed == 0) return res != S_OK ? res : E_FAIL; _convPos += processed; _convSize -= processed; _nowPos64 += processed; RINOK(res) } const UInt32 convPos = _convPos; if (convPos != 0) { const UInt32 num = _bufPos - convPos; Byte *buf = _buf; for (UInt32 i = 0; i < num; i++) buf[i] = buf[convPos + i]; _bufPos = num; _convPos = 0; } return S_OK; } Z7_COM7F_IMF(CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { RINOK(Flush2()) // _convSize is 0 // _convPos is 0 // _bufPos is small if (_bufPos != _bufSize) { UInt32 num = MyMin(size, _bufSize - _bufPos); memcpy(_buf + _bufPos, data, num); size -= num; data = (const Byte *)data + num; if (processedSize) *processedSize += num; _bufPos += num; if (_bufPos != _bufSize) continue; } // _bufPos == _bufSize _convSize = Filter->Filter(_buf, _bufPos); if (_convSize == 0) break; if (_convSize > _bufPos) { // that case is not possible. _convSize = 0; return E_FAIL; } } return S_OK; } Z7_COM7F_IMF(CFilterCoder::OutStreamFinish()) { for (;;) { RINOK(Flush2()) if (_bufPos == 0) break; const UInt32 convSize = Filter->Filter(_buf, _bufPos); _convSize = convSize; UInt32 bufPos = _bufPos; if (convSize == 0) _convSize = bufPos; else if (convSize > bufPos) { // AES if (convSize > _bufSize) { _convSize = 0; return E_FAIL; } if (!_encodeMode) { _convSize = 0; return S_FALSE; } Byte *buf = _buf; for (; bufPos < convSize; bufPos++) buf[bufPos] = 0; _bufPos = bufPos; _convSize = Filter->Filter(_buf, bufPos); if (_convSize != _bufPos) return E_FAIL; } } CMyComPtr finish; _outStream.QueryInterface(IID_IOutStreamFinish, &finish); if (finish) return finish->OutStreamFinish(); return S_OK; } // ---------- Init functions ---------- Z7_COM7F_IMF(CFilterCoder::InitEncoder()) { InitSpecVars(); return Init_and_Alloc(); } HRESULT CFilterCoder::Init_NoSubFilterInit() { InitSpecVars(); return Alloc(); } Z7_COM7F_IMF(CFilterCoder::SetOutStreamSize(const UInt64 *outSize)) { InitSpecVars(); if (outSize) { _outSize = *outSize; _outSize_Defined = true; } return Init_and_Alloc(); } // ---------- Read from Filter ---------- Z7_COM7F_IMF(CFilterCoder::SetInStream(ISequentialInStream *inStream)) { _inStream = inStream; return S_OK; } Z7_COM7F_IMF(CFilterCoder::ReleaseInStream()) { _inStream.Release(); return S_OK; } Z7_COM7F_IMF(CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_convSize != 0) { if (size > _convSize) size = _convSize; if (_outSize_Defined) { const UInt64 rem = _outSize - _nowPos64; if (size > rem) size = (UInt32)rem; } memcpy(data, _buf + _convPos, size); _convPos += size; _convSize -= size; _nowPos64 += size; if (processedSize) *processedSize = size; break; } const UInt32 convPos = _convPos; if (convPos != 0) { const UInt32 num = _bufPos - convPos; Byte *buf = _buf; for (UInt32 i = 0; i < num; i++) buf[i] = buf[convPos + i]; _bufPos = num; _convPos = 0; } { size_t readSize = _bufSize - _bufPos; const HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize); _bufPos += (UInt32)readSize; RINOK(res) } const UInt32 convSize = Filter->Filter(_buf, _bufPos); _convSize = convSize; UInt32 bufPos = _bufPos; if (convSize == 0) { if (bufPos == 0) break; // BCJ _convSize = bufPos; continue; } if (convSize > bufPos) { // AES if (convSize > _bufSize) return E_FAIL; if (!_encodeMode) return S_FALSE; Byte *buf = _buf; do buf[bufPos] = 0; while (++bufPos != convSize); _bufPos = bufPos; _convSize = Filter->Filter(_buf, convSize); if (_convSize != _bufPos) return E_FAIL; } } return S_OK; } #ifndef Z7_NO_CRYPTO Z7_COM7F_IMF(CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)) { return _setPassword->CryptoSetPassword(data, size); } Z7_COM7F_IMF(CFilterCoder::SetKey(const Byte *data, UInt32 size)) { return _cryptoProperties->SetKey(data, size); } Z7_COM7F_IMF(CFilterCoder::SetInitVector(const Byte *data, UInt32 size)) { return _cryptoProperties->SetInitVector(data, size); } #endif #ifndef Z7_EXTRACT_ONLY Z7_COM7F_IMF(CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties)) { return _setCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } Z7_COM7F_IMF(CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)) { return _writeCoderProperties->WriteCoderProperties(outStream); } Z7_COM7F_IMF(CFilterCoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties)) { return _setCoderPropertiesOpt->SetCoderPropertiesOpt(propIDs, properties, numProperties); } /* Z7_COM7F_IMF(CFilterCoder::ResetSalt() { return _cryptoResetSalt->ResetSalt(); } */ Z7_COM7F_IMF(CFilterCoder::ResetInitVector()) { return _cryptoResetInitVector->ResetInitVector(); } #endif Z7_COM7F_IMF(CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)) { return _setDecoderProperties2->SetDecoderProperties2(data, size); } tmp41wklro_/CPP/7zip/Common/FilterCoder.h0000444000175000001440000001236614405332720021267 0ustar nabijaczleweliusers// FilterCoder.h #ifndef ZIP7_INC_FILTER_CODER_H #define ZIP7_INC_FILTER_CODER_H #include "../../../C/Alloc.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #ifndef Z7_NO_CRYPTO #include "../IPassword.h" #endif #define Z7_COM_QI_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; } struct CAlignedMidBuffer { Byte *_buf; CAlignedMidBuffer(): _buf(NULL) {} ~CAlignedMidBuffer(); void AllocAligned(size_t size); }; class CFilterCoder Z7_final : public ICompressCoder, public ICompressSetOutStreamSize, public ICompressInitEncoder, public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFinish, public ICompressSetBufSize, #ifndef Z7_NO_CRYPTO public ICryptoSetPassword, public ICryptoProperties, #endif #ifndef Z7_EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public ICompressSetCoderPropertiesOpt, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp, public CAlignedMidBuffer { UInt32 _bufSize; UInt32 _inBufSize; UInt32 _outBufSize; bool _encodeMode; bool _outSize_Defined; UInt64 _outSize; UInt64 _nowPos64; CMyComPtr _inStream; CMyComPtr _outStream; UInt32 _bufPos; UInt32 _convPos; // current pos in buffer for converted data UInt32 _convSize; // size of converted data starting from _convPos void InitSpecVars() { _bufPos = 0; _convPos = 0; _convSize = 0; _outSize_Defined = false; _outSize = 0; _nowPos64 = 0; } HRESULT Alloc(); HRESULT Init_and_Alloc(); HRESULT Flush2(); #ifndef Z7_NO_CRYPTO CMyComPtr _setPassword; CMyComPtr _cryptoProperties; #endif #ifndef Z7_EXTRACT_ONLY CMyComPtr _setCoderProperties; CMyComPtr _writeCoderProperties; CMyComPtr _setCoderPropertiesOpt; // CMyComPtr _cryptoResetSalt; CMyComPtr _cryptoResetInitVector; #endif CMyComPtr _setDecoderProperties2; public: CMyComPtr Filter; CFilterCoder(bool encodeMode); struct C_InStream_Releaser { CFilterCoder *FilterCoder; C_InStream_Releaser(): FilterCoder(NULL) {} ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; struct C_OutStream_Releaser { CFilterCoder *FilterCoder; C_OutStream_Releaser(): FilterCoder(NULL) {} ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; struct C_Filter_Releaser { CFilterCoder *FilterCoder; C_Filter_Releaser(): FilterCoder(NULL) {} ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); } }; private: Z7_COM_QI_BEGIN2(ICompressCoder) Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) Z7_COM_QI_ENTRY(ICompressInitEncoder) Z7_COM_QI_ENTRY(ICompressSetInStream) Z7_COM_QI_ENTRY(ISequentialInStream) Z7_COM_QI_ENTRY(ICompressSetOutStream) Z7_COM_QI_ENTRY(ISequentialOutStream) Z7_COM_QI_ENTRY(IOutStreamFinish) Z7_COM_QI_ENTRY(ICompressSetBufSize) #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) Z7_COM_QI_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties) #endif #ifndef Z7_EXTRACT_ONLY Z7_COM_QI_ENTRY_AG(ICompressSetCoderProperties, Filter, _setCoderProperties) Z7_COM_QI_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) Z7_COM_QI_ENTRY_AG(ICompressSetCoderPropertiesOpt, Filter, _setCoderPropertiesOpt) // Z7_COM_QI_ENTRY_AG(ICryptoResetSalt, Filter, _cryptoResetSalt) Z7_COM_QI_ENTRY_AG(ICryptoResetInitVector, Filter, _cryptoResetInitVector) #endif Z7_COM_QI_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties2) Z7_COM_QI_END Z7_COM_ADDREF_RELEASE public: Z7_IFACE_COM7_IMP(ICompressCoder) Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) Z7_IFACE_COM7_IMP(ICompressInitEncoder) Z7_IFACE_COM7_IMP(ICompressSetInStream) private: Z7_IFACE_COM7_IMP(ISequentialInStream) public: Z7_IFACE_COM7_IMP(ICompressSetOutStream) private: Z7_IFACE_COM7_IMP(ISequentialOutStream) public: Z7_IFACE_COM7_IMP(IOutStreamFinish) private: Z7_IFACE_COM7_IMP(ICompressSetBufSize) #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoSetPassword) Z7_IFACE_COM7_IMP(ICryptoProperties) #endif #ifndef Z7_EXTRACT_ONLY Z7_IFACE_COM7_IMP(ICompressSetCoderProperties) Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt) // Z7_IFACE_COM7_IMP(ICryptoResetSalt) Z7_IFACE_COM7_IMP(ICryptoResetInitVector) #endif public: Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) HRESULT Init_NoSubFilterInit(); }; #endif tmp41wklro_/CPP/7zip/Common/InBuffer.cpp0000444000175000001440000000665314542025520021121 0ustar nabijaczleweliusers// InBuffer.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "InBuffer.h" CInBufferBase::CInBufferBase() throw(): _buf(NULL), _bufLim(NULL), _bufBase(NULL), _stream(NULL), _processedSize(0), _bufSize(0), _wasFinished(false), NumExtraBytes(0) {} bool CInBuffer::Create(size_t bufSize) throw() { const unsigned kMinBlockSize = 1; if (bufSize < kMinBlockSize) bufSize = kMinBlockSize; if (_bufBase != NULL && _bufSize == bufSize) return true; Free(); _bufSize = bufSize; _bufBase = (Byte *)::MidAlloc(bufSize); return (_bufBase != NULL); } void CInBuffer::Free() throw() { ::MidFree(_bufBase); _bufBase = NULL; } void CInBufferBase::Init() throw() { _processedSize = 0; _buf = _bufBase; _bufLim = _buf; _wasFinished = false; #ifdef Z7_NO_EXCEPTIONS ErrorCode = S_OK; #endif NumExtraBytes = 0; } bool CInBufferBase::ReadBlock() { #ifdef Z7_NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (size_t)(_buf - _bufBase); _buf = _bufBase; _bufLim = _bufBase; UInt32 processed; // FIX_ME: we can improve it to support (_bufSize >= (1 << 32)) const HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed); #ifdef Z7_NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _bufLim = _buf + processed; _wasFinished = (processed == 0); return !_wasFinished; } bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) { if (!ReadBlock()) { // 22.00: we don't increment (NumExtraBytes) here // NumExtraBytes++; b = 0xFF; return false; } b = *_buf++; return true; } Byte CInBufferBase::ReadByte_FromNewBlock() { if (!ReadBlock()) { NumExtraBytes++; return 0xFF; } return *_buf++; } size_t CInBufferBase::ReadBytesPart(Byte *buf, size_t size) { if (size == 0) return 0; size_t rem = (size_t)(_bufLim - _buf); if (rem == 0) { if (!ReadBlock()) return 0; rem = (size_t)(_bufLim - _buf); } if (size > rem) size = rem; memcpy(buf, _buf, size); _buf += size; return size; } size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) { size_t num = 0; for (;;) { const size_t rem = (size_t)(_bufLim - _buf); if (size <= rem) { if (size != 0) { memcpy(buf, _buf, size); _buf += size; num += size; } return num; } if (rem != 0) { memcpy(buf, _buf, rem); _buf += rem; buf += rem; num += rem; size -= rem; } if (!ReadBlock()) return num; } /* if ((size_t)(_bufLim - _buf) >= size) { const Byte *src = _buf; for (size_t i = 0; i < size; i++) buf[i] = src[i]; _buf += size; return size; } for (size_t i = 0; i < size; i++) { if (_buf >= _bufLim) if (!ReadBlock()) return i; buf[i] = *_buf++; } return size; */ } size_t CInBufferBase::Skip(size_t size) { size_t processed = 0; for (;;) { const size_t rem = (size_t)(_bufLim - _buf); if (rem >= size) { _buf += size; return processed + size; } _buf += rem; processed += rem; size -= rem; if (!ReadBlock()) return processed; } } tmp41wklro_/CPP/7zip/Common/InBuffer.h0000444000175000001440000000530014542025520020552 0ustar nabijaczleweliusers// InBuffer.h #ifndef ZIP7_INC_IN_BUFFER_H #define ZIP7_INC_IN_BUFFER_H #include "../../Common/MyException.h" #include "../IStream.h" #ifndef Z7_NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBufferBase { protected: Byte *_buf; Byte *_bufLim; Byte *_bufBase; ISequentialInStream *_stream; UInt64 _processedSize; size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger // only up to 32-bits values now are supported! bool _wasFinished; bool ReadBlock(); bool ReadByte_FromNewBlock(Byte &b); Byte ReadByte_FromNewBlock(); public: #ifdef Z7_NO_EXCEPTIONS HRESULT ErrorCode; #endif UInt32 NumExtraBytes; CInBufferBase() throw(); // the size of portion of data in real stream that was already read from this object // it doesn't include unused data in buffer // it doesn't include virtual Extra bytes after the end of real stream data UInt64 GetStreamSize() const { return _processedSize + (size_t)(_buf - _bufBase); } // the size of virtual data that was read from this object // it doesn't include unused data in buffers // it includes any virtual Extra bytes after the end of real data UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (size_t)(_buf - _bufBase); } bool WasFinished() const { return _wasFinished; } void SetStream(ISequentialInStream *stream) { _stream = stream; } void ClearStreamPtr() { _stream = NULL; } void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos) { _bufBase = buf; _bufSize = bufSize; _processedSize = 0; _buf = buf + pos; _bufLim = buf + end; _wasFinished = false; #ifdef Z7_NO_EXCEPTIONS ErrorCode = S_OK; #endif NumExtraBytes = 0; } void Init() throw(); Z7_FORCE_INLINE bool ReadByte(Byte &b) { if (_buf >= _bufLim) return ReadByte_FromNewBlock(b); b = *_buf++; return true; } Z7_FORCE_INLINE bool ReadByte_FromBuf(Byte &b) { if (_buf >= _bufLim) return false; b = *_buf++; return true; } Z7_FORCE_INLINE Byte ReadByte() { if (_buf >= _bufLim) return ReadByte_FromNewBlock(); return *_buf++; } size_t ReadBytesPart(Byte *buf, size_t size); size_t ReadBytes(Byte *buf, size_t size); size_t Skip(size_t size); }; class CInBuffer: public CInBufferBase { public: ~CInBuffer() { Free(); } bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported! void Free() throw(); }; #endif tmp41wklro_/CPP/7zip/Common/InOutTempBuffer.cpp0000444000175000001440000001226514350157340022436 0ustar nabijaczleweliusers// InOutTempBuffer.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "InOutTempBuffer.h" #include "StreamUtils.h" #ifdef USE_InOutTempBuffer_FILE #include "../../../C/7zCrc.h" #define kTempFilePrefixString FTEXT("7zt") /* Total buffer size limit, if we use temp file scheme: 32-bit: 16 MiB = 1 MiB * 16 buffers 64-bit: 4 GiB = 1 MiB * 4096 buffers */ static const size_t kNumBufsMax = (size_t)1 << (sizeof(size_t) * 2 - 4); #endif static const size_t kBufSize = (size_t)1 << 20; CInOutTempBuffer::CInOutTempBuffer(): _size(0), _bufs(NULL), _numBufs(0), _numFilled(0) { #ifdef USE_InOutTempBuffer_FILE _tempFile_Created = false; _useMemOnly = false; _crc = CRC_INIT_VAL; #endif } CInOutTempBuffer::~CInOutTempBuffer() { for (size_t i = 0; i < _numBufs; i++) MyFree(_bufs[i]); MyFree(_bufs); } void *CInOutTempBuffer::GetBuf(size_t index) { if (index >= _numBufs) { const size_t num = (_numBufs == 0 ? 16 : _numBufs * 2); void **p = (void **)MyRealloc(_bufs, num * sizeof(void *)); if (!p) return NULL; _bufs = p; memset(p + _numBufs, 0, (num - _numBufs) * sizeof(void *)); _numBufs = num; } void *buf = _bufs[index]; if (!buf) { buf = MyAlloc(kBufSize); if (buf) _bufs[index] = buf; } return buf; } HRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size) { if (size == 0) return S_OK; #ifdef USE_InOutTempBuffer_FILE if (!_tempFile_Created) #endif for (;;) // loop for additional attemp to allocate memory after file creation error { #ifdef USE_InOutTempBuffer_FILE bool allocError = false; #endif for (;;) // loop for writing to buffers { const size_t index = (size_t)(_size / kBufSize); #ifdef USE_InOutTempBuffer_FILE if (index >= kNumBufsMax && !_useMemOnly) break; #endif void *buf = GetBuf(index); if (!buf) { #ifdef USE_InOutTempBuffer_FILE if (!_useMemOnly) { allocError = true; break; } #endif return E_OUTOFMEMORY; } const size_t offset = (size_t)(_size) & (kBufSize - 1); size_t cur = kBufSize - offset; if (cur > size) cur = size; memcpy((Byte *)buf + offset, data, cur); _size += cur; if (index >= _numFilled) _numFilled = index + 1; data = (const void *)((const Byte *)data + cur); size -= (UInt32)cur; if (size == 0) return S_OK; } #ifdef USE_InOutTempBuffer_FILE #ifndef _WIN32 _outFile.mode_for_Create = 0600; // only owner will have the rights to access this file #endif if (_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) { _tempFile_Created = true; break; } _useMemOnly = true; if (allocError) return GetLastError_noZero_HRESULT(); #endif } #ifdef USE_InOutTempBuffer_FILE if (!_outFile.WriteFull(data, size)) return GetLastError_noZero_HRESULT(); _crc = CrcUpdate(_crc, data, size); _size += size; return S_OK; #endif } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { UInt64 rem = _size; // if (rem == 0) return S_OK; const size_t numFilled = _numFilled; _numFilled = 0; for (size_t i = 0; i < numFilled; i++) { if (rem == 0) return E_FAIL; size_t cur = kBufSize; if (cur > rem) cur = (size_t)rem; RINOK(WriteStream(stream, _bufs[i], cur)) rem -= cur; #ifdef USE_InOutTempBuffer_FILE // we will use _bufs[0] later for writing from temp file if (i != 0 || !_tempFile_Created) #endif { MyFree(_bufs[i]); _bufs[i] = NULL; } } #ifdef USE_InOutTempBuffer_FILE if (rem == 0) return _tempFile_Created ? E_FAIL : S_OK; if (!_tempFile_Created) return E_FAIL; if (!_outFile.Close()) return GetLastError_noZero_HRESULT(); HRESULT hres; void *buf = GetBuf(0); // index if (!buf) hres = E_OUTOFMEMORY; else { NWindows::NFile::NIO::CInFile inFile; if (!inFile.Open(_tempFile.GetPath())) hres = GetLastError_noZero_HRESULT(); else { UInt32 crc = CRC_INIT_VAL; for (;;) { size_t processed; if (!inFile.ReadFull(buf, kBufSize, processed)) { hres = GetLastError_noZero_HRESULT(); break; } if (processed == 0) { // we compare crc without CRC_GET_DIGEST hres = (_crc == crc ? S_OK : E_FAIL); break; } size_t n = processed; if (n > rem) n = (size_t)rem; hres = WriteStream(stream, buf, n); if (hres != S_OK) break; crc = CrcUpdate(crc, buf, n); rem -= n; if (n != processed) { hres = E_FAIL; break; } } } } // _tempFile.DisableDeleting(); // for debug _tempFile.Remove(); RINOK(hres) #endif return rem == 0 ? S_OK : E_FAIL; } tmp41wklro_/CPP/7zip/Common/InOutTempBuffer.h0000444000175000001440000000172314366244420022103 0ustar nabijaczleweliusers// InOutTempBuffer.h #ifndef ZIP7_INC_IN_OUT_TEMP_BUFFER_H #define ZIP7_INC_IN_OUT_TEMP_BUFFER_H // #ifdef _WIN32 #define USE_InOutTempBuffer_FILE // #endif #ifdef USE_InOutTempBuffer_FILE #include "../../Windows/FileDir.h" #endif #include "../IStream.h" class CInOutTempBuffer { UInt64 _size; void **_bufs; size_t _numBufs; size_t _numFilled; #ifdef USE_InOutTempBuffer_FILE bool _tempFile_Created; bool _useMemOnly; UInt32 _crc; // COutFile object must be declared after CTempFile object for correct destructor order NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; #endif void *GetBuf(size_t index); Z7_CLASS_NO_COPY(CInOutTempBuffer) public: CInOutTempBuffer(); ~CInOutTempBuffer(); HRESULT Write_HRESULT(const void *data, UInt32 size); HRESULT WriteToStream(ISequentialOutStream *stream); UInt64 GetDataSize() const { return _size; } }; #endif tmp41wklro_/CPP/7zip/Common/LimitedStreams.cpp0000444000175000001440000002372014365252220022343 0ustar nabijaczleweliusers// LimitedStreams.cpp #include "StdAfx.h" #include #include "LimitedStreams.h" Z7_COM7F_IMF(CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize = 0; { const UInt64 rem = _size - _pos; if (size > rem) size = (UInt32)rem; } HRESULT result = S_OK; if (size != 0) { result = _stream->Read(data, size, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if (processedSize) *processedSize = realProcessedSize; return result; } Z7_COM7F_IMF(CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (_virtPos >= _size) { // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. return S_OK; // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF } { const UInt64 rem = _size - _virtPos; if (size > rem) size = (UInt32)rem; } UInt64 newPos = _startOffset + _virtPos; if (newPos != _physPos) { _physPos = newPos; RINOK(SeekToPhys()) } HRESULT res = _stream->Read(data, size, &size); if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; return res; } Z7_COM7F_IMF(CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; } HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) { *resStream = NULL; CLimitedInStream *streamSpec = new CLimitedInStream; CMyComPtr streamTemp = streamSpec; streamSpec->SetStream(inStream); RINOK(streamSpec->InitAndSeek(pos, size)) streamSpec->SeekToStart(); *resStream = streamTemp.Detach(); return S_OK; } Z7_COM7F_IMF(CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (_virtPos >= Size) return S_OK; { UInt64 rem = Size - _virtPos; if (size > rem) size = (UInt32)rem; } if (size == 0) return S_OK; if (_curRem == 0) { const UInt32 blockSize = (UInt32)1 << BlockSizeLog; const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); const UInt32 phyBlock = Vector[virtBlock]; UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; if (newPos != _physPos) { _physPos = newPos; RINOK(SeekToPhys()) } _curRem = blockSize - offsetInBlock; for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) _curRem += (UInt32)1 << BlockSizeLog; } if (size > _curRem) size = _curRem; HRESULT res = Stream->Read(data, size, &size); if (processedSize) *processedSize = size; _physPos += size; _virtPos += size; _curRem -= size; return res; } Z7_COM7F_IMF(CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += Size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; if (_virtPos != (UInt64)offset) _curRem = 0; _virtPos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } Z7_COM7F_IMF(CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; const UInt64 virt = _virtPos; if (virt >= Extents.Back().Virt) return S_OK; if (size == 0) return S_OK; unsigned left = _prevExtentIndex; if (virt < Extents[left].Virt || virt >= Extents[left + 1].Virt) { left = 0; unsigned right = Extents.Size() - 1; for (;;) { const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); if (mid == left) break; if (virt < Extents[mid].Virt) right = mid; else left = mid; } _prevExtentIndex = left; } { const UInt64 rem = Extents[left + 1].Virt - virt; if (size > rem) size = (UInt32)rem; } const CSeekExtent &extent = Extents[left]; if (extent.Is_ZeroFill()) { memset(data, 0, size); _virtPos += size; if (processedSize) *processedSize = size; return S_OK; } { const UInt64 phy = extent.Phy + (virt - extent.Virt); if (_phyPos != phy) { _phyPos = (UInt64)0 - 1; // we don't trust seek_pos in case of error RINOK(InStream_SeekSet(Stream, phy)) _phyPos = phy; } } const HRESULT res = Stream->Read(data, size, &size); _virtPos += size; if (res == S_OK) _phyPos += size; else _phyPos = (UInt64)0 - 1; // we don't trust seek_pos in case of error if (processedSize) *processedSize = size; return res; } Z7_COM7F_IMF(CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += Extents.Back().Virt; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; } Z7_COM7F_IMF(CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { HRESULT result = S_OK; if (processedSize) *processedSize = 0; if (size > _size) { if (_size == 0) { _overflow = true; if (!_overflowIsAllowed) return E_FAIL; if (processedSize) *processedSize = size; return S_OK; } size = (UInt32)_size; } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize) *processedSize = size; return result; } Z7_COM7F_IMF(CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 cur; HRESULT res = Stream->Read(data, size, &cur); if (processedSize) *processedSize = cur; _virtPos += cur; return res; } Z7_COM7F_IMF(CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: { UInt64 pos = 0; RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos)) if (pos < Offset) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = pos - Offset; if (newPosition) *newPosition = _virtPos; return S_OK; } default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return InStream_SeekSet(Stream, Offset + _virtPos); } Z7_COM7F_IMF(CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (_virtPos >= _size) { // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. return S_OK; // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF } UInt64 rem = _size - _virtPos; if (rem < size) size = (UInt32)rem; UInt64 newPos = _startOffset + _virtPos; UInt64 offsetInCache = newPos - _cachePhyPos; HRESULT res = S_OK; if (newPos >= _cachePhyPos && offsetInCache <= _cacheSize && size <= _cacheSize - (size_t)offsetInCache) { if (size != 0) memcpy(data, _cache + (size_t)offsetInCache, size); } else { if (newPos != _physPos) { _physPos = newPos; RINOK(SeekToPhys()) } res = _stream->Read(data, size, &size); _physPos += size; } if (processedSize) *processedSize = size; _virtPos += size; return res; } Z7_COM7F_IMF(CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; } Z7_COM7F_IMF(CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { UInt32 cur; HRESULT res = Stream->Write(data, size, &cur); if (processedSize) *processedSize = cur; _virtPos += cur; if (_virtSize < _virtPos) _virtSize = _virtPos; return res; } Z7_COM7F_IMF(CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _virtPos; break; case STREAM_SEEK_END: offset += _virtSize; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); } Z7_COM7F_IMF(CTailOutStream::SetSize(UInt64 newSize)) { _virtSize = newSize; return Stream->SetSize(Offset + newSize); } tmp41wklro_/CPP/7zip/Common/LimitedStreams.h0000444000175000001440000001117614366244420022016 0ustar nabijaczleweliusers// LimitedStreams.h #ifndef ZIP7_INC_LIMITED_STREAMS_H #define ZIP7_INC_LIMITED_STREAMS_H #include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../IStream.h" #include "StreamUtils.h" Z7_CLASS_IMP_COM_1( CLimitedSequentialInStream , ISequentialInStream ) CMyComPtr _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } UInt64 GetSize() const { return _pos; } UInt64 GetRem() const { return _size - _pos; } bool WasFinished() const { return _wasFinished; } }; Z7_CLASS_IMP_IInStream( CLimitedInStream ) CMyComPtr _stream; UInt64 _virtPos; UInt64 _physPos; UInt64 _size; UInt64 _startOffset; HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); } public: void SetStream(IInStream *stream) { _stream = stream; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) { _startOffset = startOffset; _physPos = startOffset; _virtPos = 0; _size = size; return SeekToPhys(); } HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); Z7_CLASS_IMP_IInStream( CClusterInStream ) UInt64 _virtPos; UInt64 _physPos; UInt32 _curRem; public: unsigned BlockSizeLog; UInt64 Size; CMyComPtr Stream; CRecordVector Vector; UInt64 StartOffset; HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); } HRESULT InitAndSeek() { _curRem = 0; _virtPos = 0; _physPos = StartOffset; if (Vector.Size() > 0) { _physPos = StartOffset + (Vector[0] << BlockSizeLog); return SeekToPhys(); } return S_OK; } }; const UInt64 k_SeekExtent_Phy_Type_ZeroFill = (UInt64)(Int64)-1; struct CSeekExtent { UInt64 Virt; UInt64 Phy; void SetAs_ZeroFill() { Phy = k_SeekExtent_Phy_Type_ZeroFill; } bool Is_ZeroFill() const { return Phy == k_SeekExtent_Phy_Type_ZeroFill; } }; Z7_CLASS_IMP_IInStream( CExtentsStream ) UInt64 _virtPos; UInt64 _phyPos; unsigned _prevExtentIndex; public: CMyComPtr Stream; CRecordVector Extents; void ReleaseStream() { Stream.Release(); } void Init() { _virtPos = 0; _phyPos = (UInt64)0 - 1; // we need Seek() for Stream _prevExtentIndex = 0; } }; Z7_CLASS_IMP_COM_1( CLimitedSequentialOutStream , ISequentialOutStream ) CMyComPtr _stream; UInt64 _size; bool _overflow; bool _overflowIsAllowed; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size, bool overflowIsAllowed = false) { _size = size; _overflow = false; _overflowIsAllowed = overflowIsAllowed; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; Z7_CLASS_IMP_IInStream( CTailInStream ) UInt64 _virtPos; public: CMyComPtr Stream; UInt64 Offset; void Init() { _virtPos = 0; } HRESULT SeekToStart() { return InStream_SeekSet(Stream, Offset); } }; Z7_CLASS_IMP_IInStream( CLimitedCachedInStream ) CMyComPtr _stream; UInt64 _virtPos; UInt64 _physPos; UInt64 _size; UInt64 _startOffset; const Byte *_cache; size_t _cacheSize; size_t _cachePhyPos; HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); } public: CByteBuffer Buffer; void SetStream(IInStream *stream) { _stream = stream; } void SetCache(size_t cacheSize, size_t cachePos) { _cache = Buffer; _cacheSize = cacheSize; _cachePhyPos = cachePos; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) { _startOffset = startOffset; _physPos = startOffset; _virtPos = 0; _size = size; return SeekToPhys(); } HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; class CTailOutStream Z7_final : public IOutStream, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(ISequentialOutStream, IOutStream) UInt64 _virtPos; UInt64 _virtSize; public: CMyComPtr Stream; UInt64 Offset; void Init() { _virtPos = 0; _virtSize = 0; } }; #endif tmp41wklro_/CPP/7zip/Common/LockedStream.cpp0000444000175000001440000000005412471126224021765 0ustar nabijaczleweliusers// LockedStream.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Common/LockedStream.h0000444000175000001440000000014314357314620021435 0ustar nabijaczleweliusers// LockedStream.h #ifndef ZIP7_INC_LOCKED_STREAM_H #define ZIP7_INC_LOCKED_STREAM_H #endif tmp41wklro_/CPP/7zip/Common/MethodId.cpp0000444000175000001440000000005011517526614021110 0ustar nabijaczleweliusers// MethodId.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/Common/MethodId.h0000444000175000001440000000023714357314620020561 0ustar nabijaczleweliusers// MethodId.h #ifndef ZIP7_INC_7Z_METHOD_ID_H #define ZIP7_INC_7Z_METHOD_ID_H #include "../../Common/MyTypes.h" typedef UInt64 CMethodId; #endif tmp41wklro_/CPP/7zip/Common/MethodProps.cpp0000444000175000001440000004204214567042400021660 0ustar nabijaczleweliusers// MethodProps.cpp #include "StdAfx.h" #include "../../Common/StringToInt.h" #include "MethodProps.h" using namespace NWindows; UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents) { // if (percents == 0) return 0; const UInt64 q = percents / 100; const UInt32 r = (UInt32)(percents % 100); UInt64 res = 0; if (q != 0) { if (val > (UInt64)(Int64)-1 / q) return (UInt64)(Int64)-1; res = val * q; } if (r != 0) { UInt64 v2; if (val <= (UInt64)(Int64)-1 / r) v2 = val * r / 100; else v2 = val / 100 * r; res += v2; if (res < v2) return (UInt64)(Int64)-1; } return res; } bool StringToBool(const wchar_t *s, bool &res) { if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) { res = true; return true; } if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF")) { res = false; return true; } return false; } HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest) { switch (prop.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK; case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG; default: break; } return E_INVALIDARG; } unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; number = ConvertStringToUInt32(start, &end); return (unsigned)(end - start); } static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number) { const wchar_t *start = srcString; const wchar_t *end; number = ConvertStringToUInt64(start, &end); return (unsigned)(end - start); } HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { // =VT_UI4 // =VT_EMPTY : it doesn't change (resValue), and returns S_OK // {stringUInt32}=VT_EMPTY if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; return S_OK; } if (prop.vt != VT_EMPTY) return E_INVALIDARG; if (name.IsEmpty()) return S_OK; UInt32 v; if (ParseStringToUInt32(name, v) != name.Len()) return E_INVALIDARG; resValue = v; return S_OK; } HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force) { force = false; UString s; if (name.IsEmpty()) { if (prop.vt == VT_UI4) { numThreads = prop.ulVal; force = true; return S_OK; } bool val; HRESULT res = PROPVARIANT_to_bool(prop, val); if (res == S_OK) { if (!val) { numThreads = 1; force = true; } // force = true; for debug // "(VT_BOOL = VARIANT_TRUE)" set "force = false" and doesn't change numThreads return S_OK; } if (prop.vt != VT_BSTR) return res; s.SetFromBstr(prop.bstrVal); if (s.IsEmpty()) return E_INVALIDARG; } else { if (prop.vt != VT_EMPTY) return E_INVALIDARG; s = name; } s.MakeLower_Ascii(); const wchar_t *start = s; UInt32 v = numThreads; /* we force up, if threads number specified only `d` will force it down */ bool force_loc = true; for (;;) { const wchar_t c = *start; if (!c) break; if (c == 'd') { force_loc = false; // force down start++; continue; } if (c == 'u') { force_loc = true; // force up start++; continue; } bool isPercent = false; if (c == 'p') { isPercent = true; start++; } const wchar_t *end; v = ConvertStringToUInt32(start, &end); if (end == start) return E_INVALIDARG; if (isPercent) v = numThreads * v / 100; start = end; } numThreads = v; force = force_loc; return S_OK; } static HRESULT SetLogSizeProp(UInt64 number, NCOM::CPropVariant &destProp) { if (number >= 64) return E_INVALIDARG; UInt32 val32; if (number < 32) val32 = (UInt32)1 << (unsigned)number; /* else if (number == 32 && reduce_4GB_to_32bits) val32 = (UInt32)(Int32)-1; */ else { destProp = (UInt64)((UInt64)1 << (unsigned)number); return S_OK; } destProp = (UInt32)val32; return S_OK; } static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp) { /* if (reduce_4GB_to_32bits) we can reduce (4 GiB) property to (4 GiB - 1). to fit the value to UInt32 for clients that do not support 64-bit values */ const wchar_t *end; const UInt64 number = ConvertStringToUInt64(s, &end); const unsigned numDigits = (unsigned)(end - s.Ptr()); if (numDigits == 0 || s.Len() > numDigits + 1) return E_INVALIDARG; if (s.Len() == numDigits) return SetLogSizeProp(number, destProp); unsigned numBits; switch (MyCharLower_Ascii(s[numDigits])) { case 'b': numBits = 0; break; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; default: return E_INVALIDARG; } const UInt64 range4g = ((UInt64)1 << (32 - numBits)); if (number < range4g) destProp = (UInt32)((UInt32)number << numBits); /* else if (number == range4g && reduce_4GB_to_32bits) destProp = (UInt32)(Int32)-1; */ else if (numBits == 0) destProp = (UInt64)number; else if (number >= ((UInt64)1 << (64 - numBits))) return E_INVALIDARG; else destProp = (UInt64)((UInt64)number << numBits); return S_OK; } static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp) { if (prop.vt == VT_UI4) return SetLogSizeProp(prop.ulVal, destProp); if (prop.vt == VT_BSTR) { UString s; s = prop.bstrVal; return StringToDictSize(s, destProp); } return E_INVALIDARG; } void CProps::AddProp32(PROPID propid, UInt32 val) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = (UInt32)val; } void CProps::AddPropBool(PROPID propid, bool val) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = val; } class CCoderProps { PROPID *_propIDs; NCOM::CPropVariant *_props; unsigned _numProps; unsigned _numPropsMax; public: CCoderProps(unsigned numPropsMax): _propIDs(NULL), _props(NULL), _numProps(0), _numPropsMax(numPropsMax) { _propIDs = new PROPID[numPropsMax]; _props = new NCOM::CPropVariant[numPropsMax]; } ~CCoderProps() { delete []_propIDs; delete []_props; } void AddProp(const CProp &prop); HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties) { return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps); } }; void CCoderProps::AddProp(const CProp &prop) { if (_numProps >= _numPropsMax) throw 1; _propIDs[_numProps] = prop.Id; _props[_numProps] = prop.Value; _numProps++; } HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const { return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL); } HRESULT CProps::SetCoderProps_DSReduce_Aff( ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const { CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) ); FOR_VECTOR (i, Props) coderProps.AddProp(Props[i]); if (dataSizeReduce) { CProp prop; prop.Id = NCoderPropID::kReduceSize; prop.Value = *dataSizeReduce; coderProps.AddProp(prop); } if (affinity) { CProp prop; prop.Id = NCoderPropID::kAffinity; prop.Value = *affinity; coderProps.AddProp(prop); } return coderProps.SetProps(scp); } int CMethodProps::FindProp(PROPID id) const { for (unsigned i = Props.Size(); i != 0;) if (Props[--i].Id == id) return (int)i; return -1; } unsigned CMethodProps::GetLevel() const { int i = FindProp(NCoderPropID::kLevel); if (i < 0) return 5; if (Props[(unsigned)i].Value.vt != VT_UI4) return 9; UInt32 level = Props[(unsigned)i].Value.ulVal; return level > 9 ? 9 : (unsigned)level; } struct CNameToPropID { VARTYPE VarType; const char *Name; }; // the following are related to NCoderPropID::EEnum values // NCoderPropID::k_NUM_DEFINED static const CNameToPropID g_NameToPropID[] = { { VT_UI4, "" }, { VT_UI4, "d" }, { VT_UI4, "mem" }, { VT_UI4, "o" }, { VT_UI8, "c" }, { VT_UI4, "pb" }, { VT_UI4, "lc" }, { VT_UI4, "lp" }, { VT_UI4, "fb" }, { VT_BSTR, "mf" }, { VT_UI4, "mc" }, { VT_UI4, "pass" }, { VT_UI4, "a" }, { VT_UI4, "mt" }, { VT_BOOL, "eos" }, { VT_UI4, "x" }, { VT_UI8, "reduce" }, { VT_UI8, "expect" }, { VT_UI8, "cc" }, // "cc" in v23, "b" in v22.01 { VT_UI4, "check" }, { VT_BSTR, "filter" }, { VT_UI8, "memuse" }, { VT_UI8, "aff" }, { VT_UI4, "offset" }, { VT_UI4, "zhb" } /* , // { VT_UI4, "zhc" }, // { VT_UI4, "zhd" }, // { VT_UI4, "zcb" }, { VT_UI4, "dc" }, { VT_UI4, "zx" }, { VT_UI4, "zf" }, { VT_UI4, "zmml" }, { VT_UI4, "zov" }, { VT_BOOL, "zmfr" }, { VT_BOOL, "zle" }, // long enable // { VT_UI4, "zldb" }, { VT_UI4, "zld" }, { VT_UI4, "zlhb" }, { VT_UI4, "zlmml" }, { VT_UI4, "zlbb" }, { VT_UI4, "zlhrb" }, { VT_BOOL, "zwus" }, { VT_BOOL, "zshp" }, { VT_BOOL, "zshs" }, { VT_BOOL, "zshe" }, { VT_BOOL, "zshg" }, { VT_UI4, "zpsm" } */ // { VT_UI4, "mcb" }, // mc log version // { VT_UI4, "ztlen" }, // fb ? }; /* #if defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 200410L) || (defined(_MSC_VER) && _MSC_VER >= 1600) #if (defined(__cplusplus) && __cplusplus < 201103L) \ && defined(__clang__) && __clang_major__ >= 4 #pragma GCC diagnostic ignored "-Wc11-extensions" #endif static_assert(Z7_ARRAY_SIZE(g_NameToPropID) == NCoderPropID::k_NUM_DEFINED, "g_NameToPropID doesn't match NCoderPropID enum"); #endif */ static int FindPropIdExact(const UString &name) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NameToPropID); i++) if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) return (int)i; return -1; } static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI8 && srcProp.vt == VT_UI4) { destProp = (UInt64)srcProp.ulVal; return true; } if (varType == VT_BOOL) { bool res; if (PROPVARIANT_to_bool(srcProp, res) != S_OK) return false; destProp = res; return true; } if (srcProp.vt == VT_EMPTY) { destProp = srcProp; return true; } return false; } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString s; unsigned len = srcString.Len(); if (len == 0) return; for (unsigned i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(s); s.Empty(); } else s += c; } subStrings.Add(s); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name.SetFrom(param, (unsigned)eqPos); value = param.Ptr((unsigned)(eqPos + 1)); return; } unsigned i; for (i = 0; i < param.Len(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') break; } name.SetFrom(param, i); value = param.Ptr(i); } static bool IsLogSizeProp(PROPID propid) { switch (propid) { case NCoderPropID::kDictionarySize: case NCoderPropID::kUsedMemorySize: case NCoderPropID::kBlockSize: case NCoderPropID::kBlockSize2: /* case NCoderPropID::kChainSize: case NCoderPropID::kLdmWindowSize: */ // case NCoderPropID::kReduceSize: return true; default: break; } return false; } HRESULT CMethodProps::SetParam(const UString &name, const UString &value) { int index = FindPropIdExact(name); if (index < 0) { // 'b' was used as NCoderPropID::kBlockSize2 before v23 if (!name.IsEqualTo_Ascii_NoCase("b") || value.Find(L':') >= 0) return E_INVALIDARG; index = NCoderPropID::kBlockSize2; } const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { RINOK(StringToDictSize(value, prop.Value)) } else { NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else if (!value.IsEmpty()) { if (nameToPropID.VarType == VT_UI4) { UInt32 number; if (ParseStringToUInt32(value, number) == value.Len()) propValue = number; else propValue = value; } else if (nameToPropID.VarType == VT_UI8) { UInt64 number; if (ParseStringToUInt64(value, number) == value.Len()) propValue = number; else propValue = value; } else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } Props.Add(prop); return S_OK; } HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) { UStringVector params; SplitParams(srcString, params); FOR_VECTOR (i, params) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(name, value)) } return S_OK; } HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) { if (realName.Len() == 0) { // [empty]=method return E_INVALIDARG; } if (value.vt == VT_EMPTY) { // {realName}=[empty] UString name, valueStr; SplitParam(realName, name, valueStr); return SetParam(name, valueStr); } // {realName}=value const int index = FindPropIdExact(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { RINOK(PROPVARIANT_to_DictSize(value, prop.Value)) } else { if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } Props.Add(prop); return S_OK; } static UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads) { UInt32 hs = dict - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; if (hs >= (1 << 24)) hs >>= 1; hs |= (1 << 16) - 1; // if (numHashBytes >= 5) if (!isBt) hs |= (256 << 10) - 1; hs++; UInt64 size1 = (UInt64)hs * 4; size1 += (UInt64)dict * 4; if (isBt) size1 += (UInt64)dict * 4; size1 += (2 << 20); if (numThreads > 1 && isBt) size1 += (2 << 20) + (4 << 20); return size1; } static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28; UInt64 CMethodProps::Get_Lzma_MemUsage(bool addSlidingWindowSize) const { const UInt64 dicSize = Get_Lzma_DicSize(); const bool isBt = Get_Lzma_MatchFinder_IsBt(); const UInt32 dict32 = (dicSize >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dicSize); const UInt32 numThreads = Get_Lzma_NumThreads(); UInt64 size = GetMemoryUsage_LZMA(dict32, isBt, numThreads); if (addSlidingWindowSize) { const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16); UInt64 blockSize = (UInt64)dict32 + (1 << 16) + (numThreads > 1 ? (1 << 20) : 0); blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)); if (blockSize >= kBlockSizeMax) blockSize = kBlockSizeMax; size += blockSize; } return size; } HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) { MethodName.Empty(); int splitPos = s.Find(L':'); { UString temp = s; if (splitPos >= 0) temp.DeleteFrom((unsigned)splitPos); if (!temp.IsAscii()) return E_INVALIDARG; MethodName.SetFromWStr_if_Ascii(temp); } if (splitPos < 0) return S_OK; PropsString = s.Ptr((unsigned)(splitPos + 1)); return ParseParamsFromString(PropsString); } HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) { if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m")) return ParseParamsFromPROPVARIANT(realName, value); // -m{N}=method if (value.vt != VT_BSTR) return E_INVALIDARG; UString s; s = value.bstrVal; return ParseMethodFromString(s); } tmp41wklro_/CPP/7zip/Common/MethodProps.h0000444000175000001440000002236014357314620021331 0ustar nabijaczleweliusers// MethodProps.h #ifndef ZIP7_INC_7Z_METHOD_PROPS_H #define ZIP7_INC_7Z_METHOD_PROPS_H #include "../../Common/MyString.h" #include "../../Common/Defs.h" #include "../../Windows/Defs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" // UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads); inline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents) { if (percents == 0) return 0; if (val <= (UInt64)(Int64)-1 / percents) return val * percents / 100; return val / 100 * percents; } UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents); bool StringToBool(const wchar_t *s, bool &res); HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); /* if (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK. So you must set (resValue) for default value before calling */ HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); /* input: (numThreads = the_number_of_processors) */ HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force); inline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads) { bool forced = false; numThreads = numCPUs; return ParseMtProp2(name, prop, numThreads, forced); } struct CProp { PROPID Id; bool IsOptional; NWindows::NCOM::CPropVariant Value; CProp(): IsOptional(false) {} }; struct CProps { CObjectVector Props; void Clear() { Props.Clear(); } bool AreThereNonOptionalProps() const { FOR_VECTOR (i, Props) if (!Props[i].IsOptional) return true; return false; } void AddProp32(PROPID propid, UInt32 val); void AddPropBool(PROPID propid, bool val); void AddProp_Ascii(PROPID propid, const char *s) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = s; } HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; }; class CMethodProps: public CProps { HRESULT SetParam(const UString &name, const UString &value); public: unsigned GetLevel() const; int Get_NumThreads() const { const int i = FindProp(NCoderPropID::kNumThreads); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return (int)val.ulVal; } return -1; } bool Get_DicSize(UInt64 &res) const { res = 0; const int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { res = val.ulVal; return true; } if (val.vt == VT_UI8) { res = val.uhVal.QuadPart; return true; } } return false; } int FindProp(PROPID id) const; UInt32 Get_Lzma_Algo() const { int i = FindProp(NCoderPropID::kAlgorithm); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return val.ulVal; } return GetLevel() >= 5 ? 1 : 0; } UInt64 Get_Lzma_DicSize() const { UInt64 v; if (Get_DicSize(v)) return v; const unsigned level = GetLevel(); const UInt32 dictSize = ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : ( level <= 6 ? ((UInt32)1 << (level + 19)) : ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) ))); return dictSize; } bool Get_Lzma_MatchFinder_IsBt() const { const int i = FindProp(NCoderPropID::kMatchFinder); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BSTR) return ((val.bstrVal[0] | 0x20) != 'h'); // check for "hc" } return GetLevel() >= 5; } bool Get_Lzma_Eos() const { const int i = FindProp(NCoderPropID::kEndMarker); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BOOL) return VARIANT_BOOLToBool(val.boolVal); } return false; } bool Are_Lzma_Model_Props_Defined() const { if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; return false; } UInt32 Get_Lzma_NumThreads() const { if (Get_Lzma_Algo() == 0) return 1; int numThreads = Get_NumThreads(); if (numThreads >= 0) return numThreads < 2 ? 1 : 2; return 2; } UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const; /* returns -1, if numThreads is unknown */ int Get_Xz_NumThreads(UInt32 &lzmaThreads) const { lzmaThreads = 1; int numThreads = Get_NumThreads(); if (numThreads >= 0 && numThreads <= 1) return 1; if (Get_Lzma_Algo() != 0) lzmaThreads = 2; return numThreads; } UInt64 GetProp_BlockSize(PROPID id) const { const int i = FindProp(id); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { return val.ulVal; } if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } } return 0; } UInt64 Get_Xz_BlockSize() const { { UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize); UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2); UInt64 minSize = MyMin(blockSize1, blockSize2); if (minSize != 0) return minSize; UInt64 maxSize = MyMax(blockSize1, blockSize2); if (maxSize != 0) return maxSize; } const UInt32 kMinSize = (UInt32)1 << 20; const UInt32 kMaxSize = (UInt32)1 << 28; const UInt64 dictSize = Get_Lzma_DicSize(); /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */ UInt64 blockSize = (UInt64)dictSize << 2; if (blockSize < kMinSize) blockSize = kMinSize; if (blockSize > kMaxSize) blockSize = kMaxSize; if (blockSize < dictSize) blockSize = dictSize; blockSize += (kMinSize - 1); blockSize &= ~(UInt64)(kMinSize - 1); return blockSize; } UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const { fixedNumber = false; int numThreads = Get_NumThreads(); if (numThreads >= 0) { fixedNumber = true; if (numThreads < 1) return 1; const unsigned kNumBZip2ThreadsMax = 64; if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; return (unsigned)numThreads; } return 1; } UInt32 Get_BZip2_BlockSize() const { const int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { UInt32 blockSize = val.ulVal; const UInt32 kDicSizeMin = 100000; const UInt32 kDicSizeMax = 900000; if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; return blockSize; } } const unsigned level = GetLevel(); return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); } UInt64 Get_Ppmd_MemSize() const { const int i = FindProp(NCoderPropID::kUsedMemorySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return val.ulVal; if (val.vt == VT_UI8) return val.uhVal.QuadPart; } const unsigned level = GetLevel(); const UInt32 mem = (UInt32)1 << (level + 19); return mem; } void AddProp_Level(UInt32 level) { AddProp32(NCoderPropID::kLevel, level); } void AddProp_NumThreads(UInt32 numThreads) { AddProp32(NCoderPropID::kNumThreads, numThreads); } void AddProp_EndMarker_if_NotFound(bool eos) { if (FindProp(NCoderPropID::kEndMarker) < 0) AddPropBool(NCoderPropID::kEndMarker, eos); } void AddProp_BlockSize2(UInt64 blockSize2) { if (FindProp(NCoderPropID::kBlockSize2) < 0) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = NCoderPropID::kBlockSize2; prop.Value = blockSize2; } } HRESULT ParseParamsFromString(const UString &srcString); HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); }; class COneMethodInfo: public CMethodProps { public: AString MethodName; UString PropsString; void Clear() { CMethodProps::Clear(); MethodName.Empty(); PropsString.Empty(); } bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); HRESULT ParseMethodFromString(const UString &s); }; #endif tmp41wklro_/CPP/7zip/Common/MultiOutStream.cpp0000444000175000001440000006020614475550760022367 0ustar nabijaczleweliusers// MultiOutStream.cpp #include "StdAfx.h" // #define DEBUG_VOLUMES #ifdef DEBUG_VOLUMES #include #define PRF(x) x; #else #define PRF(x) #endif #include "../../Common/ComTry.h" #include "../../Windows/FileDir.h" #include "../../Windows/FileFind.h" #include "../../Windows/System.h" #include "MultiOutStream.h" using namespace NWindows; using namespace NFile; using namespace NDir; static const unsigned k_NumVols_MAX = k_VectorSizeMax - 1; // 2; // for debug /* #define UPDATE_HRES(hres, x) \ { const HRESULT res2 = (x); if (hres == SZ_OK) hres = res2; } */ HRESULT CMultiOutStream::Destruct() { COM_TRY_BEGIN HRESULT hres = S_OK; HRESULT hres3 = S_OK; while (!Streams.IsEmpty()) { try { HRESULT hres2; if (NeedDelete) { /* we could call OptReOpen_and_SetSize() to test that we try to delete correct file, but we cannot guarantee that (RealSize) will be correct after Write() or another failures. And we still want to delete files even for such cases. So we don't check for OptReOpen_and_SetSize() here: */ // if (OptReOpen_and_SetSize(Streams.Size() - 1, 0) == S_OK) hres2 = CloseStream_and_DeleteFile(Streams.Size() - 1); } else { hres2 = CloseStream(Streams.Size() - 1); } if (hres == S_OK) hres = hres2; } catch(...) { hres3 = E_OUTOFMEMORY; } { /* Stream was released in CloseStream_*() above already, and it was removed from linked list it's some unexpected case, if Stream is still attached here. So the following code is optional: */ CVolStream &s = Streams.Back(); if (s.Stream) { if (hres3 == S_OK) hres3 = E_FAIL; s.Stream.Detach(); /* it will be not failure, even if we call RemoveFromLinkedList() twice for same CVolStream in this Destruct() function */ RemoveFromLinkedList(Streams.Size() - 1); } } Streams.DeleteBack(); // Delete_LastStream_Records(); } if (hres == S_OK) hres = hres3; if (hres == S_OK && NumListItems != 0) hres = E_FAIL; return hres; COM_TRY_END } CMultiOutStream::~CMultiOutStream() { // we try to avoid exception in destructors Destruct(); } void CMultiOutStream::Init(const CRecordVector &sizes) { Streams.Clear(); InitLinkedList(); Sizes = sizes; NeedDelete = true; MTime_Defined = false; FinalVol_WasReopen = false; NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks(); _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; _absLimit = (UInt64)(Int64)-1; _restrict_Begin = 0; _restrict_End = (UInt64)(Int64)-1; _restrict_Global = 0; UInt64 sum = 0; unsigned i = 0; for (i = 0; i < Sizes.Size(); i++) { if (i >= k_NumVols_MAX) { _absLimit = sum; break; } const UInt64 size = Sizes[i]; const UInt64 next = sum + size; if (next < sum) break; sum = next; } // if (Sizes.IsEmpty()) throw "no volume sizes"; const UInt64 size = Sizes.Back(); if (size == 0) throw "zero size last volume"; if (i == Sizes.Size()) if ((_absLimit - sum) / size >= (k_NumVols_MAX - i)) _absLimit = sum + (k_NumVols_MAX - i) * size; } /* IsRestricted(): we must call only if volume is full (s.RealSize==VolSize) or finished. the function doesn't use VolSize and it uses s.RealSize instead. it returns true : if stream is restricted, and we can't close that stream it returns false : if there is no restriction, and we can close that stream Note: (RealSize == 0) (empty volume) on restriction bounds are supposed as non-restricted */ bool CMultiOutStream::IsRestricted(const CVolStream &s) const { if (s.Start < _restrict_Global) return true; if (_restrict_Begin == _restrict_End) return false; if (_restrict_Begin <= s.Start) return _restrict_End > s.Start; return _restrict_Begin < s.Start + s.RealSize; } /* // this function check also _length and volSize bool CMultiOutStream::IsRestricted_for_Close(unsigned index) const { const CVolStream &s = Streams[index]; if (_length <= s.Start) // we don't close streams after the end, because we still can write them later return true; // (_length > s.Start) const UInt64 volSize = GetVolSize_for_Stream(index); if (volSize == 0) return IsRestricted_Empty(s); if (_length - s.Start < volSize) return true; return IsRestricted(s); } */ FString CMultiOutStream::GetFilePath(unsigned index) { FString name; name.Add_UInt32((UInt32)(index + 1)); while (name.Len() < 3) name.InsertAtFront(FTEXT('0')); name.Insert(0, Prefix); return name; } // we close stream, but we still keep item in Streams[] vector HRESULT CMultiOutStream::CloseStream(unsigned index) { CVolStream &s = Streams[index]; if (s.Stream) { RINOK(s.StreamSpec->Close()) // the following two commands must be called together: s.Stream.Release(); RemoveFromLinkedList(index); } return S_OK; } // we close stream and delete file, but we still keep item in Streams[] vector HRESULT CMultiOutStream::CloseStream_and_DeleteFile(unsigned index) { PRF(printf("\n====== %u, CloseStream_AndDelete \n", index)) RINOK(CloseStream(index)) FString path = GetFilePath(index); path += Streams[index].Postfix; // we can checki that file exist // if (NFind::DoesFileExist_Raw(path)) if (!DeleteFileAlways(path)) return GetLastError_noZero_HRESULT(); return S_OK; } HRESULT CMultiOutStream::CloseStream_and_FinalRename(unsigned index) { PRF(printf("\n====== %u, CloseStream_and_FinalRename \n", index)) CVolStream &s = Streams[index]; // HRESULT res = S_OK; bool mtime_WasSet = false; if (MTime_Defined && s.Stream) { if (s.StreamSpec->SetMTime(&MTime)) mtime_WasSet = true; // else res = GetLastError_noZero_HRESULT(); } RINOK(CloseStream(index)) if (s.Postfix.IsEmpty()) // if Postfix is empty, the path is already final return S_OK; const FString path = GetFilePath(index); FString tempPath = path; tempPath += s.Postfix; if (MTime_Defined && !mtime_WasSet) { if (!SetDirTime(tempPath, NULL, NULL, &MTime)) { // res = GetLastError_noZero_HRESULT(); } } if (!MyMoveFile(tempPath, path)) return GetLastError_noZero_HRESULT(); /* we clear CVolStream::Postfix. So we will not use Temp path anymore for this stream, and we will work only with final path */ s.Postfix.Empty(); // we can ignore set_mtime error or we can return it return S_OK; // return res; } HRESULT CMultiOutStream::PrepareToOpenNew() { PRF(printf("PrepareToOpenNew NumListItems =%u, NumOpenFiles_AllowedMax = %u \n", NumListItems, NumOpenFiles_AllowedMax)) if (NumListItems < NumOpenFiles_AllowedMax) return S_OK; /* when we create zip archive: in most cases we need only starting data of restricted region for rewriting zip's local header. So here we close latest created volume (from Head), and we try to keep oldest volumes that will be used for header rewriting later. */ const int index = Head; if (index == -1) return E_FAIL; PRF(printf("\n== %u, PrepareToOpenNew::CloseStream, NumListItems =%u \n", index, NumListItems)) /* we don't expect non-restricted stream here in normal cases (if _restrict_Global was not changed). if there was non-restricted stream, it should be closed before */ // if (!IsRestricted_for_Close(index)) return CloseStream_and_FinalRename(index); return CloseStream((unsigned)index); } HRESULT CMultiOutStream::CreateNewStream(UInt64 newSize) { PRF(printf("\n== %u, CreateNewStream, size =%u \n", Streams.Size(), (unsigned)newSize)) if (Streams.Size() >= k_NumVols_MAX) return E_INVALIDARG; // E_OUTOFMEMORY RINOK(PrepareToOpenNew()) CVolStream s; s.StreamSpec = new COutFileStream; s.Stream = s.StreamSpec; const FString path = GetFilePath(Streams.Size()); if (NFind::DoesFileExist_Raw(path)) return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); if (!CreateTempFile2(path, false, s.Postfix, &s.StreamSpec->File)) return GetLastError_noZero_HRESULT(); s.Start = GetGlobalOffset_for_NewStream(); s.Pos = 0; s.RealSize = 0; const unsigned index = Streams.Add(s); InsertToLinkedList(index); if (newSize != 0) return s.SetSize2(newSize); return S_OK; } HRESULT CMultiOutStream::CreateStreams_If_Required(unsigned streamIndex) { // UInt64 lastStreamSize = 0; for (;;) { const unsigned numStreamsBefore = Streams.Size(); if (streamIndex < numStreamsBefore) return S_OK; UInt64 newSize; if (streamIndex == numStreamsBefore) { // it's final volume that will be used for real writing. /* SetSize(_offsetPos) is not required, because the file Size will be set later by calling Seek() with Write() */ newSize = 0; // lastStreamSize; } else { // it's intermediate volume. So we need full volume size newSize = GetVolSize_for_Stream(numStreamsBefore); } RINOK(CreateNewStream(newSize)) // optional check if (numStreamsBefore + 1 != Streams.Size()) return E_FAIL; if (streamIndex != numStreamsBefore) { // it's intermediate volume. So we can close it, if it's non-restricted bool isRestricted; { const CVolStream &s = Streams[numStreamsBefore]; if (newSize == 0) isRestricted = IsRestricted_Empty(s); else isRestricted = IsRestricted(s); } if (!isRestricted) { RINOK(CloseStream_and_FinalRename(numStreamsBefore)) } } } } HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex) { PRF(printf("\n====== %u, ReOpenStream \n", streamIndex)) RINOK(PrepareToOpenNew()) CVolStream &s = Streams[streamIndex]; FString path = GetFilePath(streamIndex); path += s.Postfix; s.StreamSpec = new COutFileStream; s.Stream = s.StreamSpec; s.Pos = 0; HRESULT hres; if (s.StreamSpec->Open_EXISTING(path)) { if (s.Postfix.IsEmpty()) { /* it's unexpected case that we open finished volume. It can mean that the code for restriction is incorrect */ FinalVol_WasReopen = true; } UInt64 realSize = 0; hres = s.StreamSpec->GetSize(&realSize); if (hres == S_OK) { if (realSize == s.RealSize) { PRF(printf("\n ReOpenStream OK realSize = %u\n", (unsigned)realSize)) InsertToLinkedList(streamIndex); return S_OK; } // file size was changed between Close() and ReOpen() // we must release Stream to be consistent with linked list hres = E_FAIL; } } else hres = GetLastError_noZero_HRESULT(); s.Stream.Release(); s.StreamSpec = NULL; return hres; } /* Sets size of stream, if new size is not equal to old size (RealSize). If stream was closed and size change is required, it reopens the stream. */ HRESULT CMultiOutStream::OptReOpen_and_SetSize(unsigned index, UInt64 size) { CVolStream &s = Streams[index]; if (size == s.RealSize) return S_OK; if (!s.Stream) { RINOK(ReOpenStream(index)) } PRF(printf("\n== %u, OptReOpen_and_SetSize, size =%u RealSize = %u\n", index, (unsigned)size, (unsigned)s.RealSize)) // comment it to debug tail after data return s.SetSize2(size); } /* call Normalize_finalMode(false), if _length was changed. for all streams starting after _length: - it sets zero size - it still keeps file open Note: after _length reducing with CMultiOutStream::SetSize() we can have very big number of empty streams at the end of Streams[] list. And Normalize_finalMode() will runs all these empty streams of Streams[] vector. So it can be ineffective, if we call Normalize_finalMode() many times after big reducing of (_length). call Normalize_finalMode(true) to set final presentations of all streams for all streams starting after _length: - it sets zero size - it removes file - it removes CVolStream object from Streams[] vector Note: we don't remove zero sized first volume, if (_length == 0) */ HRESULT CMultiOutStream::Normalize_finalMode(bool finalMode) { PRF(printf("\n== Normalize_finalMode: _length =%d \n", (unsigned)_length)) unsigned i = Streams.Size(); UInt64 offset = 0; /* At first we normalize (reduce or increase) the sizes of all existing streams in Streams[] that can be affected by changed _length. And we remove tailing zero-size streams, if (finalMode == true) */ while (i != 0) { offset = Streams[--i].Start; // it's last item in Streams[] // we don't want to remove first volume if (offset < _length || i == 0) { const UInt64 volSize = GetVolSize_for_Stream(i); UInt64 size = _length - offset; // (size != 0) here if (size > volSize) size = volSize; RINOK(OptReOpen_and_SetSize(i, size)) if (_length - offset <= volSize) return S_OK; // _length - offset > volSize offset += volSize; // _length > offset break; // UPDATE_HRES(res, OptReOpen_and_SetSize(i, size)); } /* we Set Size of stream to zero even for (finalMode==true), although that stream will be deleted in next commands */ // UPDATE_HRES(res, OptReOpen_and_SetSize(i, 0)); RINOK(OptReOpen_and_SetSize(i, 0)) if (finalMode) { RINOK(CloseStream_and_DeleteFile(i)) /* CVolStream::Stream was released above already, and it was removed from linked list. So we don't need to update linked list structure, when we delete last item in Streams[] */ Streams.DeleteBack(); // Delete_LastStream_Records(); } } /* now we create new zero-filled streams to cover all data up to _length */ if (_length == 0) return S_OK; // (offset) is start offset of next stream after existing Streams[] for (;;) { // _length > offset const UInt64 volSize = GetVolSize_for_Stream(Streams.Size()); UInt64 size = _length - offset; // (size != 0) here if (size > volSize) size = volSize; RINOK(CreateNewStream(size)) if (_length - offset <= volSize) return S_OK; // _length - offset > volSize) offset += volSize; // _length > offset } } HRESULT CMultiOutStream::FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes) { // at first we remove unused zero-sized streams after _length HRESULT res = Normalize_finalMode(true); numTotalVolumesRes = Streams.Size(); FOR_VECTOR (i, Streams) { const HRESULT res2 = CloseStream_and_FinalRename(i); if (res == S_OK) res = res2; } if (NumListItems != 0 && res == S_OK) res = E_FAIL; return res; } bool CMultiOutStream::SetMTime_Final(const CFiTime &mTime) { // we will set mtime only if new value differs from previous if (!FinalVol_WasReopen && MTime_Defined && Compare_FiTime(&MTime, &mTime) == 0) return true; bool res = true; FOR_VECTOR (i, Streams) { CVolStream &s = Streams[i]; if (s.Stream) { if (!s.StreamSpec->SetMTime(&mTime)) res = false; } else { if (!SetDirTime(GetFilePath(i), NULL, NULL, &mTime)) res = false; } } return res; } Z7_COM7F_IMF(CMultiOutStream::SetSize(UInt64 newSize)) { COM_TRY_BEGIN if ((Int64)newSize < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; if (newSize > _absLimit) { /* big seek value was sent to SetSize() or to Seek()+Write(). It can mean one of two situations: 1) some incorrect code called it with big seek value. 2) volume size was small, and we have too big number of volumes */ /* in Windows SetEndOfFile() can return: ERROR_NEGATIVE_SEEK: for >= (1 << 63) ERROR_INVALID_PARAMETER: for > (16 TiB - 64 KiB) ERROR_DISK_FULL: for <= (16 TiB - 64 KiB) */ // return E_FAIL; // return E_OUTOFMEMORY; return E_INVALIDARG; } if (newSize > _length) { // we don't expect such case. So we just define global restriction */ _restrict_Global = newSize; } else if (newSize < _restrict_Global) _restrict_Global = newSize; PRF(printf("\n== CMultiOutStream::SetSize, size =%u \n", (unsigned)newSize)) _length = newSize; return Normalize_finalMode(false); COM_TRY_END } Z7_COM7F_IMF(CMultiOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { COM_TRY_BEGIN if (processedSize) *processedSize = 0; if (size == 0) return S_OK; PRF(printf("\n -- CMultiOutStream::Write() : _absPos = %6u, size =%6u \n", (unsigned)_absPos, (unsigned)size)) if (_absPos > _length) { // it create data only up to _absPos. // but we still can need additional new streams, if _absPos at range of volume RINOK(SetSize(_absPos)) } while (size != 0) { UInt64 volSize; { if (_streamIndex < Sizes.Size() - 1) { volSize = Sizes[_streamIndex]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } } else { volSize = Sizes[Sizes.Size() - 1]; if (_offsetPos >= volSize) { const UInt64 v = _offsetPos / volSize; if (v >= ((UInt32)(Int32)-1) - _streamIndex) return E_INVALIDARG; // throw 202208; _streamIndex += (unsigned)v; _offsetPos -= (unsigned)v * volSize; } if (_streamIndex >= k_NumVols_MAX) return E_INVALIDARG; } } // (_offsetPos < volSize) here /* we can need to create one or more streams here, vol_size for some streams is allowed to be 0. Also we close some new created streams, if they are non-restricted */ // file Size will be set later by calling Seek() with Write() /* the case (_absPos > _length) was processed above with SetSize(_absPos), so here it's expected. that we can create optional zero-size streams and then _streamIndex */ RINOK(CreateStreams_If_Required(_streamIndex)) CVolStream &s = Streams[_streamIndex]; PRF(printf("\n%d, == Write : Pos = %u, RealSize = %u size =%u \n", _streamIndex, (unsigned)s.Pos, (unsigned)s.RealSize, size)) if (!s.Stream) { RINOK(ReOpenStream(_streamIndex)) } if (_offsetPos != s.Pos) { RINOK(s.Stream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL)) s.Pos = _offsetPos; } UInt32 curSize = size; { const UInt64 rem = volSize - _offsetPos; if (curSize > rem) curSize = (UInt32)rem; } // curSize != 0 UInt32 realProcessed = 0; HRESULT hres = s.Stream->Write(data, curSize, &realProcessed); data = (const void *)((const Byte *)data + realProcessed); size -= realProcessed; s.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_length < _absPos) _length = _absPos; if (s.RealSize < _offsetPos) s.RealSize = _offsetPos; if (processedSize) *processedSize += realProcessed; if (s.Pos == volSize) { bool isRestricted; if (volSize == 0) isRestricted = IsRestricted_Empty(s); else isRestricted = IsRestricted(s); if (!isRestricted) { const HRESULT res2 = CloseStream_and_FinalRename(_streamIndex); if (hres == S_OK) hres = res2; } _streamIndex++; _offsetPos = 0; } RINOK(hres) if (realProcessed == 0 && curSize != 0) return E_FAIL; // break; } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CMultiOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { PRF(printf("\n-- CMultiOutStream::Seek seekOrigin=%u Seek =%u\n", seekOrigin, (unsigned)offset)) switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _absPos; break; case STREAM_SEEK_END: offset += _length; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; if ((UInt64)offset != _absPos) { _absPos = (UInt64)offset; _offsetPos = (UInt64)offset; _streamIndex = 0; } if (newPosition) *newPosition = (UInt64)offset; return S_OK; } // result value will be saturated to (UInt32)(Int32)-1 unsigned CMultiOutStream::GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const { const unsigned last = Sizes.Size() - 1; for (unsigned i = 0; i < last; i++) { const UInt64 size = Sizes[i]; if (offset < size) { relOffset = offset; return i; } offset -= size; } const UInt64 size = Sizes[last]; const UInt64 v = offset / size; if (v >= ((UInt32)(Int32)-1) - last) return (unsigned)(int)-1; // saturation relOffset = offset - (unsigned)v * size; return last + (unsigned)(v); } Z7_COM7F_IMF(CMultiOutStream::SetRestriction(UInt64 begin, UInt64 end)) { COM_TRY_BEGIN // begin = end = 0; // for debug PRF(printf("\n==================== CMultiOutStream::SetRestriction %u, %u\n", (unsigned)begin, (unsigned)end)) if (begin > end) { // these value are FAILED values. return E_FAIL; // return E_INVALIDARG; /* // or we can ignore error with 3 ways: no change, non-restricted, saturation: end = begin; // non-restricted end = (UInt64)(Int64)-1; // saturation: return S_OK; */ } UInt64 b = _restrict_Begin; UInt64 e = _restrict_End; _restrict_Begin = begin; _restrict_End = end; if (b == e) // if there were no restriction before return S_OK; // no work to derestrict now. /* [b, e) is previous restricted region. So all volumes that intersect that [b, e) region are candidats for derestriction */ if (begin != end) // if there is new non-empty restricted region { /* Now we will try to reduce or change (b) and (e) bounds to reduce main loop that checks volumes for derestriction. We still use one big derestriction region in main loop, although in some cases we could have two smaller derestriction regions. Also usually restriction region cannot move back from previous start position, so (b <= begin) is expected here for normal cases */ if (b == begin) // if same low bounds b = end; // we need to derestrict only after the end of new restricted region if (e == end) // if same high bounds e = begin; // we need to derestrict only before the begin of new restricted region } if (b > e) // || b == (UInt64)(Int64)-1 return S_OK; /* Here we close finished volumes that are not restricted anymore. We close (low number) volumes at first. */ UInt64 offset; unsigned index = GetStreamIndex_for_Offset(b, offset); for (; index < Streams.Size(); index++) { { const CVolStream &s = Streams[index]; if (_length <= s.Start) break; // we don't close streams after _length // (_length > s.Start) const UInt64 volSize = GetVolSize_for_Stream(index); if (volSize == 0) { if (e < s.Start) break; // we don't close empty stream, if next byte [s.Start, s.Start] is restricted if (IsRestricted_Empty(s)) continue; } else { if (e <= s.Start) break; // we don't close non full streams if (_length - s.Start < volSize) break; // (volSize == s.RealSize) is expected here. So no need to check it // if (volSize != s.RealSize) break; if (IsRestricted(s)) continue; } } RINOK(CloseStream_and_FinalRename(index)) } return S_OK; COM_TRY_END } tmp41wklro_/CPP/7zip/Common/MultiOutStream.h0000444000175000001440000001052714413324420022015 0ustar nabijaczleweliusers// MultiOutStream.h #ifndef ZIP7_INC_MULTI_OUT_STREAM_H #define ZIP7_INC_MULTI_OUT_STREAM_H #include "FileStreams.h" Z7_CLASS_IMP_COM_2( CMultiOutStream , IOutStream , IStreamSetRestriction ) Z7_IFACE_COM7_IMP(ISequentialOutStream) Z7_CLASS_NO_COPY(CMultiOutStream) struct CVolStream { COutFileStream *StreamSpec; CMyComPtr Stream; UInt64 Start; // start pos of current Stream in global stream UInt64 Pos; // pos in current Stream UInt64 RealSize; int Next; // next older int Prev; // prev newer AString Postfix; HRESULT SetSize2(UInt64 size) { const HRESULT res = Stream->SetSize(size); if (res == SZ_OK) RealSize = size; return res; } }; unsigned _streamIndex; // (_streamIndex >= Stream.Size()) is allowed in some internal code UInt64 _offsetPos; // offset relative to Streams[_streamIndex] volume. (_offsetPos >= volSize is allowed) UInt64 _absPos; UInt64 _length; // virtual Length UInt64 _absLimit; CObjectVector Streams; CRecordVector Sizes; UInt64 _restrict_Begin; UInt64 _restrict_End; UInt64 _restrict_Global; unsigned NumOpenFiles_AllowedMax; // ----- Double Linked List ----- unsigned NumListItems; int Head; // newest int Tail; // oldest void InitLinkedList() { Head = -1; Tail = -1; NumListItems = 0; } void InsertToLinkedList(unsigned index) { { CVolStream &node = Streams[index]; node.Next = Head; node.Prev = -1; } if (Head != -1) Streams[(unsigned)Head].Prev = (int)index; else { // if (Tail != -1) throw 1; Tail = (int)index; } Head = (int)index; NumListItems++; } void RemoveFromLinkedList(unsigned index) { CVolStream &s = Streams[index]; if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev; if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next; s.Next = -1; // optional s.Prev = -1; // optional NumListItems--; } /* void Delete_LastStream_Records() { if (Streams.Back().Stream) RemoveFromLinkedList(Streams.Size() - 1); Streams.DeleteBack(); } */ UInt64 GetVolSize_for_Stream(unsigned i) const { const unsigned last = Sizes.Size() - 1; return Sizes[i < last ? i : last]; } UInt64 GetGlobalOffset_for_NewStream() const { return Streams.Size() == 0 ? 0: Streams.Back().Start + GetVolSize_for_Stream(Streams.Size() - 1); } unsigned GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const; bool IsRestricted(const CVolStream &s) const; bool IsRestricted_Empty(const CVolStream &s) const { // (s) must be stream that has (VolSize == 0). // we treat empty stream as restricted, if next byte is restricted. if (s.Start < _restrict_Global) return true; return (_restrict_Begin != _restrict_End) && (_restrict_Begin <= s.Start) && (_restrict_Begin == s.Start || _restrict_End > s.Start); } // bool IsRestricted_for_Close(unsigned index) const; FString GetFilePath(unsigned index); HRESULT CloseStream(unsigned index); HRESULT CloseStream_and_DeleteFile(unsigned index); HRESULT CloseStream_and_FinalRename(unsigned index); HRESULT PrepareToOpenNew(); HRESULT CreateNewStream(UInt64 newSize); HRESULT CreateStreams_If_Required(unsigned streamIndex); HRESULT ReOpenStream(unsigned streamIndex); HRESULT OptReOpen_and_SetSize(unsigned index, UInt64 size); HRESULT Normalize_finalMode(bool finalMode); public: FString Prefix; CFiTime MTime; bool MTime_Defined; bool FinalVol_WasReopen; bool NeedDelete; CMultiOutStream() {} ~CMultiOutStream(); void Init(const CRecordVector &sizes); bool SetMTime_Final(const CFiTime &mTime); UInt64 GetSize() const { return _length; } /* it makes final flushing, closes open files and renames to final name if required but it still keeps Streams array of all closed files. So we still can delete all files later, if required */ HRESULT FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes); // Destruct object without exceptions HRESULT Destruct(); }; #endif tmp41wklro_/CPP/7zip/Common/OffsetStream.cpp0000444000175000001440000000173114413277340022021 0ustar nabijaczleweliusers// OffsetStream.cpp #include "StdAfx.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); } Z7_COM7F_IMF(COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { return _stream->Write(data, size, processedSize); } Z7_COM7F_IMF(COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { if (seekOrigin == STREAM_SEEK_SET) { if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; offset += _offset; } UInt64 absoluteNewPosition = 0; // =0 for gcc-10 const HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition) *newPosition = absoluteNewPosition - _offset; return result; } Z7_COM7F_IMF(COffsetOutStream::SetSize(UInt64 newSize)) { return _stream->SetSize(_offset + newSize); } tmp41wklro_/CPP/7zip/Common/OffsetStream.h0000444000175000001440000000060414413277340021464 0ustar nabijaczleweliusers// OffsetStream.h #ifndef ZIP7_INC_OFFSET_STREAM_H #define ZIP7_INC_OFFSET_STREAM_H #include "../../Common/MyCom.h" #include "../IStream.h" Z7_CLASS_IMP_NOQIB_1( COffsetOutStream , IOutStream ) Z7_IFACE_COM7_IMP(ISequentialOutStream) CMyComPtr _stream; UInt64 _offset; public: HRESULT Init(IOutStream *stream, UInt64 offset); }; #endif tmp41wklro_/CPP/7zip/Common/OutBuffer.cpp0000444000175000001440000000420514413277340021317 0ustar nabijaczleweliusers// OutBuffer.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "OutBuffer.h" bool COutBuffer::Create(UInt32 bufSize) throw() { const UInt32 kMinBlockSize = 1; if (bufSize < kMinBlockSize) bufSize = kMinBlockSize; if (_buf && _bufSize == bufSize) return true; Free(); _bufSize = bufSize; _buf = (Byte *)::MidAlloc(bufSize); return (_buf != NULL); } void COutBuffer::Free() throw() { ::MidFree(_buf); _buf = NULL; } void COutBuffer::Init() throw() { _streamPos = 0; _limitPos = _bufSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef Z7_NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const throw() { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufSize; return res; } HRESULT COutBuffer::FlushPart() throw() { // _streamPos < _bufSize UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef Z7_NO_EXCEPTIONS result = ErrorCode; #endif if (_buf2) { memcpy(_buf2, _buf + _streamPos, size); _buf2 += size; } if (_stream #ifdef Z7_NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buf + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufSize) _streamPos = 0; if (_pos == _bufSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() throw() { #ifdef Z7_NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while (_streamPos != _pos) { const HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { const HRESULT result = Flush(); #ifdef Z7_NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } tmp41wklro_/CPP/7zip/Common/OutBuffer.h0000444000175000001440000000435114542025520020760 0ustar nabijaczleweliusers// OutBuffer.h #ifndef ZIP7_INC_OUT_BUFFER_H #define ZIP7_INC_OUT_BUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef Z7_NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buf; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufSize; ISequentialOutStream *_stream; UInt64 _processedSize; Byte *_buf2; bool _overDict; HRESULT FlushPart() throw(); public: #ifdef Z7_NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buf(NULL), _pos(0), _stream(NULL), _buf2(NULL) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufSize) throw(); void Free() throw(); void SetMemStream(Byte *buf) { _buf2 = buf; } void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() throw(); HRESULT Flush() throw(); void FlushWithCheck(); void WriteByte(Byte b) { UInt32 pos = _pos; _buf[pos] = b; pos++; _pos = pos; if (pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } Byte *GetOutBuffer(size_t &avail) { const UInt32 pos = _pos; avail = (size_t)(_limitPos - pos); return _buf + pos; } void SkipWrittenBytes(size_t num) { const UInt32 pos = _pos; const UInt32 rem = _limitPos - pos; if (rem > num) { _pos = pos + (UInt32)num; return; } // (rem <= num) // the caller must not call it with (rem < num) // so (rem == num) _pos = _limitPos; FlushWithCheck(); } /* void WriteBytesBig(const void *data, size_t size) { while (size) { UInt32 pos = _pos; UInt32 rem = _limitPos - pos; if (rem > size) { _pos = pos + size; memcpy(_buf + pos, data, size); return; } memcpy(_buf + pos, data, rem); _pos = pos + rem; FlushWithCheck(); } } */ UInt64 GetProcessedSize() const throw(); }; #endif tmp41wklro_/CPP/7zip/Common/ProgressUtils.cpp0000444000175000001440000000207714413277340022250 0ustar nabijaczleweliusers// ProgressUtils.cpp #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress(): SendRatio(true), SendProgress(true), ProgressOffset(0), InSize(0), OutSize(0) {} void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } Z7_COM7F_IMF(CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { UInt64 inSize2 = InSize; UInt64 outSize2 = OutSize; if (inSize) inSize2 += (*inSize); if (outSize) outSize2 += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2)) } if (SendProgress) { inSize2 += ProgressOffset; outSize2 += ProgressOffset; return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2); } return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } tmp41wklro_/CPP/7zip/Common/ProgressUtils.h0000444000175000001440000000113714413277340021711 0ustar nabijaczleweliusers// ProgressUtils.h #ifndef ZIP7_INC_PROGRESS_UTILS_H #define ZIP7_INC_PROGRESS_UTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" Z7_CLASS_IMP_COM_1( CLocalProgress , ICompressProgressInfo ) public: bool SendRatio; bool SendProgress; private: bool _inSizeIsMain; CMyComPtr _progress; CMyComPtr _ratioProgress; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); }; #endif tmp41wklro_/CPP/7zip/Common/PropId.cpp0000444000175000001440000000305714331466140020614 0ustar nabijaczleweliusers// PropId.cpp #include "StdAfx.h" #include "../../Common/MyWindows.h" #include "../PropID.h" // VARTYPE const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = { VT_EMPTY, VT_UI4, VT_UI4, VT_BSTR, VT_BSTR, VT_BSTR, VT_BOOL, VT_UI8, VT_UI8, VT_UI4, VT_FILETIME, VT_FILETIME, VT_FILETIME, VT_BOOL, VT_BOOL, VT_BOOL, VT_BOOL, VT_BOOL, VT_UI4, VT_UI4, VT_BSTR, VT_BOOL, VT_BSTR, VT_BSTR, VT_BSTR, VT_BSTR, VT_BSTR, VT_UI8, VT_BSTR, VT_UI8, VT_BSTR, VT_UI8, VT_UI8, VT_BSTR, // or VT_UI8 kpidUnpackVer VT_UI4, // or VT_UI8 kpidVolume VT_BOOL, VT_UI8, VT_UI8, VT_UI8, VT_UI8, VT_UI4, VT_BOOL, VT_BOOL, VT_BSTR, VT_UI8, VT_UI8, VT_UI4, // kpidChecksum VT_BSTR, VT_UI8, VT_BSTR, // or VT_UI8 kpidId VT_BSTR, VT_BSTR, VT_UI4, VT_UI4, VT_BSTR, VT_BSTR, VT_UI8, VT_UI8, VT_UI4, VT_BSTR, VT_BSTR, VT_BSTR, VT_BSTR, // kpidNtSecure VT_BOOL, VT_BOOL, VT_BOOL, VT_BOOL, VT_BSTR, // SHA-1 VT_BSTR, // SHA-256 VT_BSTR, VT_UI8, VT_UI4, VT_UI4, VT_BSTR, VT_UI8, VT_UI8, VT_UI8, VT_UI8, VT_UI8, VT_UI8, VT_UI8, VT_BSTR, VT_BSTR, VT_BSTR, VT_BOOL, VT_BOOL, VT_BOOL, VT_UI8, VT_UI8, VT_BSTR, // kpidNtReparse VT_BSTR, VT_UI8, VT_UI8, VT_BOOL, VT_BSTR, VT_BSTR, VT_BSTR, VT_BOOL, VT_FILETIME, // kpidChangeTime VT_UI4, VT_UI4, VT_UI4, VT_UI4, VT_UI4, VT_UI4 // kpidDevMinor }; tmp41wklro_/CPP/7zip/Common/RegisterArc.h0000444000175000001440000000523114401407000021256 0ustar nabijaczleweliusers// RegisterArc.h #ifndef ZIP7_INC_REGISTER_ARC_H #define ZIP7_INC_REGISTER_ARC_H #include "../Archive/IArchive.h" struct CArcInfo { UInt32 Flags; Byte Id; Byte SignatureSize; UInt16 SignatureOffset; const Byte *Signature; const char *Name; const char *Ext; const char *AddExt; UInt32 TimeFlags; Func_CreateInArchive CreateInArchive; Func_CreateOutArchive CreateOutArchive; Func_IsArc IsArc; bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; } }; void RegisterArc(const CArcInfo *arcInfo) throw(); #define IMP_CreateArcIn_2(c) \ static IInArchive *CreateArc() { return new c; } #define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler()) #ifdef Z7_EXTRACT_ONLY #define IMP_CreateArcOut #define CreateArcOut NULL #else #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } #endif #define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, tf, crIn, crOut, isArc } ; \ #define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ REGISTER_ARC_V (n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \ struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ static CRegisterArc g_RegisterArc; #define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \ IMP_CreateArcIn_2(cls) \ REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, 0, CreateArc, NULL, isArc) #define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ IMP_CreateArcIn_2(cls) \ REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, 0, CreateArc, NULL, isArc) #define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) #define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \ REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) #define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, tf, isArc) \ IMP_CreateArcIn \ IMP_CreateArcOut \ REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) #define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, tf, isArc) \ IMP_CreateArcIn \ IMP_CreateArcOut \ REGISTER_ARC_V(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) \ struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ static CRegisterArcDecSig g_RegisterArc; #endif tmp41wklro_/CPP/7zip/Common/RegisterCodec.h0000444000175000001440000000646714401407000021602 0ustar nabijaczleweliusers// RegisterCodec.h #ifndef ZIP7_INC_REGISTER_CODEC_H #define ZIP7_INC_REGISTER_CODEC_H #include "../Common/MethodId.h" #include "../ICoder.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const char *Name; UInt32 NumStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); } #define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC_VAR(x) static const CCodecInfo g_CodecInfo_ ## x = #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo_ ## x); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec_ ## x; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] = #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_CodecsInfo); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ REGISTER_CODEC_VAR(x) \ { crDec, crEnc, id, name, 1, false }; \ REGISTER_CODEC(x) #ifdef Z7_EXTRACT_ONLY #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ REGISTER_CODEC_CREATE(CreateDec, clsDec) \ REGISTER_CODEC_2(x, CreateDec, NULL, id, name) #else #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ REGISTER_CODEC_CREATE(CreateDec, clsDec) \ REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \ REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name) #endif #define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter) #define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \ { crDec, crEnc, id, name, 1, true } #define REGISTER_FILTER(x, crDec, crEnc, id, name) \ REGISTER_CODEC_VAR(x) \ REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ REGISTER_CODEC(x) #ifdef Z7_EXTRACT_ONLY #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name) #else #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ REGISTER_FILTER_CREATE(x ## _CreateEnc, clsEnc) \ REGISTER_FILTER(x, x ## _CreateDec, x ## _CreateEnc, id, name) #endif struct CHasherInfo { IHasher * (*CreateHasher)(); CMethodId Id; const char *Name; UInt32 DigestSize; }; void RegisterHasher(const CHasherInfo *hasher) throw(); #define REGISTER_HASHER_NAME(x) CRegHasher_ ## x #define REGISTER_HASHER(cls, id, name, size) \ Z7_COM7F_IMF2(UInt32, cls::GetDigestSize()) { return size; } \ static IHasher *CreateHasherSpec() { return new cls(); } \ static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \ struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \ static REGISTER_HASHER_NAME(cls) g_RegisterHasher; #endif tmp41wklro_/CPP/7zip/Common/StdAfx.h0000444000175000001440000000035614360505460020255 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Common/StreamBinder.cpp0000444000175000001440000000734014413277340022000 0ustar nabijaczleweliusers// StreamBinder.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamBinder.h" Z7_CLASS_IMP_COM_1( CBinderInStream , ISequentialInStream ) CStreamBinder *_binder; public: ~CBinderInStream() { _binder->CloseRead_CallOnce(); } CBinderInStream(CStreamBinder *binder): _binder(binder) {} }; Z7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { return _binder->Read(data, size, processedSize); } Z7_CLASS_IMP_COM_1( CBinderOutStream , ISequentialOutStream ) CStreamBinder *_binder; public: ~CBinderOutStream() { _binder->CloseWrite(); } CBinderOutStream(CStreamBinder *binder): _binder(binder) {} }; Z7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { return _binder->Write(data, size, processedSize); } static HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event) { const WRes wres = event.CreateIfNotCreated_Reset(); return HRESULT_FROM_WIN32(wres); } HRESULT CStreamBinder::Create_ReInit() { RINOK(Event_Create_or_Reset(_canRead_Event)) // RINOK(Event_Create_or_Reset(_canWrite_Event)) // _canWrite_Semaphore.Close(); // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce() _canWrite_Semaphore.OptCreateInit(0, 3); // _readingWasClosed = false; _readingWasClosed2 = false; _waitWrite = true; _bufSize = 0; _buf = NULL; ProcessedSize = 0; // WritingWasCut = false; return S_OK; } void CStreamBinder::CreateStreams2(CMyComPtr &inStream, CMyComPtr &outStream) { inStream = new CBinderInStream(this); outStream = new CBinderOutStream(this); } // (_canRead_Event && _bufSize == 0) means that stream is finished. HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; if (size != 0) { if (_waitWrite) { WRes wres = _canRead_Event.Lock(); if (wres != 0) return HRESULT_FROM_WIN32(wres); _waitWrite = false; } if (size > _bufSize) size = _bufSize; if (size != 0) { memcpy(data, _buf, size); _buf = ((const Byte *)_buf) + size; ProcessedSize += size; if (processedSize) *processedSize = size; _bufSize -= size; /* if (_bufSize == 0), then we have read whole buffer we have two ways here: - if we check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading */ if (_bufSize == 0) { _waitWrite = true; // _canWrite_Event.Set(); _canWrite_Semaphore.Release(); } } } return S_OK; } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (!_readingWasClosed2) { _buf = data; _bufSize = size; _canRead_Event.Set(); /* _canWrite_Event.Lock(); if (_readingWasClosed) _readingWasClosed2 = true; */ _canWrite_Semaphore.Lock(); // _bufSize : is remain size that was not read size -= _bufSize; // size : is size of data that was read if (size != 0) { // if some data was read, then we report that size and return if (processedSize) *processedSize = size; return S_OK; } _readingWasClosed2 = true; } // WritingWasCut = true; return k_My_HRESULT_WritingWasCut; } tmp41wklro_/CPP/7zip/Common/StreamBinder.h0000444000175000001440000000461114357314620021443 0ustar nabijaczleweliusers// StreamBinder.h #ifndef ZIP7_INC_STREAM_BINDER_H #define ZIP7_INC_STREAM_BINDER_H #include "../../Windows/Synchronization.h" #include "../IStream.h" /* We can use one from two code versions here: with Event or with Semaphore to unlock Writer thread The difference for cases where Reading must be closed before Writing closing 1) Event Version: _canWrite_Event We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function. The writer thread can get (_readingWasClosed) status in one from two iterations. It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers. reader thread: _canWrite_Event.Set(); _readingWasClosed = true; _canWrite_Event.Set(); writer thread: _canWrite_Event.Wait() if (_readingWasClosed) 2) Semaphore Version: _canWrite_Semaphore writer thread always will detect closing of reading in latest iteration after all data processing iterations */ class CStreamBinder { NWindows::NSynchronization::CAutoResetEvent _canRead_Event; // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; NWindows::NSynchronization::CSemaphore _canWrite_Semaphore; // bool _readingWasClosed; // set it in reader thread and check it in write thread bool _readingWasClosed2; // use it in writer thread // bool WritingWasCut; bool _waitWrite; // use it in reader thread UInt32 _bufSize; const void *_buf; public: UInt64 ProcessedSize; // the size that was read by reader thread void CreateStreams2(CMyComPtr &inStream, CMyComPtr &outStream); HRESULT Create_ReInit(); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseRead_CallOnce() { // call it only once: for example, in destructor /* _readingWasClosed = true; _canWrite_Event.Set(); */ /* We must relase Semaphore only once !!! we must release at least 2 items of Semaphore: one item to unlock partial Write(), if Read() have read some items then additional item to stop writing (_bufSize will be 0) */ _canWrite_Semaphore.Release(2); } void CloseWrite() { _buf = NULL; _bufSize = 0; _canRead_Event.Set(); } }; #endif tmp41wklro_/CPP/7zip/Common/StreamObjects.cpp0000444000175000001440000001636214413277340022172 0ustar nabijaczleweliusers// StreamObjects.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "StreamObjects.h" Z7_COM7F_IMF(CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (_pos >= Buf.Size()) return S_OK; size_t rem = Buf.Size() - (size_t)_pos; if (rem > size) rem = (size_t)size; memcpy(data, (const Byte *)Buf + (size_t)_pos, rem); _pos += rem; if (processedSize) *processedSize = (UInt32)rem; return S_OK; } Z7_COM7F_IMF(CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _pos; break; case STREAM_SEEK_END: offset += Buf.Size(); break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _pos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } Z7_COM7F_IMF(CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (_pos >= _size) return S_OK; size_t rem = _size - (size_t)_pos; if (rem > size) rem = (size_t)size; memcpy(data, _data + (size_t)_pos, rem); _pos += rem; if (processedSize) *processedSize = (UInt32)rem; return S_OK; } Z7_COM7F_IMF(CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _pos; break; case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _pos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream) { *stream = NULL; CBufInStream *inStreamSpec = new CBufInStream; CMyComPtr streamTemp = inStreamSpec; inStreamSpec->Init((const Byte *)data, size, ref); *stream = streamTemp.Detach(); } void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream) { *stream = NULL; CBufferInStream *inStreamSpec = new CBufferInStream; CMyComPtr streamTemp = inStreamSpec; inStreamSpec->Buf.CopyFrom((const Byte *)data, size); inStreamSpec->Init(); *stream = streamTemp.Detach(); } void CByteDynBuffer::Free() throw() { MyFree(_buf); _buf = NULL; _capacity = 0; } bool CByteDynBuffer::EnsureCapacity(size_t cap) throw() { if (cap <= _capacity) return true; const size_t cap2 = _capacity + _capacity / 4; if (cap < cap2) cap = cap2; Byte *buf = (Byte *)MyRealloc(_buf, cap); if (!buf) return false; _buf = buf; _capacity = cap; return true; } Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) { addSize += _size; if (addSize < _size) return NULL; if (!_buffer.EnsureCapacity(addSize)) return NULL; return (Byte *)_buffer + _size; } void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const { dest.CopyFrom((const Byte *)_buffer, _size); } Z7_COM7F_IMF(CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; Byte *buf = GetBufPtrForWriting(size); if (!buf) return E_OUTOFMEMORY; memcpy(buf, data, size); UpdateSize(size); if (processedSize) *processedSize = size; return S_OK; } Z7_COM7F_IMF(CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { size_t rem = _size - _pos; if (rem > size) rem = (size_t)size; if (rem != 0) { memcpy(_buffer + _pos, data, rem); _pos += rem; } if (processedSize) *processedSize = (UInt32)rem; return (rem != 0 || size == 0) ? S_OK : E_FAIL; } Z7_COM7F_IMF(CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return result; } static const UInt64 kEmptyTag = (UInt64)(Int64)-1; void CCachedInStream::Free() throw() { MyFree(_tags); _tags = NULL; MidFree(_data); _data = NULL; } bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw() { unsigned sizeLog = blockSizeLog + numBlocksLog; if (sizeLog >= sizeof(size_t) * 8) return false; size_t dataSize = (size_t)1 << sizeLog; if (!_data || dataSize != _dataSize) { MidFree(_data); _data = (Byte *)MidAlloc(dataSize); if (!_data) return false; _dataSize = dataSize; } if (!_tags || numBlocksLog != _numBlocksLog) { MyFree(_tags); _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); if (!_tags) return false; _numBlocksLog = numBlocksLog; } _blockSizeLog = blockSizeLog; return true; } void CCachedInStream::Init(UInt64 size) throw() { _size = size; _pos = 0; const size_t numBlocks = (size_t)1 << _numBlocksLog; for (size_t i = 0; i < numBlocks; i++) _tags[i] = kEmptyTag; } Z7_COM7F_IMF(CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (_pos >= _size) return S_OK; { const UInt64 rem = _size - _pos; if (size > rem) size = (UInt32)rem; } while (size != 0) { const UInt64 cacheTag = _pos >> _blockSizeLog; const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); Byte *p = _data + (cacheIndex << _blockSizeLog); if (_tags[cacheIndex] != cacheTag) { _tags[cacheIndex] = kEmptyTag; const UInt64 remInBlock = _size - (cacheTag << _blockSizeLog); size_t blockSize = (size_t)1 << _blockSizeLog; if (blockSize > remInBlock) blockSize = (size_t)remInBlock; RINOK(ReadBlock(cacheTag, p, blockSize)) _tags[cacheIndex] = cacheTag; } const size_t kBlockSize = (size_t)1 << _blockSizeLog; const size_t offset = (size_t)_pos & (kBlockSize - 1); UInt32 cur = size; const size_t rem = kBlockSize - offset; if (cur > rem) cur = (UInt32)rem; memcpy(data, p + offset, cur); if (processedSize) *processedSize += cur; data = (void *)((const Byte *)data + cur); _pos += cur; size -= cur; } return S_OK; } Z7_COM7F_IMF(CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { switch (seekOrigin) { case STREAM_SEEK_SET: break; case STREAM_SEEK_CUR: offset += _pos; break; case STREAM_SEEK_END: offset += _size; break; default: return STG_E_INVALIDFUNCTION; } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; _pos = (UInt64)offset; if (newPosition) *newPosition = (UInt64)offset; return S_OK; } tmp41wklro_/CPP/7zip/Common/StreamObjects.h0000444000175000001440000000666214413277340021641 0ustar nabijaczleweliusers// StreamObjects.h #ifndef ZIP7_INC_STREAM_OBJECTS_H #define ZIP7_INC_STREAM_OBJECTS_H #include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../IStream.h" Z7_CLASS_IMP_IInStream( CBufferInStream ) UInt64 _pos; public: CByteBuffer Buf; void Init() { _pos = 0; } }; Z7_CLASS_IMP_COM_0( CReferenceBuf ) public: CByteBuffer Buf; }; Z7_CLASS_IMP_IInStream( CBufInStream ) const Byte *_data; UInt64 _pos; size_t _size; CMyComPtr _ref; public: void Init(const Byte *data, size_t size, IUnknown *ref = NULL) { _data = data; _size = size; _pos = 0; _ref = ref; } void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); } // Seek() is allowed here. So reading order could be changed bool WasFinished() const { return _pos == _size; } }; void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } class CByteDynBuffer Z7_final { size_t _capacity; Byte *_buf; Z7_CLASS_NO_COPY(CByteDynBuffer) public: CByteDynBuffer(): _capacity(0), _buf(NULL) {} // there is no copy constructor. So don't copy this object. ~CByteDynBuffer() { Free(); } void Free() throw(); size_t GetCapacity() const { return _capacity; } operator Byte*() const { return _buf; } operator const Byte*() const { return _buf; } bool EnsureCapacity(size_t capacity) throw(); }; Z7_CLASS_IMP_COM_1( CDynBufSeqOutStream , ISequentialOutStream ) CByteDynBuffer _buffer; size_t _size; public: CDynBufSeqOutStream(): _size(0) {} void Init() { _size = 0; } size_t GetSize() const { return _size; } const Byte *GetBuffer() const { return _buffer; } void CopyToBuffer(CByteBuffer &dest) const; Byte *GetBufPtrForWriting(size_t addSize); void UpdateSize(size_t addSize) { _size += addSize; } }; Z7_CLASS_IMP_COM_1( CBufPtrSeqOutStream , ISequentialOutStream ) Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } }; Z7_CLASS_IMP_COM_1( CSequentialOutStreamSizeCount , ISequentialOutStream ) CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } }; class CCachedInStream: public IInStream, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) UInt64 *_tags; Byte *_data; size_t _dataSize; unsigned _blockSizeLog; unsigned _numBlocksLog; UInt64 _size; UInt64 _pos; protected: virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0; public: CCachedInStream(): _tags(NULL), _data(NULL) {} virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (Release() calls it) !!! void Free() throw(); bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); void Init(UInt64 size) throw(); }; #endif tmp41wklro_/CPP/7zip/Common/StreamUtils.cpp0000444000175000001440000000532314410104040021653 0ustar nabijaczleweliusers// StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT InStream_SeekToBegin(IInStream *stream) throw() { return InStream_SeekSet(stream, 0); } HRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &sizeRes) throw() { #ifdef _WIN32 { Z7_DECL_CMyComPtr_QI_FROM( IStreamGetSize, streamGetSize, stream) if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK) return S_OK; } #endif const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes); const HRESULT hres2 = InStream_SeekToBegin(stream); return hres != S_OK ? hres : hres2; } HRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw() { RINOK(InStream_GetPos(stream, curPosRes)) #ifdef _WIN32 { Z7_DECL_CMyComPtr_QI_FROM( IStreamGetSize, streamGetSize, stream) if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK) return S_OK; } #endif const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes); const HRESULT hres2 = InStream_SeekSet(stream, curPosRes); return hres != S_OK ? hres : hres2; } HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw() { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res) if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw() { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)) return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw() { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)) return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw() { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res) if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } tmp41wklro_/CPP/7zip/Common/StreamUtils.h0000444000175000001440000000246114362203220021326 0ustar nabijaczleweliusers// StreamUtils.h #ifndef ZIP7_INC_STREAM_UTILS_H #define ZIP7_INC_STREAM_UTILS_H #include "../IStream.h" inline HRESULT InStream_SeekSet(IInStream *stream, UInt64 offset) throw() { return stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); } inline HRESULT InStream_GetPos(IInStream *stream, UInt64 &curPosRes) throw() { return stream->Seek(0, STREAM_SEEK_CUR, &curPosRes); } inline HRESULT InStream_GetSize_SeekToEnd(IInStream *stream, UInt64 &sizeRes) throw() { return stream->Seek(0, STREAM_SEEK_END, &sizeRes); } HRESULT InStream_SeekToBegin(IInStream *stream) throw(); HRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &size) throw(); HRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw(); inline HRESULT InStream_GetSize_SeekToBegin(IInStream *stream, UInt64 &sizeRes) throw() { RINOK(InStream_SeekToBegin(stream)) return InStream_AtBegin_GetSize(stream, sizeRes); } HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw(); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw(); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw(); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw(); #endif tmp41wklro_/CPP/7zip/Common/UniqBlocks.cpp0000444000175000001440000000244014166341420021463 0ustar nabijaczleweliusers// UniqBlocks.cpp #include "StdAfx.h" #include #include "UniqBlocks.h" unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) { unsigned left = 0, right = Sorted.Size(); while (left != right) { const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned index = Sorted[mid]; const CByteBuffer &buf = Bufs[index]; const size_t sizeMid = buf.Size(); if (size < sizeMid) right = mid; else if (size > sizeMid) left = mid + 1; else { if (size == 0) return index; const int cmp = memcmp(data, buf, size); if (cmp == 0) return index; if (cmp < 0) right = mid; else left = mid + 1; } } unsigned index = Bufs.Size(); Sorted.Insert(left, index); Bufs.AddNew().CopyFrom(data, size); return index; } UInt64 CUniqBlocks::GetTotalSizeInBytes() const { UInt64 size = 0; FOR_VECTOR (i, Bufs) size += Bufs[i].Size(); return size; } void CUniqBlocks::GetReverseMap() { unsigned num = Sorted.Size(); BufIndexToSortedIndex.ClearAndSetSize(num); unsigned *p = &BufIndexToSortedIndex[0]; const unsigned *sorted = &Sorted[0]; for (unsigned i = 0; i < num; i++) p[sorted[i]] = i; } tmp41wklro_/CPP/7zip/Common/UniqBlocks.h0000444000175000001440000000142314357314620021134 0ustar nabijaczleweliusers// UniqBlocks.h #ifndef ZIP7_INC_UNIQ_BLOCKS_H #define ZIP7_INC_UNIQ_BLOCKS_H #include "../../Common/MyBuffer.h" #include "../../Common/MyString.h" struct C_UInt32_UString_Map { CRecordVector Numbers; UStringVector Strings; void Add_UInt32(const UInt32 n) { Numbers.AddToUniqueSorted(n); } int Find(const UInt32 n) { return Numbers.FindInSorted(n); } }; struct CUniqBlocks { CObjectVector Bufs; CUIntVector Sorted; CUIntVector BufIndexToSortedIndex; unsigned AddUniq(const Byte *data, size_t size); UInt64 GetTotalSizeInBytes() const; void GetReverseMap(); bool IsOnlyEmpty() const { return (Bufs.Size() == 0 || (Bufs.Size() == 1 && Bufs[0].Size() == 0)); } }; #endif tmp41wklro_/CPP/7zip/Common/VirtThread.cpp0000444000175000001440000000155714406252760021502 0ustar nabijaczleweliusers// VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->Exit) return THREAD_FUNC_RET_ZERO; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK_WRes(StartEvent.CreateIfNotCreated_Reset()) RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset()) // StartEvent.Reset(); // FinishedEvent.Reset(); Exit = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } WRes CVirtThread::Start() { Exit = false; return StartEvent.Set(); } void CVirtThread::WaitThreadFinish() { Exit = true; if (StartEvent.IsCreated()) StartEvent.Set(); if (Thread.IsCreated()) { Thread.Wait_Close(); } } tmp41wklro_/CPP/7zip/Common/VirtThread.h0000444000175000001440000000115014357314620021133 0ustar nabijaczleweliusers// VirtThread.h #ifndef ZIP7_INC_VIRT_THREAD_H #define ZIP7_INC_VIRT_THREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool Exit; virtual ~CVirtThread() { WaitThreadFinish(); } void WaitThreadFinish(); // call it in destructor of child class ! WRes Create(); WRes Start(); virtual void Execute() = 0; WRes WaitExecuteFinish() { return FinishedEvent.Lock(); } }; #endif tmp41wklro_/CPP/7zip/Compress/0000700000175000001440000000000014706260545017250 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Compress/Bcj2Coder.cpp0000444000175000001440000006362614541015260021523 0ustar nabijaczleweliusers// Bcj2Coder.cpp #include "StdAfx.h" // #include #include "../../../C/Alloc.h" #include "../Common/StreamUtils.h" #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { CBaseCoder::CBaseCoder() { for (unsigned i = 0; i < BCJ2_NUM_STREAMS + 1; i++) { _bufs[i] = NULL; _bufsSizes[i] = 0; _bufsSizes_New[i] = (1 << 18); } } CBaseCoder::~CBaseCoder() { for (unsigned i = 0; i < BCJ2_NUM_STREAMS + 1; i++) ::MidFree(_bufs[i]); } HRESULT CBaseCoder::Alloc(bool allocForOrig) { const unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS; for (unsigned i = 0; i < num; i++) { UInt32 size = _bufsSizes_New[i]; /* buffer sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP streams must be aligned for 4 */ size &= ~(UInt32)3; const UInt32 kMinBufSize = 4; if (size < kMinBufSize) size = kMinBufSize; // size = 4 * 100; // for debug // if (BCJ2_IS_32BIT_STREAM(i) == 1) size = 4 * 1; // for debug if (!_bufs[i] || size != _bufsSizes[i]) { if (_bufs[i]) { ::MidFree(_bufs[i]); _bufs[i] = NULL; } _bufsSizes[i] = 0; Byte *buf = (Byte *)::MidAlloc(size); if (!buf) return E_OUTOFMEMORY; _bufs[i] = buf; _bufsSizes[i] = size; } } return S_OK; } #ifndef Z7_EXTRACT_ONLY CEncoder::CEncoder(): _relatLim(BCJ2_ENC_RELAT_LIMIT_DEFAULT) // , _excludeRangeBits(BCJ2_RELAT_EXCLUDE_NUM_BITS) {} CEncoder::~CEncoder() {} Z7_COM7F_IMF(CEncoder::SetInBufSize(UInt32, UInt32 size)) { _bufsSizes_New[BCJ2_NUM_STREAMS] = size; return S_OK; } Z7_COM7F_IMF(CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size)) { _bufsSizes_New[streamIndex] = size; return S_OK; } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) { UInt32 relatLim = BCJ2_ENC_RELAT_LIMIT_DEFAULT; // UInt32 excludeRangeBits = BCJ2_RELAT_EXCLUDE_NUM_BITS; for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = props[i]; const PROPID propID = propIDs[i]; if (propID >= NCoderPropID::kReduceSize // && propID != NCoderPropID::kHashBits ) continue; switch (propID) { /* case NCoderPropID::kDefaultProp: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = prop.ulVal; if (v > 31) return E_INVALIDARG; relatLim = (UInt32)1 << v; break; } case NCoderPropID::kHashBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = prop.ulVal; if (v > 31) return E_INVALIDARG; excludeRangeBits = v; break; } */ case NCoderPropID::kDictionarySize: { if (prop.vt != VT_UI4) return E_INVALIDARG; relatLim = prop.ulVal; if (relatLim > BCJ2_ENC_RELAT_LIMIT_MAX) return E_INVALIDARG; break; } case NCoderPropID::kNumThreads: case NCoderPropID::kLevel: continue; default: return E_INVALIDARG; } } _relatLim = relatLim; // _excludeRangeBits = excludeRangeBits; return S_OK; } HRESULT CEncoder::CodeReal( ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS) return E_INVALIDARG; RINOK(Alloc()) CBcj2Enc_ip_unsigned fileSize_minus1 = BCJ2_ENC_FileSizeField_UNLIMITED; if (inSizes && inSizes[0]) { const UInt64 inSize = *inSizes[0]; #ifdef BCJ2_ENC_FileSize_MAX if (inSize <= BCJ2_ENC_FileSize_MAX) #endif fileSize_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(inSize); } Z7_DECL_CMyComPtr_QI_FROM(ICompressGetSubStreamSize, getSubStreamSize, inStreams[0]) CBcj2Enc enc; enc.src = _bufs[BCJ2_NUM_STREAMS]; enc.srcLim = enc.src; { for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++) { enc.bufs[i] = _bufs[i]; enc.lims[i] = _bufs[i] + _bufsSizes[i]; } } Bcj2Enc_Init(&enc); enc.fileIp64 = 0; enc.fileSize64_minus1 = fileSize_minus1; enc.relatLimit = _relatLim; // enc.relatExcludeBits = _excludeRangeBits; enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; // Varibales that correspond processed data in input stream: UInt64 inPos_without_Temp = 0; // it doesn't include data in enc.temp[] UInt64 inPos_with_Temp = 0; // it includes data in enc.temp[] UInt64 prevProgress = 0; UInt64 totalRead = 0; // size read from input stream UInt64 outSizeRc = 0; UInt64 subStream_Index = 0; UInt64 subStream_StartPos = 0; // global start offset of subStreams[subStream_Index] UInt64 subStream_Size = 0; const Byte *srcLim_Read = _bufs[BCJ2_NUM_STREAMS]; bool readWasFinished = false; bool isAccurate = false; bool wasUnknownSize = false; for (;;) { if (readWasFinished && enc.srcLim == srcLim_Read) enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM; // for debug: // for (int y=0;y<100;y++) { CBcj2Enc enc2 = enc; Bcj2Enc_Encode(&enc2); } Bcj2Enc_Encode(&enc); inPos_with_Temp = totalRead - (size_t)(srcLim_Read - enc.src); inPos_without_Temp = inPos_with_Temp - Bcj2Enc_Get_AvailInputSize_in_Temp(&enc); // if (inPos_without_Temp != enc.ip64) return E_FAIL; if (Bcj2Enc_IsFinished(&enc)) break; if (enc.state < BCJ2_NUM_STREAMS) { if (enc.bufs[enc.state] != enc.lims[enc.state]) return E_FAIL; const size_t curSize = (size_t)(enc.bufs[enc.state] - _bufs[enc.state]); // printf("Write stream = %2d %6d\n", enc.state, curSize); RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize)) if (enc.state == BCJ2_STREAM_RC) outSizeRc += curSize; enc.bufs[enc.state] = _bufs[enc.state]; enc.lims[enc.state] = _bufs[enc.state] + _bufsSizes[enc.state]; } else { if (enc.state != BCJ2_ENC_STATE_ORIG) return E_FAIL; // (enc.state == BCJ2_ENC_STATE_ORIG) if (enc.src != enc.srcLim) return E_FAIL; if (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE && Bcj2Enc_Get_AvailInputSize_in_Temp(&enc) != 0) return E_FAIL; if (enc.src == srcLim_Read) { if (readWasFinished) return E_FAIL; UInt32 curSize = _bufsSizes[BCJ2_NUM_STREAMS]; RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize)) // printf("Read %6u bytes\n", curSize); if (curSize == 0) readWasFinished = true; totalRead += curSize; enc.src = _bufs[BCJ2_NUM_STREAMS]; srcLim_Read = _bufs[BCJ2_NUM_STREAMS] + curSize; } enc.srcLim = srcLim_Read; if (getSubStreamSize) { /* we set base default conversions options that will be used, if subStream related options will be not OK */ enc.fileIp64 = 0; enc.fileSize64_minus1 = fileSize_minus1; for (;;) { UInt64 nextPos; if (isAccurate) nextPos = subStream_StartPos + subStream_Size; else { const HRESULT hres = getSubStreamSize->GetSubStreamSize(subStream_Index, &subStream_Size); if (hres != S_OK) { enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; /* if sub-stream size is unknown, we use default settings. We still can recover to normal mode for next sub-stream, if GetSubStreamSize() will return S_OK, when current sub-stream will be finished. */ if (hres == S_FALSE) { wasUnknownSize = true; break; } if (hres == E_NOTIMPL) { getSubStreamSize.Release(); break; } return hres; } // printf("GetSubStreamSize %6u : %6u \n", (unsigned)subStream_Index, (unsigned)subStream_Size); nextPos = subStream_StartPos + subStream_Size; if ((Int64)subStream_Size == -1) { /* it's not expected, but (-1) can mean unknown size. */ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; wasUnknownSize = true; break; } if (nextPos < subStream_StartPos) return E_FAIL; isAccurate = (nextPos < totalRead || (nextPos <= totalRead && readWasFinished)); } /* (nextPos) is estimated end position of current sub_stream. But only (totalRead) and (readWasFinished) values can confirm that this estimated end position is accurate. That end position is accurate, if it can't be changed in further calls of GetSubStreamSize() */ /* (nextPos < inPos_with_Temp) is unexpected case here, that we can get if from some incorrect ICompressGetSubStreamSize object, where new GetSubStreamSize() call returns smaller size than confirmed by Read() size from previous GetSubStreamSize() call. */ if (nextPos < inPos_with_Temp) { if (wasUnknownSize) { /* that case can be complicated for recovering. so we disable sub-streams requesting. */ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; getSubStreamSize.Release(); break; } return E_FAIL; // to stop after failure } if (nextPos <= inPos_with_Temp) { // (nextPos == inPos_with_Temp) /* CBcj2Enc encoder requires to finish each [non-empty] block (sub-stream) with BCJ2_ENC_FINISH_MODE_END_BLOCK or with BCJ2_ENC_FINISH_MODE_END_STREAM for last block: And we send data of new block to CBcj2Enc, only if previous block was finished. So we switch to next sub-stream if after Bcj2Enc_Encode() call we have && (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE) && (nextPos == inPos_with_Temp) && (enc.state == BCJ2_ENC_STATE_ORIG) */ if (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE) { /* subStream_StartPos is increased only here. (subStream_StartPos == inPos_with_Temp) : at start (subStream_StartPos <= inPos_with_Temp) : will be later */ subStream_StartPos = nextPos; subStream_Size = 0; wasUnknownSize = false; subStream_Index++; isAccurate = false; // we don't change finishMode here continue; } } enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; /* for (!isAccurate) case: (totalRead <= real_end_of_subStream) so we can use BCJ2_ENC_FINISH_MODE_CONTINUE up to (totalRead) // we don't change settings at the end of substream, if settings were unknown, */ /* if (wasUnknownSize) then we can't trust size of that sub-stream. so we use default settings instead */ if (!wasUnknownSize) #ifdef BCJ2_ENC_FileSize_MAX if (subStream_Size <= BCJ2_ENC_FileSize_MAX) #endif { enc.fileIp64 = (CBcj2Enc_ip_unsigned)( (CBcj2Enc_ip_signed)enc.ip64 + (CBcj2Enc_ip_signed)(subStream_StartPos - inPos_without_Temp)); Bcj2Enc_SET_FileSize(&enc, subStream_Size) } if (isAccurate) { /* (real_end_of_subStream == nextPos <= totalRead) So we can use BCJ2_ENC_FINISH_MODE_END_BLOCK up to (nextPos). */ const size_t rem = (size_t)(totalRead - nextPos); if ((size_t)(enc.srcLim - enc.src) < rem) return E_FAIL; enc.srcLim -= rem; enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK; } break; } // for() loop } // getSubStreamSize } if (progress && inPos_without_Temp - prevProgress >= (1 << 22)) { prevProgress = inPos_without_Temp; const UInt64 outSize2 = inPos_without_Temp + outSizeRc + (size_t)(enc.bufs[BCJ2_STREAM_RC] - _bufs[BCJ2_STREAM_RC]); // printf("progress %8u, %8u\n", (unsigned)inSize2, (unsigned)outSize2); RINOK(progress->SetRatioInfo(&inPos_without_Temp, &outSize2)) } } for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++) { RINOK(WriteStream(outStreams[i], _bufs[i], (size_t)(enc.bufs[i] - _bufs[i]))) } // if (inPos_without_Temp != subStream_StartPos + subStream_Size) return E_FAIL; return S_OK; } Z7_COM7F_IMF(CEncoder::Code( ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress)) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(...) { return E_FAIL; } } #endif CDecoder::CDecoder(): _finishMode(false) #ifndef Z7_NO_READ_FROM_CODER , _outSizeDefined(false) , _outSize(0) , _outSize_Processed(0) #endif {} Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size)) { _bufsSizes_New[streamIndex] = size; return S_OK; } Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32, UInt32 size)) { _bufsSizes_New[BCJ2_NUM_STREAMS] = size; return S_OK; } Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) { _finishMode = (finishMode != 0); return S_OK; } void CBaseDecoder::InitCommon() { for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++) { dec.lims[i] = dec.bufs[i] = _bufs[i]; _readRes[i] = S_OK; _extraSizes[i] = 0; _readSizes[i] = 0; } Bcj2Dec_Init(&dec); } /* call ReadInStream() only after Bcj2Dec_Decode(). input requirement: (dec.state < BCJ2_NUM_STREAMS) */ void CBaseDecoder::ReadInStream(ISequentialInStream *inStream) { const unsigned state = dec.state; UInt32 total; { Byte *buf = _bufs[state]; const Byte *cur = dec.bufs[state]; // if (cur != dec.lims[state]) throw 1; // unexpected case dec.lims[state] = dec.bufs[state] = buf; total = (UInt32)_extraSizes[state]; for (UInt32 i = 0; i < total; i++) buf[i] = cur[i]; } if (_readRes[state] != S_OK) return; do { UInt32 curSize = _bufsSizes[state] - total; // if (state == 0) curSize = 0; // for debug // curSize = 7; // for debug /* even if we have reached provided inSizes[state] limit, we call Read() with (curSize != 0), because we want the called handler of stream->Read() could execute required Init/Flushing code even for empty stream. In another way we could call Read() with (curSize == 0) for finished streams, but some Read() handlers can ignore Read(size=0) calls. */ const HRESULT hres = inStream->Read(_bufs[state] + total, curSize, &curSize); _readRes[state] = hres; if (curSize == 0) break; _readSizes[state] += curSize; total += curSize; if (hres != S_OK) break; } while (total < 4 && BCJ2_IS_32BIT_STREAM(state)); /* we exit from decoding loop here, if we can't provide new data for input stream. Usually it's normal exit after full stream decoding. */ if (total == 0) return; if (BCJ2_IS_32BIT_STREAM(state)) { const unsigned extra = (unsigned)total & 3; _extraSizes[state] = extra; if (total < 4) { if (_readRes[state] == S_OK) _readRes[state] = S_FALSE; // actually it's stream error. So maybe we need another error code. return; } total -= (UInt32)extra; } dec.lims[state] += total; // = _bufs[state] + total; } Z7_COM7F_IMF(CDecoder::Code( ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress)) { if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1) return E_INVALIDARG; RINOK(Alloc()) InitCommon(); dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS]; UInt64 outSizeWritten = 0; UInt64 prevProgress = 0; HRESULT hres_Crit = S_OK; // critical hres status (mostly from input stream reading) HRESULT hres_Weak = S_OK; // first non-critical error code from input stream reading for (;;) { if (Bcj2Dec_Decode(&dec) != SZ_OK) { /* it's possible only at start (first 5 bytes in RC stream) */ hres_Crit = S_FALSE; break; } if (dec.state < BCJ2_NUM_STREAMS) { ReadInStream(inStreams[dec.state]); const unsigned state = dec.state; const HRESULT hres = _readRes[state]; if (dec.lims[state] == _bufs[state]) { // we break decoding, if there are no new data in input stream hres_Crit = hres; break; } if (hres != S_OK && hres_Weak == S_OK) hres_Weak = hres; } else // (BCJ2_DEC_STATE_ORIG_0 <= state <= BCJ2_STATE_ORIG) { { const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (curSize != 0) { outSizeWritten += curSize; RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)) } } { UInt32 rem = _bufsSizes[BCJ2_NUM_STREAMS]; if (outSizes && outSizes[0]) { const UInt64 outSize = *outSizes[0] - outSizeWritten; if (rem > outSize) rem = (UInt32)outSize; } dec.dest = _bufs[BCJ2_NUM_STREAMS]; dec.destLim = dec.dest + rem; /* we exit from decoding loop here, if (outSizes[0]) limit for output stream was reached */ if (rem == 0) break; } } if (progress) { // here we don't count additional data in dec.temp (up to 4 bytes for output stream) const UInt64 processed = outSizeWritten + (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (processed - prevProgress >= (1 << 24)) { prevProgress = processed; const UInt64 inSize = processed + _readSizes[BCJ2_STREAM_RC] - (size_t)( dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); RINOK(progress->SetRatioInfo(&inSize, &prevProgress)) } } } { const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (curSize != 0) { outSizeWritten += curSize; RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)) } } if (hres_Crit == S_OK) hres_Crit = hres_Weak; if (hres_Crit != S_OK) return hres_Crit; if (_finishMode) { if (!Bcj2Dec_IsMaybeFinished_code(&dec)) return S_FALSE; /* here we support two correct ways to finish full stream decoding with one of the following conditions: - the end of input stream MAIN was reached - the end of output stream ORIG was reached Currently 7-Zip/7z code ends with (state == BCJ2_STREAM_MAIN), because the sizes of MAIN and ORIG streams are known and these sizes are stored in 7z archive headers. And Bcj2Dec_Decode() exits with (state == BCJ2_STREAM_MAIN), if both MAIN and ORIG streams have reached buffers limits. But if the size of MAIN stream is not known or if the size of MAIN stream includes some padding after payload data, then we still can correctly finish decoding with (state == BCJ2_DEC_STATE_ORIG), if we know the exact size of output ORIG stream. */ if (dec.state != BCJ2_STREAM_MAIN) if (dec.state != BCJ2_DEC_STATE_ORIG) return S_FALSE; /* the caller also will know written size. So the following check is optional: */ if (outSizes && outSizes[0] && *outSizes[0] != outSizeWritten) return S_FALSE; if (inSizes) { for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++) { /* if (inSizes[i]) is defined, we do full check for processed stream size. */ if (inSizes[i] && *inSizes[i] != GetProcessedSize_ForInStream(i)) return S_FALSE; } } /* v23.02: we call Read(0) for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP streams, if there were no Read() calls for such stream. So the handlers of these input streams objects can do Init/Flushing even for case when stream is empty: */ for (unsigned i = BCJ2_STREAM_CALL; i < BCJ2_STREAM_CALL + 2; i++) { if (_readSizes[i]) continue; Byte b; UInt32 processed; RINOK(inStreams[i]->Read(&b, 0, &processed)) } } return S_OK; } Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)) { *value = GetProcessedSize_ForInStream(streamIndex); return S_OK; } #ifndef Z7_NO_READ_FROM_CODER Z7_COM7F_IMF(CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)) { _inStreams[streamIndex] = inStream; return S_OK; } Z7_COM7F_IMF(CDecoder::ReleaseInStream2(UInt32 streamIndex)) { _inStreams[streamIndex].Release(); return S_OK; } Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) { _outSizeDefined = (outSize != NULL); _outSize = 0; if (_outSizeDefined) _outSize = *outSize; _outSize_Processed = 0; const HRESULT res = Alloc(false); // allocForOrig InitCommon(); dec.destLim = dec.dest = NULL; return res; } Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; /* Note the case: The output (ORIG) stream can be empty. But BCJ2_STREAM_RC stream always is not empty. And we want to support full data processing for all streams. We disable check (size == 0) here. So if the caller calls this CDecoder::Read() with (size == 0), we execute required Init/Flushing code in this CDecoder object. Also this CDecoder::Read() function will call Read() for input streams. So the handlers of input streams objects also can do Init/Flushing. */ // if (size == 0) return S_OK; // disabled to allow (size == 0) processing UInt32 totalProcessed = 0; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSize_Processed; if (size > rem) size = (UInt32)rem; } dec.dest = (Byte *)data; dec.destLim = (const Byte *)data + size; HRESULT res = S_OK; for (;;) { if (Bcj2Dec_Decode(&dec) != SZ_OK) return S_FALSE; // this error can be only at start of stream { const UInt32 curSize = (UInt32)(size_t)(dec.dest - (Byte *)data); if (curSize != 0) { data = (void *)((Byte *)data + curSize); size -= curSize; _outSize_Processed += curSize; totalProcessed += curSize; if (processedSize) *processedSize = totalProcessed; } } if (dec.state >= BCJ2_NUM_STREAMS) break; ReadInStream(_inStreams[dec.state]); if (dec.lims[dec.state] == _bufs[dec.state]) { /* we break decoding, if there are no new data in input stream. and we ignore error code, if some data were written to output buffer. */ if (totalProcessed == 0) res = _readRes[dec.state]; break; } } if (res == S_OK) if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed) { if (!Bcj2Dec_IsMaybeFinished_code(&dec)) return S_FALSE; if (dec.state != BCJ2_STREAM_MAIN) if (dec.state != BCJ2_DEC_STATE_ORIG) return S_FALSE; } return res; } #endif }} /* extern "C" { extern UInt32 bcj2_stats[256 + 2][2]; } static class CBcj2Stat { public: ~CBcj2Stat() { printf("\nBCJ2 stat:"); unsigned sums[2] = { 0, 0 }; int i; for (i = 2; i < 256 + 2; i++) { sums[0] += bcj2_stats[i][0]; sums[1] += bcj2_stats[i][1]; } const unsigned sums2 = sums[0] + sums[1]; for (int vi = 0; vi < 256 + 3; vi++) { printf("\n"); UInt32 n0, n1; if (vi < 4) printf("\n"); if (vi < 2) i = vi; else if (vi == 2) i = -1; else i = vi - 1; if (i < 0) { n0 = sums[0]; n1 = sums[1]; printf("calls :"); } else { if (i == 0) printf("jcc :"); else if (i == 1) printf("jump :"); else printf("call %02x :", i - 2); n0 = bcj2_stats[i][0]; n1 = bcj2_stats[i][1]; } const UInt32 sum = n0 + n1; printf(" %10u", sum); #define PRINT_PERC(val, sum) \ { UInt32 _sum = sum; if (_sum == 0) _sum = 1; \ printf(" %7.3f %%", (double)((double)val * (double)100 / (double)_sum )); } if (i >= 2 || i < 0) { PRINT_PERC(sum, sums2); } else printf("%10s", ""); printf(" :%10u", n0); PRINT_PERC(n0, sum); printf(" :%10u", n1); PRINT_PERC(n1, sum); } printf("\n\n"); fflush(stdout); } } g_CBcjStat; */ tmp41wklro_/CPP/7zip/Compress/Bcj2Coder.h0000444000175000001440000000565114375372660021201 0ustar nabijaczleweliusers// Bcj2Coder.h #ifndef ZIP7_INC_COMPRESS_BCJ2_CODER_H #define ZIP7_INC_COMPRESS_BCJ2_CODER_H #include "../../../C/Bcj2.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NBcj2 { class CBaseCoder { protected: Byte *_bufs[BCJ2_NUM_STREAMS + 1]; UInt32 _bufsSizes[BCJ2_NUM_STREAMS + 1]; UInt32 _bufsSizes_New[BCJ2_NUM_STREAMS + 1]; HRESULT Alloc(bool allocForOrig = true); public: CBaseCoder(); ~CBaseCoder(); }; #ifndef Z7_EXTRACT_ONLY class CEncoder Z7_final: public ICompressCoder2, public ICompressSetCoderProperties, public ICompressSetBufSize, public CMyUnknownImp, public CBaseCoder { Z7_IFACES_IMP_UNK_3( ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize) UInt32 _relatLim; // UInt32 _excludeRangeBits; HRESULT CodeReal( ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); public: CEncoder(); ~CEncoder(); }; #endif class CBaseDecoder: public CBaseCoder { protected: HRESULT _readRes[BCJ2_NUM_STREAMS]; unsigned _extraSizes[BCJ2_NUM_STREAMS]; UInt64 _readSizes[BCJ2_NUM_STREAMS]; CBcj2Dec dec; UInt64 GetProcessedSize_ForInStream(unsigned i) const { return _readSizes[i] - ((size_t)(dec.lims[i] - dec.bufs[i]) + _extraSizes[i]); } void InitCommon(); void ReadInStream(ISequentialInStream *inStream); }; class CDecoder Z7_final: public ICompressCoder2, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize2, public ICompressSetBufSize, #ifndef Z7_NO_READ_FROM_CODER public ICompressSetInStream2, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp, public CBaseDecoder { Z7_COM_QI_BEGIN2(ICompressCoder2) Z7_COM_QI_ENTRY(ICompressSetFinishMode) Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize2) Z7_COM_QI_ENTRY(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER Z7_COM_QI_ENTRY(ICompressSetInStream2) Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) Z7_COM_QI_ENTRY(ISequentialInStream) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressCoder2) Z7_IFACE_COM7_IMP(ICompressSetFinishMode) Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize2) Z7_IFACE_COM7_IMP(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER Z7_IFACE_COM7_IMP(ICompressSetInStream2) Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) Z7_IFACE_COM7_IMP(ISequentialInStream) #endif bool _finishMode; #ifndef Z7_NO_READ_FROM_CODER bool _outSizeDefined; UInt64 _outSize; UInt64 _outSize_Processed; CMyComPtr _inStreams[BCJ2_NUM_STREAMS]; #endif public: CDecoder(); }; }} #endif tmp41wklro_/CPP/7zip/Compress/Bcj2Register.cpp0000444000175000001440000000074514365514000022244 0ustar nabijaczleweliusers// Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2) #ifndef Z7_EXTRACT_ONLY REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2) #else #define CreateCodecOut NULL #endif REGISTER_CODEC_VAR(BCJ2) { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false }; REGISTER_CODEC(BCJ2) }} tmp41wklro_/CPP/7zip/Compress/BcjCoder.cpp0000444000175000001440000000066414410354640021435 0ustar nabijaczleweliusers// BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" namespace NCompress { namespace NBcj { Z7_COM7F_IMF(CCoder2::Init()) { _pc = 0; _state = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL; return S_OK; } Z7_COM7F_IMF2(UInt32, CCoder2::Filter(Byte *data, UInt32 size)) { const UInt32 processed = (UInt32)(size_t)(_convFunc(data, size, _pc, &_state) - data); _pc += processed; return processed; } }} tmp41wklro_/CPP/7zip/Compress/BcjCoder.h0000444000175000001440000000137614377637100021112 0ustar nabijaczleweliusers// BcjCoder.h #ifndef ZIP7_INC_COMPRESS_BCJ_CODER_H #define ZIP7_INC_COMPRESS_BCJ_CODER_H #include "../../../C/Bra.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NBcj { /* CCoder in old versions used another constructor parameter CCoder(int encode). And some code called it as CCoder(0). We have changed constructor parameter type. So we have changed the name of class also to CCoder2. */ Z7_CLASS_IMP_COM_1( CCoder2 , ICompressFilter ) UInt32 _pc; UInt32 _state; z7_Func_BranchConvSt _convFunc; public: CCoder2(z7_Func_BranchConvSt convFunc): _pc(0), _state(Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL), _convFunc(convFunc) {} }; }} #endif tmp41wklro_/CPP/7zip/Compress/BcjRegister.cpp0000444000175000001440000000043414374651260022167 0ustar nabijaczleweliusers// BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" namespace NCompress { namespace NBcj { REGISTER_FILTER_E(BCJ, CCoder2(z7_BranchConvSt_X86_Dec), CCoder2(z7_BranchConvSt_X86_Enc), 0x3030103, "BCJ") }} tmp41wklro_/CPP/7zip/Compress/BranchMisc.cpp0000444000175000001440000000407214564101640021770 0ustar nabijaczleweliusers// BranchMisc.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "../Common/StreamUtils.h" #include "BranchMisc.h" namespace NCompress { namespace NBranch { Z7_COM7F_IMF(CCoder::Init()) { _pc = 0; return S_OK; } Z7_COM7F_IMF2(UInt32, CCoder::Filter(Byte *data, UInt32 size)) { const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data); _pc += processed; return processed; } #ifndef Z7_EXTRACT_ONLY Z7_COM7F_IMF(CEncoder::Init()) { _pc = _pc_Init; return S_OK; } Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size)) { const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data); _pc += processed; return processed; } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) { UInt32 pc = 0; for (UInt32 i = 0; i < numProps; i++) { const PROPID propID = propIDs[i]; if (propID == NCoderPropID::kDefaultProp || propID == NCoderPropID::kBranchOffset) { const PROPVARIANT &prop = props[i]; if (prop.vt != VT_UI4) return E_INVALIDARG; pc = prop.ulVal; if (pc & _alignment) return E_INVALIDARG; } } _pc_Init = pc; return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { if (_pc_Init == 0) return S_OK; UInt32 buf32[1]; SetUi32(buf32, _pc_Init) return WriteStream(outStream, buf32, 4); } #endif Z7_COM7F_IMF(CDecoder::Init()) { _pc = _pc_Init; return S_OK; } Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size)) { const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data); _pc += processed; return processed; } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)) { UInt32 val = 0; if (size != 0) { if (size != 4) return E_NOTIMPL; val = GetUi32(props); if (val & _alignment) return E_NOTIMPL; } _pc_Init = val; return S_OK; } }} tmp41wklro_/CPP/7zip/Compress/BranchMisc.h0000444000175000001440000000215514554710260021440 0ustar nabijaczleweliusers// BranchMisc.h #ifndef ZIP7_INC_COMPRESS_BRANCH_MISC_H #define ZIP7_INC_COMPRESS_BRANCH_MISC_H #include "../../../C/Bra.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NBranch { Z7_CLASS_IMP_COM_1( CCoder , ICompressFilter ) UInt32 _pc; z7_Func_BranchConv BraFunc; public: CCoder(z7_Func_BranchConv bra): _pc(0), BraFunc(bra) {} }; #ifndef Z7_EXTRACT_ONLY Z7_CLASS_IMP_COM_3( CEncoder , ICompressFilter , ICompressSetCoderProperties , ICompressWriteCoderProperties ) UInt32 _pc; UInt32 _pc_Init; UInt32 _alignment; z7_Func_BranchConv BraFunc; public: CEncoder(z7_Func_BranchConv bra, UInt32 alignment): _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {} }; #endif Z7_CLASS_IMP_COM_2( CDecoder , ICompressFilter , ICompressSetDecoderProperties2 ) UInt32 _pc; UInt32 _pc_Init; UInt32 _alignment; z7_Func_BranchConv BraFunc; public: CDecoder(z7_Func_BranchConv bra, UInt32 alignment): _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {} }; }} #endif tmp41wklro_/CPP/7zip/Compress/BranchRegister.cpp0000444000175000001440000000272014560733420022662 0ustar nabijaczleweliusers// BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" namespace NCompress { namespace NBranch { #ifdef Z7_EXTRACT_ONLY #define GET_CREATE_FUNC(x) NULL #define CREATE_BRA_E(n) #else #define GET_CREATE_FUNC(x) x #define CREATE_BRA_E(n) \ REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(Z7_BRANCH_CONV_ENC_2(n))) #endif #define CREATE_BRA(n) \ REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(Z7_BRANCH_CONV_DEC_2(n))) \ CREATE_BRA_E(n) CREATE_BRA(BranchConv_PPC) CREATE_BRA(BranchConv_IA64) CREATE_BRA(BranchConv_ARM) CREATE_BRA(BranchConv_ARMT) CREATE_BRA(BranchConv_SPARC) #define METHOD_ITEM(n, id, name) \ REGISTER_FILTER_ITEM( \ CreateBra_Decoder_ ## n, GET_CREATE_FUNC( \ CreateBra_Encoder_ ## n), \ 0x3030000 + id, name) REGISTER_CODECS_VAR { METHOD_ITEM(BranchConv_PPC, 0x205, "PPC"), METHOD_ITEM(BranchConv_IA64, 0x401, "IA64"), METHOD_ITEM(BranchConv_ARM, 0x501, "ARM"), METHOD_ITEM(BranchConv_ARMT, 0x701, "ARMT"), METHOD_ITEM(BranchConv_SPARC, 0x805, "SPARC") }; REGISTER_CODECS(Branch) #define REGISTER_FILTER_E_BRANCH(id, n, name, alignment) \ REGISTER_FILTER_E(n, \ CDecoder(Z7_BRANCH_CONV_DEC(n), alignment), \ CEncoder(Z7_BRANCH_CONV_ENC(n), alignment), \ id, name) REGISTER_FILTER_E_BRANCH(0xa, ARM64, "ARM64", 3) REGISTER_FILTER_E_BRANCH(0xb, RISCV, "RISCV", 1) }} tmp41wklro_/CPP/7zip/Compress/ByteSwap.cpp0000444000175000001440000000362614404313440021515 0ustar nabijaczleweliusers// ByteSwap.cpp #include "StdAfx.h" #include "../../../C/SwapBytes.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../Common/RegisterCodec.h" namespace NCompress { namespace NByteSwap { Z7_CLASS_IMP_COM_1(CByteSwap2, ICompressFilter) }; Z7_CLASS_IMP_COM_1(CByteSwap4, ICompressFilter) }; Z7_COM7F_IMF(CByteSwap2::Init()) { return S_OK; } Z7_COM7F_IMF2(UInt32, CByteSwap2::Filter(Byte *data, UInt32 size)) { const UInt32 kMask = 2 - 1; size &= ~kMask; /* if ((unsigned)(ptrdiff_t)data & kMask) { if (size == 0) return 0; const Byte *end = data + (size_t)size; do { const Byte b0 = data[0]; data[0] = data[1]; data[1] = b0; data += kStep; } while (data != end); } else */ z7_SwapBytes2((UInt16 *)(void *)data, size >> 1); return size; } Z7_COM7F_IMF(CByteSwap4::Init()) { return S_OK; } Z7_COM7F_IMF2(UInt32, CByteSwap4::Filter(Byte *data, UInt32 size)) { const UInt32 kMask = 4 - 1; size &= ~kMask; /* if ((unsigned)(ptrdiff_t)data & kMask) { if (size == 0) return 0; const Byte *end = data + (size_t)size; do { const Byte b0 = data[0]; const Byte b1 = data[1]; data[0] = data[3]; data[1] = data[2]; data[2] = b1; data[3] = b0; data += kStep; } while (data != end); } else */ z7_SwapBytes4((UInt32 *)(void *)data, size >> 2); return size; } static struct C_SwapBytesPrepare { C_SwapBytesPrepare() { z7_SwapBytesPrepare(); } } g_SwapBytesPrepare; REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2()) REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4()) REGISTER_CODECS_VAR { REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"), REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4"), }; REGISTER_CODECS(ByteSwap) }} tmp41wklro_/CPP/7zip/Compress/CodecExports.cpp0000444000175000001440000002260714414244460022367 0ustar nabijaczleweliusers// CodecExports.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "../../../C/7zVersion.h" #include "../../Common/ComTry.h" #include "../../Common/MyCom.h" #include "../../Windows/Defs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" #include "../Common/RegisterCodec.h" extern unsigned g_NumCodecs; extern const CCodecInfo *g_Codecs[]; extern unsigned g_NumHashers; extern const CHasherInfo *g_Hashers[]; static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw() { const UINT len = (UINT)strlen(s); BSTR dest = ::SysAllocStringLen(NULL, len); if (dest) { for (UINT i = 0; i <= len; i++) dest[i] = (Byte)s[i]; prop->bstrVal = dest; prop->vt = VT_BSTR; } } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw() { if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL) value->vt = VT_BSTR; return S_OK; } static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw() { GUID clsId; clsId.Data1 = k_7zip_GUID_Data1; clsId.Data2 = k_7zip_GUID_Data2; clsId.Data3 = typeId; SetUi64(clsId.Data4, id) return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw() { index = -1; if (clsid->Data1 != k_7zip_GUID_Data1 || clsid->Data2 != k_7zip_GUID_Data2) return S_OK; encode = true; if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false; else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK; const UInt64 id = GetUi64(clsid->Data4); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || (encode ? !codec.CreateEncoder : !codec.CreateDecoder) || (isFilter ? !codec.IsFilter : codec.IsFilter)) continue; if (codec.NumStreams == 1 ? isCoder2 : !isCoder2) return E_NOINTERFACE; index = (int)i; return S_OK; } return S_OK; } /* #ifdef __GNUC__ #ifndef __clang__ #pragma GCC diagnostic ignored "-Wduplicated-branches" #endif #endif */ static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder) { COM_TRY_BEGIN const CCodecInfo &codec = *g_Codecs[index]; void *c; if (encode) c = codec.CreateEncoder(); else c = codec.CreateDecoder(); if (c) { IUnknown *unk; unk = (IUnknown *)c; /* if (codec.IsFilter) unk = (IUnknown *)(ICompressFilter *)c; else if (codec.NumStreams != 1) unk = (IUnknown *)(ICompressCoder2 *)c; else unk = (IUnknown *)(ICompressCoder *)c; */ unk->AddRef(); *coder = c; } return S_OK; COM_TRY_END } static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { *outObject = NULL; const CCodecInfo &codec = *g_Codecs[index]; if (encode ? !codec.CreateEncoder : !codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; if (codec.IsFilter) { if (*iid != IID_ICompressFilter) return E_NOINTERFACE; } else if (codec.NumStreams != 1) { if (*iid != IID_ICompressCoder2) return E_NOINTERFACE; } else { if (*iid != IID_ICompressCoder) return E_NOINTERFACE; } return CreateCoderMain(index, encode, outObject); } STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject) { return CreateCoder2(false, index, iid, outObject); } STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject) { return CreateCoder2(true, index, iid, outObject); } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = NULL; bool isFilter = false; bool isCoder2 = false; const bool isCoder = (*iid == IID_ICompressCoder) != 0; if (!isCoder) { isFilter = (*iid == IID_ICompressFilter) != 0; if (!isFilter) { isCoder2 = (*iid == IID_ICompressCoder2) != 0; if (!isCoder2) return E_NOINTERFACE; } } bool encode; int codecIndex; const HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoderMain((unsigned)codecIndex, encode, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch (propID) { case NMethodPropID::kID: value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; case NMethodPropID::kName: SetPropFromAscii(codec.Name, value); break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value); break; case NMethodPropID::kDecoderIsAssigned: value->vt = VT_BOOL; value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL); break; case NMethodPropID::kEncoderIsAssigned: value->vt = VT_BOOL; value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL); break; case NMethodPropID::kPackStreams: if (codec.NumStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumStreams; } break; case NMethodPropID::kIsFilter: { value->vt = VT_BOOL; value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter); } break; /* case NMethodPropID::kDecoderFlags: { value->vt = VT_UI4; value->ulVal = (ULONG)codec.DecoderFlags; } break; case NMethodPropID::kEncoderFlags: { value->vt = VT_UI4; value->ulVal = (ULONG)codec.EncoderFlags; } break; */ } return S_OK; } STDAPI GetNumberOfMethods(UInt32 *numCodecs); STDAPI GetNumberOfMethods(UInt32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } // ---------- Hashers ---------- static int FindHasherClassId(const GUID *clsid) throw() { if (clsid->Data1 != k_7zip_GUID_Data1 || clsid->Data2 != k_7zip_GUID_Data2 || clsid->Data3 != k_7zip_GUID_Data3_Hasher) return -1; const UInt64 id = GetUi64(clsid->Data4); for (unsigned i = 0; i < g_NumCodecs; i++) if (id == g_Hashers[i]->Id) return (int)i; return -1; } static HRESULT CreateHasher2(UInt32 index, IHasher **hasher) { COM_TRY_BEGIN *hasher = g_Hashers[index]->CreateHasher(); if (*hasher) (*hasher)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateHasher(const GUID *clsid, IHasher **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **outObject) { COM_TRY_BEGIN *outObject = NULL; const int index = FindHasherClassId(clsid); if (index < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateHasher2((UInt32)(unsigned)index, outObject); COM_TRY_END } STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CHasherInfo &codec = *g_Hashers[codecIndex]; switch (propID) { case NMethodPropID::kID: value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; case NMethodPropID::kName: SetPropFromAscii(codec.Name, value); break; case NMethodPropID::kEncoder: if (codec.CreateHasher) return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value); break; case NMethodPropID::kDigestSize: value->ulVal = (ULONG)codec.DigestSize; value->vt = VT_UI4; break; } return S_OK; } Z7_CLASS_IMP_COM_1(CHashers, IHashers) }; STDAPI GetHashers(IHashers **hashers); STDAPI GetHashers(IHashers **hashers) { COM_TRY_BEGIN *hashers = new CHashers; if (*hashers) (*hashers)->AddRef(); return S_OK; COM_TRY_END } Z7_COM7F_IMF2(UInt32, CHashers::GetNumHashers()) { return g_NumHashers; } Z7_COM7F_IMF(CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) { return ::GetHasherProp(index, propID, value); } Z7_COM7F_IMF(CHashers::CreateHasher(UInt32 index, IHasher **hasher)) { return ::CreateHasher2(index, hasher); } STDAPI GetModuleProp(PROPID propID, PROPVARIANT *value); STDAPI GetModuleProp(PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); switch (propID) { case NModulePropID::kInterfaceType: { NWindows::NCOM::PropVarEm_Set_UInt32(value, NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule); break; } case NModulePropID::kVersion: { NWindows::NCOM::PropVarEm_Set_UInt32(value, (MY_VER_MAJOR << 16) | MY_VER_MINOR); break; } } return S_OK; } tmp41wklro_/CPP/7zip/Compress/CopyCoder.cpp0000444000175000001440000000706614366434040021657 0ustar nabijaczleweliusers// Compress/CopyCoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buf); } Z7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */)) { return S_OK; } Z7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) { if (!_buf) { _buf = (Byte *)::MidAlloc(kBufSize); if (!_buf) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 size = kBufSize; if (outSize) { const UInt64 rem = *outSize - TotalSize; if (size > rem) { size = (UInt32)rem; if (size == 0) { /* if we enable the following check, we will make one call of Read(_buf, 0) for empty stream */ // if (TotalSize != 0) return S_OK; } } } HRESULT readRes; { UInt32 pos = 0; do { const UInt32 curSize = size - pos; UInt32 processed = 0; readRes = inStream->Read(_buf + pos, curSize, &processed); if (processed > curSize) return E_FAIL; // internal code failure pos += processed; if (readRes != S_OK || processed == 0) break; } while (pos < kBufSize); size = pos; } if (size == 0) return readRes; if (outStream) { UInt32 pos = 0; do { const UInt32 curSize = size - pos; UInt32 processed = 0; const HRESULT res = outStream->Write(_buf + pos, curSize, &processed); if (processed > curSize) return E_FAIL; // internal code failure pos += processed; TotalSize += processed; RINOK(res) if (processed == 0) return E_FAIL; } while (pos < size); } else TotalSize += size; RINOK(readRes) if (size != kBufSize) return S_OK; if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)) } } } Z7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream)) { _inStream = inStream; TotalSize = 0; return S_OK; } Z7_COM7F_IMF(CCopyCoder::ReleaseInStream()) { _inStream.Release(); return S_OK; } Z7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { UInt32 realProcessedSize = 0; HRESULT res = _inStream->Read(data, size, &realProcessedSize); TotalSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; return res; } Z7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value)) { *value = TotalSize; return S_OK; } HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { CMyComPtr copyCoder = new CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, progress); } HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) { NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)) return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; } } tmp41wklro_/CPP/7zip/Compress/CopyCoder.h0000444000175000001440000000145014366244420021314 0ustar nabijaczleweliusers// Compress/CopyCoder.h #ifndef ZIP7_INC_COMPRESS_COPY_CODER_H #define ZIP7_INC_COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { Z7_CLASS_IMP_COM_5( CCopyCoder , ICompressCoder , ICompressSetInStream , ISequentialInStream , ICompressSetFinishMode , ICompressGetInStreamProcessedSize ) Byte *_buf; CMyComPtr _inStream; public: UInt64 TotalSize; CCopyCoder(): _buf(NULL), TotalSize(0) {} ~CCopyCoder(); }; HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress); } #endif tmp41wklro_/CPP/7zip/Compress/CopyRegister.cpp0000444000175000001440000000037712707365677022425 0ustar nabijaczleweliusers// CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" namespace NCompress { REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder()) REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy") } tmp41wklro_/CPP/7zip/Compress/DeltaFilter.cpp0000444000175000001440000000476614544576640022206 0ustar nabijaczleweliusers// DeltaFilter.cpp #include "StdAfx.h" #include "../../../C/Delta.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../Common/RegisterCodec.h" namespace NCompress { namespace NDelta { struct CDelta { unsigned _delta; Byte _state[DELTA_STATE_SIZE]; CDelta(): _delta(1) {} void DeltaInit() { Delta_Init(_state); } }; #ifndef Z7_EXTRACT_ONLY class CEncoder Z7_final: public ICompressFilter, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp, CDelta { Z7_IFACES_IMP_UNK_3( ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties) }; Z7_COM7F_IMF(CEncoder::Init()) { DeltaInit(); return S_OK; } Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size)) { Delta_Encode(_state, _delta, data, size); return size; } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) { unsigned delta = _delta; for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = props[i]; const PROPID propID = propIDs[i]; if (propID >= NCoderPropID::kReduceSize) continue; if (prop.vt != VT_UI4) return E_INVALIDARG; switch (propID) { case NCoderPropID::kDefaultProp: if (prop.ulVal < 1 || prop.ulVal > 256) return E_INVALIDARG; delta = prop.ulVal; break; case NCoderPropID::kNumThreads: break; case NCoderPropID::kLevel: break; default: return E_INVALIDARG; } } _delta = delta; return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { const Byte prop = (Byte)(_delta - 1); return outStream->Write(&prop, 1, NULL); } #endif class CDecoder Z7_final: public ICompressFilter, public ICompressSetDecoderProperties2, public CMyUnknownImp, CDelta { Z7_IFACES_IMP_UNK_2( ICompressFilter, ICompressSetDecoderProperties2) }; Z7_COM7F_IMF(CDecoder::Init()) { DeltaInit(); return S_OK; } Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size)) { Delta_Decode(_state, _delta, data, size); return size; } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)) { if (size != 1) return E_INVALIDARG; _delta = (unsigned)props[0] + 1; return S_OK; } REGISTER_FILTER_E(Delta, CDecoder(), CEncoder(), 3, "Delta") }} tmp41wklro_/CPP/7zip/Compress/Lzma2Decoder.cpp0000444000175000001440000001440414410544260022231 0ustar nabijaczleweliusers// Lzma2Decoder.cpp #include "StdAfx.h" // #include #include "../../../C/Alloc.h" // #include "../../../C/CpuTicks.h" #include "../Common/StreamUtils.h" #include "Lzma2Decoder.h" namespace NCompress { namespace NLzma2 { CDecoder::CDecoder(): _dec(NULL) , _inProcessed(0) , _prop(0xFF) , _finishMode(false) , _inBufSize(1 << 20) , _outStep(1 << 20) #ifndef Z7_ST , _tryMt(1) , _numThreads(1) , _memUsage((UInt64)(sizeof(size_t)) << 28) #endif {} CDecoder::~CDecoder() { if (_dec) Lzma2DecMt_Destroy(_dec); } Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; } Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)) { if (size != 1) return E_NOTIMPL; if (prop[0] > 40) return E_NOTIMPL; _prop = prop[0]; return S_OK; } Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) { _finishMode = (finishMode != 0); return S_OK; } #ifndef Z7_ST static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize) { const UInt32 kMinSize = (UInt32)1 << 20; const UInt32 kMaxSize = (UInt32)1 << 28; UInt64 blockSize = (UInt64)dictSize << 2; if (blockSize < kMinSize) blockSize = kMinSize; if (blockSize > kMaxSize) blockSize = kMaxSize; if (blockSize < dictSize) blockSize = dictSize; blockSize += (kMinSize - 1); blockSize &= ~(UInt64)(kMinSize - 1); return blockSize; } #define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))) #endif #define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) { _inProcessed = 0; if (!_dec) { _dec = Lzma2DecMt_Create( // &g_AlignedAlloc, &g_Alloc, &g_MidAlloc); if (!_dec) return E_OUTOFMEMORY; } CLzma2DecMtProps props; Lzma2DecMtProps_Init(&props); props.inBufSize_ST = _inBufSize; props.outStep_ST = _outStep; #ifndef Z7_ST { props.numThreads = 1; UInt32 numThreads = _numThreads; if (_tryMt && numThreads >= 1) { const UInt64 useLimit = _memUsage; const UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop); const UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize); const size_t expectedBlockSize = (size_t)expectedBlockSize64; const size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16; if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize) { props.outBlockMax = expectedBlockSize; props.inBlockMax = inBlockMax; const size_t kOverheadSize = props.inBufSize_MT + (1 << 16); const UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize); if (numThreads > okThreads) numThreads = (UInt32)okThreads; if (numThreads == 0) numThreads = 1; props.numThreads = numThreads; } } } #endif CSeqInStreamWrap inWrap; CSeqOutStreamWrap outWrap; CCompressProgressWrap progressWrap; inWrap.Init(inStream); outWrap.Init(outStream); progressWrap.Init(progress); SRes res; UInt64 inProcessed = 0; int isMT = False; #ifndef Z7_ST isMT = _tryMt; #endif // UInt64 cpuTicks = GetCpuTicks(); res = Lzma2DecMt_Decode(_dec, _prop, &props, &outWrap.vt, outSize, _finishMode, &inWrap.vt, &inProcessed, &isMT, progress ? &progressWrap.vt : NULL); /* cpuTicks = GetCpuTicks() - cpuTicks; printf("\n ticks = %10I64u\n", cpuTicks / 1000000); */ #ifndef Z7_ST /* we reset _tryMt, only if p->props.numThreads was changed */ if (props.numThreads > 1) _tryMt = isMT; #endif _inProcessed = inProcessed; RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) if (res == SZ_OK && _finishMode) { if (inSize && *inSize != inProcessed) res = SZ_ERROR_DATA; if (outSize && *outSize != outWrap.Processed) res = SZ_ERROR_DATA; } return SResToHRESULT(res); } Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value)) { *value = _inProcessed; return S_OK; } #ifndef Z7_ST Z7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads)) { _numThreads = numThreads; return S_OK; } Z7_COM7F_IMF(CDecoder::SetMemLimit(UInt64 memUsage)) { _memUsage = memUsage; return S_OK; } #endif #ifndef Z7_NO_READ_FROM_CODER Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) { CLzma2DecMtProps props; Lzma2DecMtProps_Init(&props); props.inBufSize_ST = _inBufSize; props.outStep_ST = _outStep; _inProcessed = 0; if (!_dec) { _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc); if (!_dec) return E_OUTOFMEMORY; } _inWrap.Init(_inStream); const SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt); if (res != SZ_OK) return SResToHRESULT(res); return S_OK; } Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream)) { _inStream = inStream; return S_OK; } Z7_COM7F_IMF(CDecoder::ReleaseInStream()) { _inStream.Release(); return S_OK; } Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; size_t size2 = size; UInt64 inProcessed = 0; const SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed); _inProcessed += inProcessed; if (processedSize) *processedSize = (UInt32)size2; if (res != SZ_OK) return SResToHRESULT(res); return S_OK; } #endif }} tmp41wklro_/CPP/7zip/Compress/Lzma2Decoder.h0000444000175000001440000000411414366434040021677 0ustar nabijaczleweliusers// Lzma2Decoder.h #ifndef ZIP7_INC_LZMA2_DECODER_H #define ZIP7_INC_LZMA2_DECODER_H #include "../../../C/Lzma2DecMt.h" #include "../Common/CWrappers.h" namespace NCompress { namespace NLzma2 { class CDecoder Z7_final: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, public ICompressSetBufSize, #ifndef Z7_NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif #ifndef Z7_ST public ICompressSetCoderMt, public ICompressSetMemLimit, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(ICompressCoder) Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2) Z7_COM_QI_ENTRY(ICompressSetFinishMode) Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize) Z7_COM_QI_ENTRY(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER Z7_COM_QI_ENTRY(ICompressSetInStream) Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) Z7_COM_QI_ENTRY(ISequentialInStream) #endif #ifndef Z7_ST Z7_COM_QI_ENTRY(ICompressSetCoderMt) Z7_COM_QI_ENTRY(ICompressSetMemLimit) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressCoder) Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) Z7_IFACE_COM7_IMP(ICompressSetFinishMode) Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize) Z7_IFACE_COM7_IMP(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) Z7_IFACE_COM7_IMP(ICompressSetInStream) Z7_IFACE_COM7_IMP(ISequentialInStream) #endif #ifndef Z7_ST Z7_IFACE_COM7_IMP(ICompressSetCoderMt) Z7_IFACE_COM7_IMP(ICompressSetMemLimit) #endif CLzma2DecMtHandle _dec; UInt64 _inProcessed; Byte _prop; int _finishMode; UInt32 _inBufSize; UInt32 _outStep; #ifndef Z7_ST int _tryMt; UInt32 _numThreads; UInt64 _memUsage; #endif #ifndef Z7_NO_READ_FROM_CODER CMyComPtr _inStream; CSeqInStreamWrap _inWrap; #endif public: CDecoder(); ~CDecoder(); }; }} #endif tmp41wklro_/CPP/7zip/Compress/Lzma2Encoder.cpp0000444000175000001440000000620714410544260022245 0ustar nabijaczleweliusers// Lzma2Encoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/CWrappers.h" #include "../Common/StreamUtils.h" #include "Lzma2Encoder.h" namespace NCompress { namespace NLzma { HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); } namespace NLzma2 { CEncoder::CEncoder() { _encoder = NULL; _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc); if (!_encoder) throw 1; } CEncoder::~CEncoder() { if (_encoder) Lzma2Enc_Destroy(_encoder); } HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props) { switch (propID) { case NCoderPropID::kBlockSize: { if (prop.vt == VT_UI4) lzma2Props.blockSize = prop.ulVal; else if (prop.vt == VT_UI8) lzma2Props.blockSize = prop.uhVal.QuadPart; else return E_INVALIDARG; break; } case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break; default: RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)) } return S_OK; } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { CLzma2EncProps lzma2Props; Lzma2EncProps_Init(&lzma2Props); for (UInt32 i = 0; i < numProps; i++) { RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props)) } return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props)); } Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; const PROPID propID = propIDs[i]; if (propID == NCoderPropID::kExpectedDataSize) if (prop.vt == VT_UI8) Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart); } return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { const Byte prop = Lzma2Enc_WriteProperties(_encoder); return WriteStream(outStream, &prop, 1); } #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)) { CSeqInStreamWrap inWrap; CSeqOutStreamWrap outWrap; CCompressProgressWrap progressWrap; inWrap.Init(inStream); outWrap.Init(outStream); progressWrap.Init(progress); SRes res = Lzma2Enc_Encode2(_encoder, &outWrap.vt, NULL, NULL, &inWrap.vt, NULL, 0, progress ? &progressWrap.vt : NULL); RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) return SResToHRESULT(res); } }} tmp41wklro_/CPP/7zip/Compress/Lzma2Encoder.h0000444000175000001440000000074214410544260021710 0ustar nabijaczleweliusers// Lzma2Encoder.h #ifndef ZIP7_INC_LZMA2_ENCODER_H #define ZIP7_INC_LZMA2_ENCODER_H #include "../../../C/Lzma2Enc.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma2 { Z7_CLASS_IMP_COM_4( CEncoder , ICompressCoder , ICompressSetCoderProperties , ICompressWriteCoderProperties , ICompressSetCoderPropertiesOpt ) CLzma2EncHandle _encoder; public: CEncoder(); ~CEncoder(); }; }} #endif tmp41wklro_/CPP/7zip/Compress/Lzma2Register.cpp0000444000175000001440000000047114365514000022445 0ustar nabijaczleweliusers// Lzma2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Lzma2Decoder.h" #ifndef Z7_EXTRACT_ONLY #include "Lzma2Encoder.h" #endif namespace NCompress { namespace NLzma2 { REGISTER_CODEC_E(LZMA2, CDecoder(), CEncoder(), 0x21, "LZMA2") }} tmp41wklro_/CPP/7zip/Compress/LzmaDecoder.cpp0000444000175000001440000002054114567042400022150 0ustar nabijaczleweliusers// LzmaDecoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch (res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; case SZ_ERROR_DATA: return S_FALSE; default: break; } return E_FAIL; } namespace NCompress { namespace NLzma { CDecoder::CDecoder(): FinishStream(false), _propsWereSet(false), _outSizeDefined(false), _outStep(1 << 20), _inBufSize(0), _inBufSizeNew(1 << 20), _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED), _inBuf(NULL) { _inProcessed = 0; _inPos = _inLim = 0; /* AlignOffsetAlloc_CreateVTable(&_alloc); _alloc.numAlignBits = 7; _alloc.offset = 0; */ LzmaDec_CONSTRUCT(&_state) } CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt MyFree(_inBuf); } Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSizeNew = size; return S_OK; } Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; } HRESULT CDecoder::CreateInputBuffer() { if (!_inBuf || _inBufSizeNew != _inBufSize) { MyFree(_inBuf); _inBufSize = 0; _inBuf = (Byte *)MyAlloc(_inBufSizeNew); if (!_inBuf) return E_OUTOFMEMORY; _inBufSize = _inBufSizeNew; } return S_OK; } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt _propsWereSet = true; return CreateInputBuffer(); } void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); _outSize = 0; if (_outSizeDefined) _outSize = *outSize; _outProcessed = 0; _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED; LzmaDec_Init(&_state); } Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) { _inProcessed = 0; _inPos = _inLim = 0; SetOutStreamSizeResume(outSize); return S_OK; } Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) { FinishStream = (finishMode != 0); return S_OK; } Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value)) { *value = _inProcessed; return S_OK; } HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { if (!_inBuf || !_propsWereSet) return S_FALSE; const UInt64 startInProgress = _inProcessed; SizeT wrPos = _state.dicPos; HRESULT readRes = S_OK; for (;;) { if (_inPos == _inLim && readRes == S_OK) { _inPos = _inLim = 0; readRes = inStream->Read(_inBuf, _inBufSize, &_inLim); } const SizeT dicPos = _state.dicPos; SizeT size; { SizeT next = _state.dicBufSize; if (next - wrPos > _outStep) next = wrPos + _outStep; size = next - dicPos; } ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outProcessed; if (size >= rem) { size = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inProcessed = _inLim - _inPos; ELzmaStatus status; const SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); _lzmaStatus = status; _inPos += (UInt32)inProcessed; _inProcessed += inProcessed; const SizeT outProcessed = _state.dicPos - dicPos; _outProcessed += outProcessed; // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0) const bool outFinished = (_outSizeDefined && _outProcessed >= _outSize); const bool needStop = (res != 0 || (inProcessed == 0 && outProcessed == 0) || status == LZMA_STATUS_FINISHED_WITH_MARK || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)); if (needStop || outProcessed >= size) { const HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos); if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; wrPos = _state.dicPos; RINOK(res2) if (needStop) { if (res != 0) { // return SResToHRESULT(res); return S_FALSE; } if (status == LZMA_STATUS_FINISHED_WITH_MARK) { if (FinishStream) if (_outSizeDefined && _outSize != _outProcessed) return S_FALSE; return readRes; } if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT) if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) return readRes; return S_FALSE; } } if (progress) { const UInt64 inSize = _inProcessed - startInProgress; RINOK(progress->SetRatioInfo(&inSize, &_outProcessed)) } } } Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) { if (!_inBuf) return E_INVALIDARG; SetOutStreamSize(outSize); HRESULT res = CodeSpec(inStream, outStream, progress); if (res == S_OK) if (FinishStream && inSize && *inSize != _inProcessed) res = S_FALSE; return res; } #ifndef Z7_NO_READ_FROM_CODER Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream)) { _inStream = inStream; return S_OK; } Z7_COM7F_IMF(CDecoder::ReleaseInStream()) { _inStream.Release(); return S_OK; } Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outProcessed; if (size >= rem) { size = (UInt32)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } HRESULT readRes = S_OK; for (;;) { if (_inPos == _inLim && readRes == S_OK) { _inPos = _inLim = 0; readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); } SizeT inProcessed = _inLim - _inPos; SizeT outProcessed = size; ELzmaStatus status; const SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, finishMode, &status); _lzmaStatus = status; _inPos += (UInt32)inProcessed; _inProcessed += inProcessed; _outProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; if (res != 0) return S_FALSE; /* if (status == LZMA_STATUS_FINISHED_WITH_MARK) return readRes; if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) { if (FinishStream && _outSizeDefined && _outProcessed >= _outSize && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) return S_FALSE; return readRes; } */ if (inProcessed == 0 && outProcessed == 0) return readRes; } } HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) { SetOutStreamSizeResume(outSize); return CodeSpec(_inStream, outStream, progress); } HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize) { RINOK(CreateInputBuffer()) if (processedSize) *processedSize = 0; HRESULT readRes = S_OK; while (size != 0) { if (_inPos == _inLim) { _inPos = _inLim = 0; if (readRes == S_OK) readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); if (_inLim == 0) break; } UInt32 cur = _inLim - _inPos; if (cur > size) cur = size; memcpy(data, _inBuf + _inPos, cur); _inPos += cur; _inProcessed += cur; size -= cur; data = (Byte *)data + cur; if (processedSize) *processedSize += cur; } return readRes; } #endif }} tmp41wklro_/CPP/7zip/Compress/LzmaDecoder.h0000444000175000001440000000575714410553300021622 0ustar nabijaczleweliusers// LzmaDecoder.h #ifndef ZIP7_INC_LZMA_DECODER_H #define ZIP7_INC_LZMA_DECODER_H // #include "../../../C/Alloc.h" #include "../../../C/LzmaDec.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder Z7_final: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, public ICompressSetBufSize, #ifndef Z7_NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(ICompressCoder) Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2) Z7_COM_QI_ENTRY(ICompressSetFinishMode) Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize) Z7_COM_QI_ENTRY(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER Z7_COM_QI_ENTRY(ICompressSetInStream) Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) Z7_COM_QI_ENTRY(ISequentialInStream) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressCoder) public: Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) private: Z7_IFACE_COM7_IMP(ICompressSetFinishMode) Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize) // Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) Z7_IFACE_COM7_IMP(ICompressSetBufSize) #ifndef Z7_NO_READ_FROM_CODER public: Z7_IFACE_COM7_IMP(ICompressSetInStream) private: Z7_IFACE_COM7_IMP(ISequentialInStream) Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) #else Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize)); #endif public: bool FinishStream; // set it before decoding, if you need to decode full LZMA stream private: bool _propsWereSet; bool _outSizeDefined; UInt32 _outStep; UInt32 _inBufSize; UInt32 _inBufSizeNew; ELzmaStatus _lzmaStatus; UInt32 _inPos; UInt32 _inLim; Byte *_inBuf; UInt64 _outSize; UInt64 _inProcessed; UInt64 _outProcessed; // CAlignOffsetAlloc _alloc; CLzmaDec _state; HRESULT CreateInputBuffer(); HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); void SetOutStreamSizeResume(const UInt64 *outSize); #ifndef Z7_NO_READ_FROM_CODER private: CMyComPtr _inStream; public: HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize); #endif public: CDecoder(); ~CDecoder(); UInt64 GetInputProcessedSize() const { return _inProcessed; } UInt64 GetOutputProcessedSize() const { return _outProcessed; } bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; } bool CheckFinishStatus(bool withEndMark) const { return _lzmaStatus == (withEndMark ? LZMA_STATUS_FINISHED_WITH_MARK : LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK); } }; }} #endif tmp41wklro_/CPP/7zip/Compress/LzmaEncoder.cpp0000444000175000001440000002110514410562320022152 0ustar nabijaczleweliusers// LzmaEncoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/CWrappers.h" #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" // #define LOG_LZMA_THREADS #ifdef LOG_LZMA_THREADS #include #include "../../Common/IntToString.h" #include "../../Windows/TimeUtils.h" EXTERN_C_BEGIN void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); EXTERN_C_END #endif namespace NCompress { namespace NLzma { CEncoder::CEncoder() { _encoder = NULL; _encoder = LzmaEnc_Create(&g_AlignedAlloc); if (!_encoder) throw 1; } CEncoder::~CEncoder() { if (_encoder) LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc); } static inline wchar_t GetLowCharFast(wchar_t c) { return c |= 0x20; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { const wchar_t c = GetLowCharFast(*s++); if (c == 'h') { if (GetLowCharFast(*s++) != 'c') return 0; const int num = (int)(*s++ - L'0'); if (num < 4 || num > 5) return 0; if (*s != 0) return 0; *btMode = 0; *numHashBytes = num; return 1; } if (c != 'b') return 0; { if (GetLowCharFast(*s++) != 't') return 0; const int num = (int)(*s++ - L'0'); if (num < 2 || num > 5) return 0; if (*s != 0) return 0; *btMode = 1; *numHashBytes = num; return 1; } } #define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = (int)v; break; #define SET_PROP_32U(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) { if (propID == NCoderPropID::kMatchFinder) { if (prop.vt != VT_BSTR) return E_INVALIDARG; return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; } if (propID == NCoderPropID::kAffinity) { if (prop.vt == VT_UI8) ep.affinity = prop.uhVal.QuadPart; else return E_INVALIDARG; return S_OK; } if (propID == NCoderPropID::kHashBits) { if (prop.vt == VT_UI4) ep.numHashOutBits = prop.ulVal; else return E_INVALIDARG; return S_OK; } if (propID > NCoderPropID::kReduceSize) return S_OK; if (propID == NCoderPropID::kReduceSize) { if (prop.vt == VT_UI8) ep.reduceSize = prop.uhVal.QuadPart; else return E_INVALIDARG; return S_OK; } if (propID == NCoderPropID::kDictionarySize) { if (prop.vt == VT_UI8) { // 21.03 : we support 64-bit VT_UI8 for dictionary and (dict == 4 GiB) const UInt64 v = prop.uhVal.QuadPart; if (v > ((UInt64)1 << 32)) return E_INVALIDARG; UInt32 dict; if (v == ((UInt64)1 << 32)) dict = (UInt32)(Int32)-1; else dict = (UInt32)v; ep.dictSize = dict; return S_OK; } } if (prop.vt != VT_UI4) return E_INVALIDARG; const UInt32 v = prop.ulVal; switch (propID) { case NCoderPropID::kDefaultProp: if (v > 32) return E_INVALIDARG; ep.dictSize = (v == 32) ? (UInt32)(Int32)-1 : (UInt32)1 << (unsigned)v; break; SET_PROP_32(kLevel, level) SET_PROP_32(kNumFastBytes, fb) SET_PROP_32U(kMatchFinderCycles, mc) SET_PROP_32(kAlgorithm, algo) SET_PROP_32U(kDictionarySize, dictSize) SET_PROP_32(kPosStateBits, pb) SET_PROP_32(kLitPosBits, lp) SET_PROP_32(kLitContextBits, lc) SET_PROP_32(kNumThreads, numThreads) default: return E_INVALIDARG; } return S_OK; } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; const PROPID propID = propIDs[i]; switch (propID) { case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break; default: RINOK(SetLzmaProp(propID, prop, props)) } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; const PROPID propID = propIDs[i]; if (propID == NCoderPropID::kExpectedDataSize) if (prop.vt == VT_UI8) LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart); } return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { Byte props[LZMA_PROPS_SIZE]; SizeT size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)) return WriteStream(outStream, props, size); } #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; #ifdef LOG_LZMA_THREADS static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') { char temp[64]; char *p = temp + 32; ConvertUInt64ToString(val, p); unsigned len = (unsigned)strlen(p); for (; len < numDigits; len++) *--p = c; printf("%s", p); } static void PrintTime(const char *s, UInt64 val, UInt64 total) { printf(" %s :", s); const UInt32 kFreq = 10000000; UInt64 sec = val / kFreq; PrintNum(sec, 6); printf(" ."); UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); PrintNum(ms, 3, '0'); while (val > ((UInt64)1 << 56)) { val >>= 1; total >>= 1; } UInt64 percent = 0; if (total != 0) percent = val * 100 / total; printf(" ="); PrintNum(percent, 4); printf("%%"); } struct CBaseStat { UInt64 kernelTime, userTime; BOOL Get(HANDLE thread, const CBaseStat *prevStat) { FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; BOOL res = GetThreadTimes(thread , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT); if (res) { kernelTime = GetTime64(kernelTimeFT); userTime = GetTime64(userTimeFT); if (prevStat) { kernelTime -= prevStat->kernelTime; userTime -= prevStat->userTime; } } return res; } }; static void PrintStat(HANDLE thread, UInt64 totalTime, const CBaseStat *prevStat) { CBaseStat newStat; if (!newStat.Get(thread, prevStat)) return; PrintTime("K", newStat.kernelTime, totalTime); const UInt64 processTime = newStat.kernelTime + newStat.userTime; PrintTime("U", newStat.userTime, totalTime); PrintTime("S", processTime, totalTime); printf("\n"); // PrintTime("G ", totalTime, totalTime); } #endif Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)) { CSeqInStreamWrap inWrap; CSeqOutStreamWrap outWrap; CCompressProgressWrap progressWrap; inWrap.Init(inStream); outWrap.Init(outStream); progressWrap.Init(progress); #ifdef LOG_LZMA_THREADS FILETIME startTimeFT; NWindows::NTime::GetCurUtcFileTime(startTimeFT); UInt64 totalTime = GetTime64(startTimeFT); CBaseStat oldStat; if (!oldStat.Get(GetCurrentThread(), NULL)) return E_FAIL; #endif SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc); _inputProcessed = inWrap.Processed; RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) #ifdef LOG_LZMA_THREADS NWindows::NTime::GetCurUtcFileTime(startTimeFT); totalTime = GetTime64(startTimeFT) - totalTime; HANDLE lz_threads[2]; LzmaEnc_GetLzThreads(_encoder, lz_threads); printf("\n"); printf("Main: "); PrintStat(GetCurrentThread(), totalTime, &oldStat); printf("Hash: "); PrintStat(lz_threads[0], totalTime, NULL); printf("BinT: "); PrintStat(lz_threads[1], totalTime, NULL); // PrintTime("Total: ", totalTime, totalTime); printf("\n"); #endif return SResToHRESULT(res); } }} tmp41wklro_/CPP/7zip/Compress/LzmaEncoder.h0000444000175000001440000000203414410562320021617 0ustar nabijaczleweliusers// LzmaEncoder.h #ifndef ZIP7_INC_LZMA_ENCODER_H #define ZIP7_INC_LZMA_ENCODER_H #include "../../../C/LzmaEnc.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CEncoder Z7_final: public ICompressCoder, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public ICompressSetCoderPropertiesOpt, public CMyUnknownImp { Z7_COM_UNKNOWN_IMP_4( ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties, ICompressSetCoderPropertiesOpt) Z7_IFACE_COM7_IMP(ICompressCoder) public: Z7_IFACE_COM7_IMP(ICompressSetCoderProperties) Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt) CLzmaEncHandle _encoder; UInt64 _inputProcessed; CEncoder(); ~CEncoder(); UInt64 GetInputProcessedSize() const { return _inputProcessed; } bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; } }; }} #endif tmp41wklro_/CPP/7zip/Compress/LzmaRegister.cpp0000444000175000001440000000046614365514000022367 0ustar nabijaczleweliusers// LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" #ifndef Z7_EXTRACT_ONLY #include "LzmaEncoder.h" #endif namespace NCompress { namespace NLzma { REGISTER_CODEC_E(LZMA, CDecoder(), CEncoder(), 0x30101, "LZMA") }} tmp41wklro_/CPP/7zip/Compress/PpmdDecoder.cpp0000444000175000001440000001142314567051420022146 0ustar nabijaczleweliusers// PpmdDecoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../../../C/CpuArch.h" #include "../Common/StreamUtils.h" #include "PpmdDecoder.h" namespace NCompress { namespace NPpmd { static const UInt32 kBufSize = (1 << 16); enum { kStatus_NeedInit, kStatus_Normal, kStatus_Finished_With_Mark, kStatus_Error }; CDecoder::~CDecoder() { ::MidFree(_outBuf); Ppmd7_Free(&_ppmd, &g_BigAlloc); } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)) { if (size < 5) return E_INVALIDARG; _order = props[0]; const UInt32 memSize = GetUi32(props + 1); if (_order < PPMD7_MIN_ORDER || _order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return E_NOTIMPL; if (!_inStream.Alloc(1 << 20)) return E_OUTOFMEMORY; if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) return E_OUTOFMEMORY; return S_OK; } #define MY_rangeDec _ppmd.rc.dec #define CHECK_EXTRA_ERROR \ if (_inStream.Extra) { \ _status = kStatus_Error; \ return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); } HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) { if (_res != S_OK) return _res; switch (_status) { case kStatus_Finished_With_Mark: return S_OK; case kStatus_Error: return S_FALSE; case kStatus_NeedInit: _inStream.Init(); if (!Ppmd7z_RangeDec_Init(&MY_rangeDec)) { _status = kStatus_Error; return (_res = S_FALSE); } CHECK_EXTRA_ERROR _status = kStatus_Normal; Ppmd7_Init(&_ppmd, _order); break; default: break; } if (_outSizeDefined) { const UInt64 rem = _outSize - _processedSize; if (size > rem) size = (UInt32)rem; } int sym = 0; { Byte *buf = memStream; const Byte *lim = buf + size; for (; buf != lim; buf++) { sym = Ppmd7z_DecodeSymbol(&_ppmd); if (_inStream.Extra || sym < 0) break; *buf = (Byte)sym; } /* buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim); sym = _ppmd.LastSymbol; */ _processedSize += (size_t)(buf - memStream); } CHECK_EXTRA_ERROR if (sym >= 0) { if (!FinishStream || !_outSizeDefined || _outSize != _processedSize || MY_rangeDec.Code == 0) return S_OK; /* // We can decode additional End Marker here: sym = Ppmd7z_DecodeSymbol(&_ppmd); CHECK_EXTRA_ERROR */ } if (sym != PPMD7_SYM_END || MY_rangeDec.Code != 0) { _status = kStatus_Error; return (_res = S_FALSE); } _status = kStatus_Finished_With_Mark; return S_OK; } Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) { if (!_outBuf) { _outBuf = (Byte *)::MidAlloc(kBufSize); if (!_outBuf) return E_OUTOFMEMORY; } _inStream.Stream = inStream; SetOutStreamSize(outSize); do { const UInt64 startPos = _processedSize; const HRESULT res = CodeSpec(_outBuf, kBufSize); const size_t processed = (size_t)(_processedSize - startPos); RINOK(WriteStream(outStream, _outBuf, processed)) RINOK(res) if (_status == kStatus_Finished_With_Mark) break; if (progress) { const UInt64 inProcessed = _inStream.GetProcessed(); RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize)) } } while (!_outSizeDefined || _processedSize < _outSize); if (FinishStream && inSize && *inSize != _inStream.GetProcessed()) return S_FALSE; return S_OK; } Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; _processedSize = 0; _status = kStatus_NeedInit; _res = SZ_OK; return S_OK; } Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) { FinishStream = (finishMode != 0); return S_OK; } Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value)) { *value = _inStream.GetProcessed(); return S_OK; } #ifndef Z7_NO_READ_FROM_CODER Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream)) { InSeqStream = inStream; _inStream.Stream = inStream; return S_OK; } Z7_COM7F_IMF(CDecoder::ReleaseInStream()) { InSeqStream.Release(); return S_OK; } Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { const UInt64 startPos = _processedSize; const HRESULT res = CodeSpec((Byte *)data, size); if (processedSize) *processedSize = (UInt32)(_processedSize - startPos); return res; } #endif }} tmp41wklro_/CPP/7zip/Compress/PpmdDecoder.h0000444000175000001440000000375614410562320021616 0ustar nabijaczleweliusers// PpmdDecoder.h #ifndef ZIP7_INC_COMPRESS_PPMD_DECODER_H #define ZIP7_INC_COMPRESS_PPMD_DECODER_H #include "../../../C/Ppmd7.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../Common/CWrappers.h" namespace NCompress { namespace NPpmd { class CDecoder Z7_final: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, #ifndef Z7_NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(ICompressCoder) Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2) Z7_COM_QI_ENTRY(ICompressSetFinishMode) Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize) #ifndef Z7_NO_READ_FROM_CODER Z7_COM_QI_ENTRY(ICompressSetInStream) Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) Z7_COM_QI_ENTRY(ISequentialInStream) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressCoder) Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) Z7_IFACE_COM7_IMP(ICompressSetFinishMode) Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize) #ifndef Z7_NO_READ_FROM_CODER Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) Z7_IFACE_COM7_IMP(ICompressSetInStream) Z7_IFACE_COM7_IMP(ISequentialInStream) #else Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize)); #endif Byte *_outBuf; CByteInBufWrap _inStream; CPpmd7 _ppmd; Byte _order; bool FinishStream; bool _outSizeDefined; HRESULT _res; int _status; UInt64 _outSize; UInt64 _processedSize; HRESULT CodeSpec(Byte *memStream, UInt32 size); public: #ifndef Z7_NO_READ_FROM_CODER CMyComPtr InSeqStream; #endif CDecoder(): _outBuf(NULL), FinishStream(false), _outSizeDefined(false) { Ppmd7_Construct(&_ppmd); _ppmd.rc.dec.Stream = &_inStream.vt; } ~CDecoder(); }; }} #endif tmp41wklro_/CPP/7zip/Compress/PpmdEncoder.cpp0000444000175000001440000001172614410562320022157 0ustar nabijaczleweliusers// PpmdEncoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/StreamUtils.h" #include "PpmdEncoder.h" namespace NCompress { namespace NPpmd { static const UInt32 kBufSize = (1 << 20); static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 }; void CEncProps::Normalize(int level) { if (level < 0) level = 5; if (level > 9) level = 9; if (MemSize == (UInt32)(Int32)-1) MemSize = (UInt32)1 << (level + 19); const unsigned kMult = 16; if (MemSize / kMult > ReduceSize) { for (unsigned i = 16; i < 32; i++) { UInt32 m = (UInt32)1 << i; if (ReduceSize <= m / kMult) { if (MemSize > m) MemSize = m; break; } } } if (Order == -1) Order = kOrders[(unsigned)level]; } CEncoder::CEncoder(): _inBuf(NULL) { _props.Normalize(-1); Ppmd7_Construct(&_ppmd); _ppmd.rc.enc.Stream = &_outStream.vt; } CEncoder::~CEncoder() { ::MidFree(_inBuf); Ppmd7_Free(&_ppmd, &g_BigAlloc); } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { int level = -1; CEncProps props; for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; const PROPID propID = propIDs[i]; if (propID > NCoderPropID::kReduceSize) continue; if (propID == NCoderPropID::kReduceSize) { if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) props.ReduceSize = (UInt32)prop.uhVal.QuadPart; continue; } if (propID == NCoderPropID::kUsedMemorySize) { // here we have selected (4 GiB - 1 KiB) as replacement for (4 GiB) MEM_SIZE. const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10); UInt32 v; if (prop.vt == VT_UI8) { // 21.03 : we support 64-bit values (for 4 GiB value) const UInt64 v64 = prop.uhVal.QuadPart; if (v64 > ((UInt64)1 << 32)) return E_INVALIDARG; if (v64 == ((UInt64)1 << 32)) v = kPpmd_Default_4g; else v = (UInt32)v64; } else if (prop.vt == VT_UI4) v = (UInt32)prop.ulVal; else return E_INVALIDARG; if (v > PPMD7_MAX_MEM_SIZE) v = kPpmd_Default_4g; /* here we restrict MEM_SIZE for Encoder. It's for better performance of encoding and decoding. The Decoder still supports more MEM_SIZE values. */ if (v < ((UInt32)1 << 16) || (v & 3) != 0) return E_INVALIDARG; // if (v < PPMD7_MIN_MEM_SIZE) return E_INVALIDARG; // (1 << 11) /* Supported MEM_SIZE range : [ (1 << 11) , 0xFFFFFFFF - 12 * 3 ] - current 7-Zip's Ppmd7 constants [ 1824 , 0xFFFFFFFF ] - real limits of Ppmd7 code */ props.MemSize = v; continue; } if (prop.vt != VT_UI4) return E_INVALIDARG; const UInt32 v = (UInt32)prop.ulVal; switch (propID) { case NCoderPropID::kOrder: if (v < 2 || v > 32) return E_INVALIDARG; props.Order = (Byte)v; break; case NCoderPropID::kNumThreads: break; case NCoderPropID::kLevel: level = (int)v; break; default: return E_INVALIDARG; } } props.Normalize(level); _props = props; return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { const UInt32 kPropSize = 5; Byte props[kPropSize]; props[0] = (Byte)_props.Order; SetUi32(props + 1, _props.MemSize) return WriteStream(outStream, props, kPropSize); } Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)) { if (!_inBuf) { _inBuf = (Byte *)::MidAlloc(kBufSize); if (!_inBuf) return E_OUTOFMEMORY; } if (!_outStream.Alloc(1 << 20)) return E_OUTOFMEMORY; if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc)) return E_OUTOFMEMORY; _outStream.Stream = outStream; _outStream.Init(); Ppmd7z_Init_RangeEnc(&_ppmd); Ppmd7_Init(&_ppmd, (unsigned)_props.Order); UInt64 processed = 0; for (;;) { UInt32 size; RINOK(inStream->Read(_inBuf, kBufSize, &size)) if (size == 0) { // We don't write EndMark in PPMD-7z. // Ppmd7z_EncodeSymbol(&_ppmd, -1); Ppmd7z_Flush_RangeEnc(&_ppmd); return _outStream.Flush(); } const Byte *buf = _inBuf; const Byte *lim = buf + size; /* for (; buf < lim; buf++) { Ppmd7z_EncodeSymbol(&_ppmd, *buf); RINOK(_outStream.Res); } */ Ppmd7z_EncodeSymbols(&_ppmd, buf, lim); RINOK(_outStream.Res) processed += size; if (progress) { const UInt64 outSize = _outStream.GetProcessed(); RINOK(progress->SetRatioInfo(&processed, &outSize)) } } } }} tmp41wklro_/CPP/7zip/Compress/PpmdEncoder.h0000444000175000001440000000141314366244420021624 0ustar nabijaczleweliusers// PpmdEncoder.h #ifndef ZIP7_INC_COMPRESS_PPMD_ENCODER_H #define ZIP7_INC_COMPRESS_PPMD_ENCODER_H #include "../../../C/Ppmd7.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../Common/CWrappers.h" namespace NCompress { namespace NPpmd { struct CEncProps { UInt32 MemSize; UInt32 ReduceSize; int Order; CEncProps() { MemSize = (UInt32)(Int32)-1; ReduceSize = (UInt32)(Int32)-1; Order = -1; } void Normalize(int level); }; Z7_CLASS_IMP_COM_3( CEncoder , ICompressCoder , ICompressSetCoderProperties , ICompressWriteCoderProperties ) Byte *_inBuf; CByteOutBufWrap _outStream; CPpmd7 _ppmd; CEncProps _props; public: CEncoder(); ~CEncoder(); }; }} #endif tmp41wklro_/CPP/7zip/Compress/PpmdRegister.cpp0000444000175000001440000000046614365514000022364 0ustar nabijaczleweliusers// PpmdRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "PpmdDecoder.h" #ifndef Z7_EXTRACT_ONLY #include "PpmdEncoder.h" #endif namespace NCompress { namespace NPpmd { REGISTER_CODEC_E(PPMD, CDecoder(), CEncoder(), 0x30401, "PPMD") }} tmp41wklro_/CPP/7zip/Compress/StdAfx.h0000444000175000001440000000035614360505460020620 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/Compress/XzDecoder.cpp0000444000175000001440000000644514567042400021655 0ustar nabijaczleweliusers// XzDecoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/CWrappers.h" #include "XzDecoder.h" namespace NCompress { namespace NXz { #define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; static HRESULT SResToHRESULT_Code(SRes res) throw() { if (res < 0) return res; switch (res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; default: break; } return S_FALSE; } HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) { MainDecodeSRes = SZ_OK; MainDecodeSRes_wasUsed = false; XzStatInfo_Clear(&Stat); if (!xz) { xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc); if (!xz) return E_OUTOFMEMORY; } CXzDecMtProps props; XzDecMtProps_Init(&props); int isMT = False; #ifndef Z7_ST { props.numThreads = 1; const UInt32 numThreads = _numThreads; if (_tryMt && numThreads > 1) { size_t memUsage = (size_t)_memUsage; if (memUsage != _memUsage) memUsage = (size_t)0 - 1; props.memUseMax = memUsage; isMT = (numThreads > 1); } props.numThreads = numThreads; } #endif CSeqInStreamWrap inWrap; CSeqOutStreamWrap outWrap; CCompressProgressWrap progressWrap; inWrap.Init(seqInStream); outWrap.Init(outStream); progressWrap.Init(progress); SRes res = XzDecMt_Decode(xz, &props, outSizeLimit, finishStream, &outWrap.vt, &inWrap.vt, &Stat, &isMT, progress ? &progressWrap.vt : NULL); MainDecodeSRes = res; #ifndef Z7_ST // _tryMt = isMT; #endif RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) // return E_OUTOFMEMORY; // for debug check MainDecodeSRes_wasUsed = true; if (res == SZ_OK && finishStream) { /* if (inSize && *inSize != Stat.PhySize) res = SZ_ERROR_DATA; */ if (outSizeLimit && *outSizeLimit != outWrap.Processed) res = SZ_ERROR_DATA; } return SResToHRESULT_Code(res); } Z7_COM7F_IMF(CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) { return Decode(inStream, outStream, outSize, _finishStream, progress); } Z7_COM7F_IMF(CComDecoder::SetFinishMode(UInt32 finishMode)) { _finishStream = (finishMode != 0); return S_OK; } Z7_COM7F_IMF(CComDecoder::GetInStreamProcessedSize(UInt64 *value)) { *value = Stat.InSize; return S_OK; } #ifndef Z7_ST Z7_COM7F_IMF(CComDecoder::SetNumberOfThreads(UInt32 numThreads)) { _numThreads = numThreads; return S_OK; } Z7_COM7F_IMF(CComDecoder::SetMemLimit(UInt64 memUsage)) { _memUsage = memUsage; return S_OK; } #endif }} tmp41wklro_/CPP/7zip/Compress/XzDecoder.h0000444000175000001440000000361414366434040021317 0ustar nabijaczleweliusers// XzDecoder.h #ifndef ZIP7_INC_XZ_DECODER_H #define ZIP7_INC_XZ_DECODER_H #include "../../../C/Xz.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NXz { struct CDecoder { CXzDecMtHandle xz; int _tryMt; UInt32 _numThreads; UInt64 _memUsage; SRes MainDecodeSRes; // it's not HRESULT bool MainDecodeSRes_wasUsed; CXzStatInfo Stat; CDecoder(): xz(NULL), _tryMt(True), _numThreads(1), _memUsage((UInt64)(sizeof(size_t)) << 28), MainDecodeSRes(SZ_OK), MainDecodeSRes_wasUsed(false) {} ~CDecoder() { if (xz) XzDecMt_Destroy(xz); } /* Decode() can return S_OK, if there is data after good xz streams, and that data is not new xz stream. check also (Stat.DataAfterEnd) flag */ HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress); }; class CComDecoder Z7_final: public ICompressCoder, public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, #ifndef Z7_ST public ICompressSetCoderMt, public ICompressSetMemLimit, #endif public CMyUnknownImp, public CDecoder { Z7_COM_QI_BEGIN2(ICompressCoder) Z7_COM_QI_ENTRY(ICompressSetFinishMode) Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize) #ifndef Z7_ST Z7_COM_QI_ENTRY(ICompressSetCoderMt) Z7_COM_QI_ENTRY(ICompressSetMemLimit) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressCoder) Z7_IFACE_COM7_IMP(ICompressSetFinishMode) Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize) #ifndef Z7_ST Z7_IFACE_COM7_IMP(ICompressSetCoderMt) Z7_IFACE_COM7_IMP(ICompressSetMemLimit) #endif bool _finishStream; public: CComDecoder(): _finishStream(false) {} }; }} #endif tmp41wklro_/CPP/7zip/Compress/XzEncoder.cpp0000444000175000001440000001327514544576640021703 0ustar nabijaczleweliusers// XzEncoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../../Common/MyString.h" #include "../../Common/StringToInt.h" #include "../Common/CWrappers.h" #include "../Common/StreamUtils.h" #include "XzEncoder.h" namespace NCompress { namespace NLzma2 { HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); } namespace NXz { void CEncoder::InitCoderProps() { XzProps_Init(&xzProps); } CEncoder::CEncoder() { XzProps_Init(&xzProps); _encoder = NULL; _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc); if (!_encoder) throw 1; } CEncoder::~CEncoder() { if (_encoder) XzEnc_Destroy(_encoder); } struct CMethodNamePair { UInt32 Id; const char *Name; }; static const CMethodNamePair g_NamePairs[] = { { XZ_ID_Delta, "Delta" }, { XZ_ID_X86, "BCJ" }, { XZ_ID_PPC, "PPC" }, { XZ_ID_IA64, "IA64" }, { XZ_ID_ARM, "ARM" }, { XZ_ID_ARMT, "ARMT" }, { XZ_ID_SPARC, "SPARC" } // { XZ_ID_LZMA2, "LZMA2" } }; static int FilterIdFromName(const wchar_t *name) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++) { const CMethodNamePair &pair = g_NamePairs[i]; if (StringsAreEqualNoCase_Ascii(name, pair.Name)) return (int)pair.Id; } return -1; } HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes) { unsigned id; switch (checkSizeInBytes) { case 0: id = XZ_CHECK_NO; break; case 4: id = XZ_CHECK_CRC32; break; case 8: id = XZ_CHECK_CRC64; break; case 32: id = XZ_CHECK_SHA256; break; default: return E_INVALIDARG; } xzProps.checkId = id; return S_OK; } HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop) { if (propID == NCoderPropID::kNumThreads) { if (prop.vt != VT_UI4) return E_INVALIDARG; xzProps.numTotalThreads = (int)(prop.ulVal); return S_OK; } if (propID == NCoderPropID::kCheckSize) { if (prop.vt != VT_UI4) return E_INVALIDARG; return SetCheckSize(prop.ulVal); } if (propID == NCoderPropID::kBlockSize2) { if (prop.vt == VT_UI4) xzProps.blockSize = prop.ulVal; else if (prop.vt == VT_UI8) xzProps.blockSize = prop.uhVal.QuadPart; else return E_INVALIDARG; return S_OK; } if (propID == NCoderPropID::kReduceSize) { if (prop.vt == VT_UI8) xzProps.reduceSize = prop.uhVal.QuadPart; else return E_INVALIDARG; return S_OK; } if (propID == NCoderPropID::kFilter) { if (prop.vt == VT_UI4) { const UInt32 id32 = prop.ulVal; if (id32 == XZ_ID_Delta) return E_INVALIDARG; xzProps.filterProps.id = prop.ulVal; } else { if (prop.vt != VT_BSTR) return E_INVALIDARG; const wchar_t *name = prop.bstrVal; const wchar_t *end; UInt32 id32 = ConvertStringToUInt32(name, &end); if (end != name) name = end; else { if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta")) { name += 5; // strlen("Delta"); id32 = XZ_ID_Delta; } else { const int filterId = FilterIdFromName(prop.bstrVal); if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */) return E_INVALIDARG; id32 = (UInt32)(unsigned)filterId; } } if (id32 == XZ_ID_Delta) { const wchar_t c = *name; if (c != '-' && c != ':') return E_INVALIDARG; name++; const UInt32 delta = ConvertStringToUInt32(name, &end); if (end == name || *end != 0 || delta == 0 || delta > 256) return E_INVALIDARG; xzProps.filterProps.delta = delta; } xzProps.filterProps.id = id32; } return S_OK; } return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props); } Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { XzProps_Init(&xzProps); for (UInt32 i = 0; i < numProps; i++) { RINOK(SetCoderProp(propIDs[i], coderProps[i])) } return S_OK; // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps)); } Z7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; const PROPID propID = propIDs[i]; if (propID == NCoderPropID::kExpectedDataSize) if (prop.vt == VT_UI8) XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart); } return S_OK; } #define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)) { CSeqInStreamWrap inWrap; CSeqOutStreamWrap outWrap; CCompressProgressWrap progressWrap; inWrap.Init(inStream); outWrap.Init(outStream); progressWrap.Init(progress); SRes res = XzEnc_SetProps(_encoder, &xzProps); if (res == SZ_OK) res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL); // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL); RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) return SResToHRESULT(res); } }} tmp41wklro_/CPP/7zip/Compress/XzEncoder.h0000444000175000001440000000112314410625440021316 0ustar nabijaczleweliusers// XzEncoder.h #ifndef ZIP7_INC_XZ_ENCODER_H #define ZIP7_INC_XZ_ENCODER_H #include "../../../C/XzEnc.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NXz { Z7_CLASS_IMP_COM_3( CEncoder , ICompressCoder , ICompressSetCoderProperties , ICompressSetCoderPropertiesOpt ) CXzEncHandle _encoder; public: CXzProps xzProps; void InitCoderProps(); HRESULT SetCheckSize(UInt32 checkSizeInBytes); HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop); CEncoder(); ~CEncoder(); }; }} #endif tmp41wklro_/CPP/7zip/Crc.mak0000444000175000001440000000042314523101560016651 0ustar nabijaczleweliusersC_OBJS = $(C_OBJS) \ $O\7zCrc.obj !IF defined(USE_NO_ASM) || defined(USE_C_CRC) || "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" C_OBJS = $(C_OBJS) \ !ELSE ASM_OBJS = $(ASM_OBJS) \ !ENDIF $O\7zCrcOpt.obj tmp41wklro_/CPP/7zip/Crc64.mak0000444000175000001440000000043114523756500017034 0ustar nabijaczleweliusersC_OBJS = $(C_OBJS) \ $O\XzCrc64.obj !IF defined(USE_NO_ASM) || defined(USE_C_CRC64) || "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" C_OBJS = $(C_OBJS) \ !ELSE ASM_OBJS = $(ASM_OBJS) \ !ENDIF $O\XzCrc64Opt.obj tmp41wklro_/CPP/7zip/Crypto/0000700000175000001440000000000014706260545016735 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/Crypto/7zAes.cpp0000444000175000001440000001611414531676040020442 0ustar nabijaczleweliusers// 7zAes.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "../../../C/Sha256.h" #include "../../Common/ComTry.h" #include "../../Common/MyBuffer2.h" #ifndef Z7_ST #include "../../Windows/Synchronization.h" #endif #include "../Common/StreamUtils.h" #include "7zAes.h" #include "MyAes.h" #ifndef Z7_EXTRACT_ONLY #include "RandGen.h" #endif namespace NCrypto { namespace N7z { static const unsigned k_NumCyclesPower_Supported_MAX = 24; bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const { if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) return false; for (unsigned i = 0; i < SaltSize; i++) if (Salt[i] != a.Salt[i]) return false; return (Password == a.Password); } void CKeyInfo::CalcKey() { if (NumCyclesPower == 0x3F) { unsigned pos; for (pos = 0; pos < SaltSize; pos++) Key[pos] = Salt[pos]; for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++) Key[pos++] = Password[i]; for (; pos < kKeySize; pos++) Key[pos] = 0; } else { const unsigned kUnrPow = 6; const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow); const size_t bufSize = 8 + SaltSize + Password.Size(); const size_t unrollSize = bufSize * numUnroll; // MY_ALIGN (16) // CSha256 sha; const size_t shaAllocSize = sizeof(CSha256) + unrollSize + bufSize * 2; CAlignedBuffer1 sha(shaAllocSize); Byte *buf = sha + sizeof(CSha256); memcpy(buf, Salt, SaltSize); memcpy(buf + SaltSize, Password, Password.Size()); memset(buf + bufSize - 8, 0, 8); Sha256_Init((CSha256 *)(void *)(Byte *)sha); { { Byte *dest = buf; for (UInt32 i = 1; i < numUnroll; i++) { dest += bufSize; memcpy(dest, buf, bufSize); } } const UInt32 numRounds = (UInt32)1 << NumCyclesPower; UInt32 r = 0; do { Byte *dest = buf + bufSize - 8; UInt32 i = r; r += numUnroll; do { SetUi32(dest, i) i++; dest += bufSize; // SetUi32(dest, i) i++; dest += bufSize; } while (i < r); Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize); } while (r < numRounds); } /* UInt64 numRounds = (UInt64)1 << NumCyclesPower; do { Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize); for (unsigned i = 0; i < 8; i++) if (++(ctr[i]) != 0) break; } while (--numRounds != 0); */ Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); memset(sha, 0, shaAllocSize); } } bool CKeyInfoCache::GetKey(CKeyInfo &key) { FOR_VECTOR (i, Keys) { const CKeyInfo &cached = Keys[i]; if (key.IsEqualTo(cached)) { for (unsigned j = 0; j < kKeySize; j++) key.Key[j] = cached.Key[j]; if (i != 0) Keys.MoveToFront(i); return true; } } return false; } void CKeyInfoCache::FindAndAdd(const CKeyInfo &key) { FOR_VECTOR (i, Keys) { const CKeyInfo &cached = Keys[i]; if (key.IsEqualTo(cached)) { if (i != 0) Keys.MoveToFront(i); return; } } Add(key); } void CKeyInfoCache::Add(const CKeyInfo &key) { if (Keys.Size() >= Size) Keys.DeleteBack(); Keys.Insert(0, key); } static CKeyInfoCache g_GlobalKeyCache(32); #ifndef Z7_ST static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); #else #define MT_LOCK #endif CBase::CBase(): _cachedKeys(16), _ivSize(0) { for (unsigned i = 0; i < sizeof(_iv); i++) _iv[i] = 0; } void CBase::PrepareKey() { // BCJ2 threads use same password. So we use long lock. MT_LOCK bool finded = false; if (!_cachedKeys.GetKey(_key)) { finded = g_GlobalKeyCache.GetKey(_key); if (!finded) _key.CalcKey(); _cachedKeys.Add(_key); } if (!finded) g_GlobalKeyCache.FindAndAdd(_key); } #ifndef Z7_EXTRACT_ONLY /* Z7_COM7F_IMF(CEncoder::ResetSalt()) { _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); return S_OK; } */ Z7_COM7F_IMF(CEncoder::ResetInitVector()) { for (unsigned i = 0; i < sizeof(_iv); i++) _iv[i] = 0; _ivSize = 16; MY_RAND_GEN(_iv, _ivSize); return S_OK; } Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) { Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)]; unsigned propsSize = 1; props[0] = (Byte)(_key.NumCyclesPower | (_key.SaltSize == 0 ? 0 : (1 << 7)) | (_ivSize == 0 ? 0 : (1 << 6))); if (_key.SaltSize != 0 || _ivSize != 0) { props[1] = (Byte)( ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4) | (_ivSize == 0 ? 0 : _ivSize - 1)); memcpy(props + 2, _key.Salt, _key.SaltSize); propsSize = 2 + _key.SaltSize; memcpy(props + propsSize, _iv, _ivSize); propsSize += _ivSize; } return WriteStream(outStream, props, propsSize); } CEncoder::CEncoder() { // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); // _key.NumCyclesPower = 0x3F; _key.NumCyclesPower = 19; _aesFilter = new CAesCbcEncoder(kKeySize); } #endif CDecoder::CDecoder() { _aesFilter = new CAesCbcDecoder(kKeySize); } Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) { _key.ClearProps(); _ivSize = 0; unsigned i; for (i = 0; i < sizeof(_iv); i++) _iv[i] = 0; if (size == 0) return S_OK; const unsigned b0 = data[0]; _key.NumCyclesPower = b0 & 0x3F; if ((b0 & 0xC0) == 0) return size == 1 ? S_OK : E_INVALIDARG; if (size <= 1) return E_INVALIDARG; const unsigned b1 = data[1]; const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); const unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F); if (size != 2 + saltSize + ivSize) return E_INVALIDARG; _key.SaltSize = saltSize; data += 2; for (i = 0; i < saltSize; i++) _key.Salt[i] = *data++; for (i = 0; i < ivSize; i++) _iv[i] = *data++; return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; } Z7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)) { COM_TRY_BEGIN _key.Password.Wipe(); _key.Password.CopyFrom(data, (size_t)size); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CBaseCoder::Init()) { COM_TRY_BEGIN PrepareKey(); CMyComPtr cp; RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)) if (!cp) return E_FAIL; RINOK(cp->SetKey(_key.Key, kKeySize)) RINOK(cp->SetInitVector(_iv, sizeof(_iv))) return _aesFilter->Init(); COM_TRY_END } Z7_COM7F_IMF2(UInt32, CBaseCoder::Filter(Byte *data, UInt32 size)) { return _aesFilter->Filter(data, size); } }} tmp41wklro_/CPP/7zip/Crypto/7zAes.h0000444000175000001440000000506014424762220020102 0ustar nabijaczleweliusers// 7zAes.h #ifndef ZIP7_INC_CRYPTO_7Z_AES_H #define ZIP7_INC_CRYPTO_7Z_AES_H #include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../ICoder.h" #include "../IPassword.h" namespace NCrypto { namespace N7z { const unsigned kKeySize = 32; const unsigned kSaltSizeMax = 16; const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE; class CKeyInfo { public: unsigned NumCyclesPower; unsigned SaltSize; Byte Salt[kSaltSizeMax]; CByteBuffer Password; Byte Key[kKeySize]; bool IsEqualTo(const CKeyInfo &a) const; void CalcKey(); CKeyInfo() { ClearProps(); } void ClearProps() { NumCyclesPower = 0; SaltSize = 0; for (unsigned i = 0; i < sizeof(Salt); i++) Salt[i] = 0; } void Wipe() { Password.Wipe(); NumCyclesPower = 0; SaltSize = 0; Z7_memset_0_ARRAY(Salt); Z7_memset_0_ARRAY(Key); } #ifdef Z7_CPP_IS_SUPPORTED_default CKeyInfo(const CKeyInfo &) = default; #endif ~CKeyInfo() { Wipe(); } }; class CKeyInfoCache { unsigned Size; CObjectVector Keys; public: CKeyInfoCache(unsigned size): Size(size) {} bool GetKey(CKeyInfo &key); void Add(const CKeyInfo &key); void FindAndAdd(const CKeyInfo &key); }; class CBase { CKeyInfoCache _cachedKeys; protected: CKeyInfo _key; Byte _iv[kIvSizeMax]; unsigned _ivSize; void PrepareKey(); CBase(); }; class CBaseCoder: public ICompressFilter, public ICryptoSetPassword, public CMyUnknownImp, public CBase { Z7_IFACE_COM7_IMP(ICompressFilter) Z7_IFACE_COM7_IMP(ICryptoSetPassword) protected: virtual ~CBaseCoder() {} CMyComPtr _aesFilter; }; #ifndef Z7_EXTRACT_ONLY class CEncoder Z7_final: public CBaseCoder, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector { Z7_COM_UNKNOWN_IMP_4( ICompressFilter, ICryptoSetPassword, ICompressWriteCoderProperties, // ICryptoResetSalt, ICryptoResetInitVector) Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) // Z7_IFACE_COM7_IMP(ICryptoResetSalt) Z7_IFACE_COM7_IMP(ICryptoResetInitVector) public: CEncoder(); }; #endif class CDecoder Z7_final: public CBaseCoder, public ICompressSetDecoderProperties2 { Z7_COM_UNKNOWN_IMP_3( ICompressFilter, ICryptoSetPassword, ICompressSetDecoderProperties2) Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) public: CDecoder(); }; }} #endif tmp41wklro_/CPP/7zip/Crypto/7zAesRegister.cpp0000444000175000001440000000035414350157340022142 0ustar nabijaczleweliusers// 7zAesRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "7zAes.h" namespace NCrypto { namespace N7z { REGISTER_FILTER_E(SzAES, CDecoder, CEncoder, 0x6F10701, "7zAES") }} tmp41wklro_/CPP/7zip/Crypto/MyAes.cpp0000444000175000001440000001440214570314420020457 0ustar nabijaczleweliusers// Crypto/MyAes.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "MyAes.h" namespace NCrypto { static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; CAesCoder::CAesCoder( // bool encodeMode, unsigned keySize // , bool ctrMode ): _keyIsSet(false), // _encodeMode(encodeMode), // _ctrMode(ctrMode), _keySize(keySize), // _ctrPos(0), // _ctrPos =0 will be set in Init() _aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2) { // _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); memset(_iv, 0, AES_BLOCK_SIZE); /* // we can use the following code to test 32-bit overflow case for AES-CTR for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1); _iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF; */ } Z7_COM7F_IMF(CAesCoder::Init()) { _ctrPos = 0; AesCbc_Init(Aes(), _iv); return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL } Z7_COM7F_IMF2(UInt32, CAesCoder::Filter(Byte *data, UInt32 size)) { if (!_keyIsSet) return 0; if (size < AES_BLOCK_SIZE) { if (size == 0) return 0; return AES_BLOCK_SIZE; } size >>= 4; // (data) must be aligned for 16-bytes here _codeFunc(Aes(), data, size); return size << 4; } Z7_COM7F_IMF(CAesCoder::SetKey(const Byte *data, UInt32 size)) { if ((size & 0x7) != 0 || size < 16 || size > 32) return E_INVALIDARG; if (_keySize != 0 && size != _keySize) return E_INVALIDARG; _setKeyFunc(Aes() + 4, data, size); _keyIsSet = true; return S_OK; } Z7_COM7F_IMF(CAesCoder::SetInitVector(const Byte *data, UInt32 size)) { if (size != AES_BLOCK_SIZE) return E_INVALIDARG; memcpy(_iv, data, size); /* we allow SetInitVector() call before SetKey() call. so we ignore possible error in Init() here */ CAesCoder::Init(); // don't call virtual function here !!! return S_OK; } #ifndef Z7_SFX /* Z7_COM7F_IMF(CAesCtrCoder::Init()) { _ctrPos = 0; return CAesCoder::Init(); } */ Z7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size)) { if (!_keyIsSet) return 0; if (size == 0) return 0; if (_ctrPos != 0) { /* Optimized caller will not call here */ const Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS); unsigned num = 0; for (unsigned i = _ctrPos; i != AES_BLOCK_SIZE; i++) { if (num == size) { _ctrPos = i; return num; } data[num++] ^= ctr[i]; } _ctrPos = 0; /* if (num < size) { we can filter more data with _codeFunc(). But it's supposed that the caller can work correctly, even if we do only partial filtering here. So we filter data only for current 16-byte block. } */ /* size -= num; size >>= 4; // (data) must be aligned for 16-bytes here _codeFunc(Aes(), data + num, size); return num + (size << 4); */ return num; } if (size < AES_BLOCK_SIZE) { /* The good optimized caller can call here only in last Filter() call. But we support also non-optimized callers, where another Filter() calls are allowed after this call. */ Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS); memset(ctr, 0, AES_BLOCK_SIZE); memcpy(ctr, data, size); _codeFunc(Aes(), ctr, 1); memcpy(data, ctr, size); _ctrPos = size; return size; } size >>= 4; // (data) must be aligned for 16-bytes here _codeFunc(Aes(), data, size); return size << 4; } #endif // Z7_SFX #ifndef Z7_EXTRACT_ONLY #ifdef MY_CPU_X86_OR_AMD64 #define USE_HW_AES #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__ARM_FEATURE_AES) \ || defined(__ARM_FEATURE_CRYPTO) #define USE_HW_AES #else #if defined(MY_CPU_ARM64) \ || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \ || defined(Z7_MSC_VER_ORIGINAL) #if defined(__ARM_FP) && \ ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ || defined(__GNUC__) && (__GNUC__ >= 6) \ ) \ || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910) #if defined(MY_CPU_ARM64) \ || !defined(Z7_CLANG_VERSION) \ || defined(__ARM_NEON) && \ (Z7_CLANG_VERSION < 170000 || \ Z7_CLANG_VERSION > 170001) #define USE_HW_AES #endif #endif #endif #endif #endif #ifdef USE_HW_AES // #pragma message("=== MyAES.c USE_HW_AES === ") #define SET_AES_FUNC_2(f2) \ if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \ { f = f2; } #ifdef MY_CPU_X86_OR_AMD64 #define SET_AES_FUNC_23(f2, f3) \ SET_AES_FUNC_2(f2) \ if (algo == 3) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) \ { f = f3; } #else // MY_CPU_X86_OR_AMD64 #define SET_AES_FUNC_23(f2, f3) \ SET_AES_FUNC_2(f2) #endif // MY_CPU_X86_OR_AMD64 #else // USE_HW_AES #define SET_AES_FUNC_23(f2, f3) #endif // USE_HW_AES #define SET_AES_FUNCS(c, f0, f1, f2, f3) \ bool c::SetFunctions(UInt32 algo) { \ _codeFunc = f0; if (algo < 1) return true; \ AES_CODE_FUNC f = NULL; \ if (algo == 1) { f = f1; } \ SET_AES_FUNC_23(f2, f3) \ if (f) { _codeFunc = f; return true; } \ return false; } #ifndef Z7_SFX SET_AES_FUNCS( CAesCtrCoder, g_AesCtr_Code, AesCtr_Code, AesCtr_Code_HW, AesCtr_Code_HW_256) #endif SET_AES_FUNCS( CAesCbcEncoder, g_AesCbc_Encode, AesCbc_Encode, AesCbc_Encode_HW, AesCbc_Encode_HW) SET_AES_FUNCS( CAesCbcDecoder, g_AesCbc_Decode, AesCbc_Decode, AesCbc_Decode_HW, AesCbc_Decode_HW_256) Z7_COM7F_IMF(CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { UInt32 algo = 0; for (UInt32 i = 0; i < numProps; i++) { if (propIDs[i] == NCoderPropID::kDefaultProp) { const PROPVARIANT &prop = coderProps[i]; if (prop.vt != VT_UI4) return E_INVALIDARG; if (prop.ulVal > 3) return E_NOTIMPL; algo = prop.ulVal; } } if (!SetFunctions(algo)) return E_NOTIMPL; return S_OK; } #endif // Z7_EXTRACT_ONLY } tmp41wklro_/CPP/7zip/Crypto/MyAes.h0000444000175000001440000000522514412251040020120 0ustar nabijaczleweliusers// Crypto/MyAes.h #ifndef ZIP7_INC_CRYPTO_MY_AES_H #define ZIP7_INC_CRYPTO_MY_AES_H #include "../../../C/Aes.h" #include "../../Common/MyBuffer2.h" #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCrypto { #ifdef Z7_EXTRACT_ONLY #define Z7_IFACEN_IAesCoderSetFunctions(x) #else #define Z7_IFACEN_IAesCoderSetFunctions(x) \ virtual bool SetFunctions(UInt32 algo) x #endif class CAesCoder: public ICompressFilter, public ICryptoProperties, #ifndef Z7_EXTRACT_ONLY public ICompressSetCoderProperties, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(ICompressFilter) Z7_COM_QI_ENTRY(ICryptoProperties) #ifndef Z7_EXTRACT_ONLY Z7_COM_QI_ENTRY(ICompressSetCoderProperties) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE public: Z7_IFACE_COM7_IMP_NONFINAL(ICompressFilter) Z7_IFACE_COM7_IMP(ICryptoProperties) private: #ifndef Z7_EXTRACT_ONLY Z7_IFACE_COM7_IMP(ICompressSetCoderProperties) #endif protected: bool _keyIsSet; // bool _encodeMode; // bool _ctrMode; // unsigned _offset; unsigned _keySize; unsigned _ctrPos; // we need _ctrPos here for Init() / SetInitVector() AES_CODE_FUNC _codeFunc; AES_SET_KEY_FUNC _setKeyFunc; private: // UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; CAlignedBuffer1 _aes; Byte _iv[AES_BLOCK_SIZE]; // UInt32 *Aes() { return _aes + _offset; } protected: UInt32 *Aes() { return (UInt32 *)(void *)(Byte *)_aes; } Z7_IFACE_PURE(IAesCoderSetFunctions) public: CAesCoder( // bool encodeMode, unsigned keySize // , bool ctrMode ); virtual ~CAesCoder() {} // we need virtual destructor for derived classes void SetKeySize(unsigned size) { _keySize = size; } }; #ifndef Z7_EXTRACT_ONLY struct CAesCbcEncoder: public CAesCoder { CAesCbcEncoder(unsigned keySize = 0): CAesCoder(keySize) { _setKeyFunc = Aes_SetKey_Enc; _codeFunc = g_AesCbc_Encode; } Z7_IFACE_IMP(IAesCoderSetFunctions) }; #endif struct CAesCbcDecoder: public CAesCoder { CAesCbcDecoder(unsigned keySize = 0): CAesCoder(keySize) { _setKeyFunc = Aes_SetKey_Dec; _codeFunc = g_AesCbc_Decode; } Z7_IFACE_IMP(IAesCoderSetFunctions) }; #ifndef Z7_SFX struct CAesCtrCoder: public CAesCoder { private: // unsigned _ctrPos; // Z7_IFACE_COM7_IMP(ICompressFilter) // Z7_COM7F_IMP(Init()) Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) public: CAesCtrCoder(unsigned keySize = 0): CAesCoder(keySize) { _ctrPos = 0; _setKeyFunc = Aes_SetKey_Enc; _codeFunc = g_AesCtr_Code; } Z7_IFACE_IMP(IAesCoderSetFunctions) }; #endif } #endif tmp41wklro_/CPP/7zip/Crypto/MyAesReg.cpp0000444000175000001440000000122314412251040021103 0ustar nabijaczleweliusers// MyAesReg.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "MyAes.h" namespace NCrypto { #ifndef Z7_SFX #define REGISTER_AES_2(name, nameString, keySize) \ REGISTER_FILTER_E(name, \ CAesCbcDecoder(keySize), \ CAesCbcEncoder(keySize), \ 0x6F00100 | ((keySize - 16) * 8) | (/* isCtr */ 0 ? 4 : 1), \ nameString) \ #define REGISTER_AES(name, nameString) \ /* REGISTER_AES_2(AES128 ## name, "AES128" nameString, 16) */ \ /* REGISTER_AES_2(AES192 ## name, "AES192" nameString, 24) */ \ REGISTER_AES_2(AES256 ## name, "AES256" nameString, 32) \ REGISTER_AES(CBC, "CBC") #endif } tmp41wklro_/CPP/7zip/Crypto/RandGen.cpp0000444000175000001440000001151614407401630020761 0ustar nabijaczleweliusers// RandGen.cpp #include "StdAfx.h" #include "RandGen.h" #ifndef USE_STATIC_SYSTEM_RAND #ifndef Z7_ST #include "../../Windows/Synchronization.h" #endif #ifdef _WIN32 #ifdef _WIN64 #define USE_STATIC_RtlGenRandom #endif #ifdef USE_STATIC_RtlGenRandom // #include EXTERN_C_BEGIN #ifndef RtlGenRandom #define RtlGenRandom SystemFunction036 BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); #endif EXTERN_C_END #else EXTERN_C_BEGIN typedef BOOLEAN (WINAPI * Func_RtlGenRandom)(PVOID RandomBuffer, ULONG RandomBufferLength); EXTERN_C_END #endif #else #include #include #include #include #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include #ifdef USE_POSIX_TIME2 #include #endif #endif // The seed and first generated data block depend from processID, // theadID, timer and system random generator, if available. // Other generated data blocks depend from previous state #define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x)); void CRandomGenerator::Init() { MY_ALIGN (16) CSha256 hash; Sha256_Init(&hash); unsigned numIterations = 1000; { #ifndef UNDER_CE const unsigned kNumIterations_Small = 100; const unsigned kBufSize = 32; MY_ALIGN (16) Byte buf[kBufSize]; #endif #ifdef _WIN32 DWORD w = ::GetCurrentProcessId(); HASH_UPD(w) w = ::GetCurrentThreadId(); HASH_UPD(w) #ifdef UNDER_CE /* if (CeGenRandom(kBufSize, buf)) { numIterations = kNumIterations_Small; Sha256_Update(&hash, buf, kBufSize); } */ #elif defined(USE_STATIC_RtlGenRandom) if (RtlGenRandom(buf, kBufSize)) { numIterations = kNumIterations_Small; Sha256_Update(&hash, buf, kBufSize); } #else { const HMODULE hModule = ::LoadLibrary(TEXT("advapi32.dll")); if (hModule) { // SystemFunction036() is real name of RtlGenRandom() function const Func_RtlGenRandom my_RtlGenRandom = Z7_GET_PROC_ADDRESS( Func_RtlGenRandom, hModule, "SystemFunction036"); if (my_RtlGenRandom) { if (my_RtlGenRandom(buf, kBufSize)) { numIterations = kNumIterations_Small; Sha256_Update(&hash, buf, kBufSize); } } ::FreeLibrary(hModule); } } #endif #else pid_t pid = getpid(); HASH_UPD(pid) pid = getppid(); HASH_UPD(pid) { int f = open("/dev/urandom", O_RDONLY); unsigned numBytes = kBufSize; if (f >= 0) { do { ssize_t n = read(f, buf, numBytes); if (n <= 0) break; Sha256_Update(&hash, buf, (size_t)n); numBytes -= (unsigned)n; } while (numBytes); close(f); if (numBytes == 0) numIterations = kNumIterations_Small; } } /* { int n = getrandom(buf, kBufSize, 0); if (n > 0) { Sha256_Update(&hash, buf, n); if (n == kBufSize) numIterations = kNumIterations_Small; } } */ #endif } #ifdef _DEBUG numIterations = 2; #endif do { #ifdef _WIN32 LARGE_INTEGER v; if (::QueryPerformanceCounter(&v)) HASH_UPD(v.QuadPart) #endif #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, NULL) == 0) { HASH_UPD(v.tv_sec) HASH_UPD(v.tv_usec) } #endif const time_t v2 = time(NULL); HASH_UPD(v2) #endif #ifdef _WIN32 const DWORD tickCount = ::GetTickCount(); HASH_UPD(tickCount) #endif for (unsigned j = 0; j < 100; j++) { Sha256_Final(&hash, _buff); Sha256_Init(&hash); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); } } while (--numIterations); Sha256_Final(&hash, _buff); _needInit = false; } #ifndef Z7_ST static NWindows::NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif void CRandomGenerator::Generate(Byte *data, unsigned size) { MT_LOCK if (_needInit) Init(); while (size != 0) { MY_ALIGN (16) CSha256 hash; Sha256_Init(&hash); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); Sha256_Final(&hash, _buff); Sha256_Init(&hash); UInt32 salt = 0xF672ABD1; HASH_UPD(salt) Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); MY_ALIGN (16) Byte buff[SHA256_DIGEST_SIZE]; Sha256_Final(&hash, buff); for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--) *data++ = buff[i]; } } MY_ALIGN (16) CRandomGenerator g_RandomGenerator; #endif tmp41wklro_/CPP/7zip/Crypto/RandGen.h0000444000175000001440000000135714415320040020422 0ustar nabijaczleweliusers// RandGen.h #ifndef ZIP7_INC_CRYPTO_RAND_GEN_H #define ZIP7_INC_CRYPTO_RAND_GEN_H #include "../../../C/Sha256.h" #ifdef _WIN64 // #define USE_STATIC_SYSTEM_RAND #endif #ifdef USE_STATIC_SYSTEM_RAND #ifdef _WIN32 #include #define MY_RAND_GEN(data, size) RtlGenRandom(data, size) #else #define MY_RAND_GEN(data, size) getrandom(data, size, 0) #endif #else class CRandomGenerator { Byte _buff[SHA256_DIGEST_SIZE]; bool _needInit; void Init(); public: CRandomGenerator(): _needInit(true) {} void Generate(Byte *data, unsigned size); }; MY_ALIGN (16) extern CRandomGenerator g_RandomGenerator; #define MY_RAND_GEN(data, size) g_RandomGenerator.Generate(data, size) #endif #endif tmp41wklro_/CPP/7zip/Crypto/StdAfx.h0000444000175000001440000000035614360505460020305 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/GuiCommon.rc0000444000175000001440000000662514575350020017711 0ustar nabijaczleweliusers#include // #include // #include // for Windows CE: #include LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #undef m #undef bxs #undef bys #undef bxsDots #undef y #undef xc #undef yc #undef xs #undef ys #undef bx #undef bx1 #undef bx2 #undef bx3 #undef by #undef by1 #undef by2 #undef by3 #undef gSpace #undef gSize #undef marg2 #undef marg3 #undef MY_DIALOG #undef MY_RESIZE_DIALOG #undef MY_PAGE #define m 8 #define bxs 64 #define bys 16 #define bxsDots 20 #define xs (xc + m + m) #define ys (yc + m + m) #define bx1 (xs - m - bxs) #define bx2 (bx1 - m - bxs) #define bx3 (bx2 - m - bxs) #define bx bx1 #define by1 (ys - m - bys) #define by2 (by1 - m - bys) #define by by1 #define MY_MODAL_DIALOG_STYLE STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU #define MY_MODAL_RESIZE_DIALOG_STYLE MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME #define MY_PAGE_STYLE STYLE WS_CHILD | WS_DISABLED | WS_CAPTION #define MY_FONT FONT 8, "MS Shell Dlg" #define MY_MODAL_DIALOG_POSTFIX 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT #define SMALL_PAGE_SIZE_X 120 // #define MY_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT // #define MY_RESIZE_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT #define MY_PAGE_POSTFIX 0, 0, xs, ys MY_PAGE_STYLE MY_FONT #define MY_PAGE DIALOG MY_PAGE_POSTFIX #define OK_CANCEL \ DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys #define CONTINUE_CANCEL \ DEFPUSHBUTTON "Continue",IDCONTINUE, bx2, by, bxs, bys \ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys #define MY_BUTTON__CLOSE \ DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys #define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP #define MY_COMBO_SORTED MY_COMBO | CBS_SORT #define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP #define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP #define cboxColonSize 18 #define colonString ":" #define MY_CONTROL_CHECKBOX(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_CHECKBOX, _x,_y,_xsize,10 #define MY_CONTROL_CHECKBOX_2LINES(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_CHECKBOX | BS_MULTILINE, _x,_y,_xsize,16 #define MY_CONTROL_CHECKBOX_COLON(_id,_x,_y) MY_CONTROL_CHECKBOX( colonString, _id, _x,_y,cboxColonSize) #define MY_AUTORADIOBUTTON "Button", BS_AUTORADIOBUTTON #define MY_AUTORADIOBUTTON_GROUP MY_AUTORADIOBUTTON | WS_GROUP #define MY_CONTROL_AUTORADIOBUTTON(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_AUTORADIOBUTTON, _x,_y,_xsize,10 #define MY_CONTROL_AUTORADIOBUTTON_GROUP(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_AUTORADIOBUTTON_GROUP, _x,_y,_xsize,10 #define MY_TEXT_NOPREFIX 8, SS_NOPREFIX // WS_EX_CLIENTEDGE #define MY_CONTROL_EDIT_WITH_SPIN(_id_edit, _id_spin, _text, _x, _y, _xSize) \ EDITTEXT _id_edit, _x, _y, _xSize, 12, ES_CENTER | ES_NUMBER | ES_AUTOHSCROLL \ CONTROL _text, _id_spin, L"msctls_updown32", \ UDS_SETBUDDYINT \ | UDS_ALIGNRIGHT \ | UDS_AUTOBUDDY \ | UDS_ARROWKEYS \ | UDS_NOTHOUSANDS, \ _x + _xSize, _y, 8, 12 // these values are unused #define OPTIONS_PAGE_XC_SIZE 280 #define OPTIONS_PAGE_YC_SIZE 280 tmp41wklro_/CPP/7zip/Guid.txt0000444000175000001440000001125314576475540017130 0ustar nabijaczleweliusers{23170F69-40C1-278A-0000-00yy00xx0000} 00 IProgress.h 05 IProgress // 050002 IProgress2 01 IFolderArchive.h // 05 IArchiveFolder // old // 06 IInFolderArchive // old 07 IFileExtractCallback.h::IFolderArchiveExtractCallback 08 IFileExtractCallback.h::IFolderArchiveExtractCallback2 // 0A IOutFolderArchive 0B IFolderArchiveUpdateCallback 0C Agent.h::IArchiveFolderInternal 0D IArchiveFolder 0E IInFolderArchive 0F IOutFolderArchive 10 IFolderArchiveUpdateCallback2 11 IFolderScanProgress 12 IFolderSetZoneIdMode 20 IFileExtractCallback.h::IGetProp 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old) 31 IFileExtractCallback.h::IFolderExtractToStreamCallback (new 21.04) 03 IStream.h 01 ISequentialInStream 02 ISequentialOutStream 03 IInStream 04 IOutStream 06 IStreamGetSize 07 IOutStreamFinish 08 IStreamGetProps 09 IStreamGetProps2 0A IStreamGetProp 10 IStreamSetRestriction 04 ICoder.h 04 ICompressProgressInfo 05 ICompressCoder 18 ICompressCoder2 1F ICompressSetCoderPropertiesOpt 20 ICompressSetCoderProperties 21 ICompressSetDecoderProperties // 22 ICompressSetDecoderProperties2 23 ICompressWriteCoderProperties 24 ICompressGetInStreamProcessedSize 25 ICompressSetCoderMt 26 ICompressSetFinishMode 27 ICompressGetInStreamProcessedSize2 28 ICompressSetMemLimit 29 ICompressReadUnusedFromInBuf 30 ICompressGetSubStreamSize 31 ICompressSetInStream 32 ICompressSetOutStream // 33 ICompressSetInStreamSize 34 ICompressSetOutStreamSize 35 ICompressSetBufSize 36 ICompressInitEncoder 37 ICompressSetInStream2 // 38 ICompressSetOutStream2 // 39 SetInStreamSize2 // 3A SetOutStreamSize2 40 ICompressFilter 60 ICompressCodecsInfo 61 ISetCompressCodecsInfo 80 ICryptoProperties 88 ICryptoResetSalt 8C ICryptoResetInitVector 90 ICryptoSetPassword A0 ICryptoSetCRC C0 IHasher C1 IHashers 05 IPassword.h 10 ICryptoGetTextPassword 11 ICryptoGetTextPassword2 06 IArchive.h 03 ISetProperties 04 IArchiveKeepModeForNextOpen 05 IArchiveAllowTail 09 IArchiveRequestMemoryUseCallback 10 IArchiveOpenCallback 20 IArchiveExtractCallback 21 IArchiveExtractCallbackMessage (deprecated in v23) 22 IArchiveExtractCallbackMessage2 (new in v23) 30 IArchiveOpenVolumeCallback 40 IInArchiveGetStream 50 IArchiveOpenSetSubArchiveName 60 IInArchive 61 IArchiveOpenSeq 70 IArchiveGetRawProps 71 IArchiveGetRootProps 80 IArchiveUpdateCallback 82 IArchiveUpdateCallback2 83 IArchiveUpdateCallbackFile 84 IArchiveGetDiskProperty 85 IArchiveUpdateCallbackArcProp (Reserved) A0 IOutArchive 08 IFolder.h 00 IFolderFolder 01 IEnumProperties 02 IFolderGetTypeID 03 IFolderGetPath 04 IFolderWasChanged 05 // IFolderReload 06 // IFolderOperations old 07 IFolderGetSystemIconIndex 08 IFolderGetItemFullSize 09 IFolderClone 0A IFolderSetFlatMode 0B IFolderOperationsExtractCallback 0C // 0D // 0E IFolderProperties 0F 10 IFolderArcProps 11 IGetFolderArcProps 12 // IFolderOperations 13 IFolderOperations 14 IFolderCalcItemFullSize 15 IFolderCompare 16 IFolderGetItemName 17 IFolderAltStreams 09 IFolder.h :: FOLDER_MANAGER_INTERFACE 00 - 04 // old IFolderManager 05 IFolderManager // 0A PluginInterface.h 00 IInitContextMenu 01 IPluginOptionsCallback 02 IPluginOptions Handler GUIDs: {23170F69-40C1-278A-1000-000110xx0000} 01 Zip 02 BZip2 03 Rar 04 Arj 05 Z 06 Lzh 07 7z 08 Cab 09 Nsis 0A lzma 0B lzma86 0C xz 0D ppmd 0E zstd BF LVM C0 AVB C1 LP C2 Sparse C3 APFS C4 Vhdx C5 Base64 C6 COFF C7 Ext C8 VMDK C9 VDI CA Qcow CB GPT CC Rar5 CD IHex CE Hxs CF TE D0 UEFIc D1 UEFIs D2 SquashFS D3 CramFS D4 APM D5 Mslz D6 Flv D7 Swf D8 Swfc D9 Ntfs DA Fat DB Mbr DC Vhd DD Pe DE Elf DF Mach-O E0 Udf E1 Xar E2 Mub E3 Hfs E4 Dmg E5 Compound E6 Wim E7 Iso E8 E9 Chm EA Split EB Rpm EC Deb ED Cpio EE Tar EF GZip {23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu // {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler // {23170F69-40C1-278B- old codecs clsids // {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions {23170F69-40C1-2790-id} Codec Decoders {23170F69-40C1-2791-id} Codec Encoders {23170F69-40C1-2792-id} Hashers tmp41wklro_/CPP/7zip/ICoder.h0000444000175000001440000004240214413514040016770 0ustar nabijaczleweliusers// ICoder.h #ifndef ZIP7_INC_ICODER_H #define ZIP7_INC_ICODER_H #include "IStream.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACE_CONSTR_CODER(i, n) \ Z7_DECL_IFACE_7ZIP(i, 4, n) \ { Z7_IFACE_COM7_PURE(i) }; #define Z7_IFACEM_ICompressProgressInfo(x) \ x(SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) Z7_IFACE_CONSTR_CODER(ICompressProgressInfo, 0x04) /* SetRatioInfo() (inSize) can be NULL, if unknown (outSize) can be NULL, if unknown returns: S_OK E_ABORT : Break by user another error codes */ #define Z7_IFACEM_ICompressCoder(x) \ x(Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, \ const UInt64 *inSize, const UInt64 *outSize, \ ICompressProgressInfo *progress)) Z7_IFACE_CONSTR_CODER(ICompressCoder, 0x05) #define Z7_IFACEM_ICompressCoder2(x) \ x(Code(ISequentialInStream * const *inStreams, const UInt64 *const *inSizes, UInt32 numInStreams, \ ISequentialOutStream *const *outStreams, const UInt64 *const *outSizes, UInt32 numOutStreams, \ ICompressProgressInfo *progress)) Z7_IFACE_CONSTR_CODER(ICompressCoder2, 0x18) /* ICompressCoder::Code ICompressCoder2::Code returns: S_OK : OK S_FALSE : data error (for decoders) E_OUTOFMEMORY : memory allocation error E_NOTIMPL : unsupported encoding method (for decoders) another error code : some error. For example, it can be error code received from inStream or outStream function. Parameters: (inStream != NULL) (outStream != NULL) if (inSize != NULL) { Encoders in 7-Zip ignore (inSize). Decoder can use (*inSize) to check that stream was decoded correctly. Some decoders in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode) } If it's required to limit the reading from input stream (inStream), it can be done with ISequentialInStream implementation. if (outSize != NULL) { Encoders in 7-Zip ignore (outSize). Decoder unpacks no more than (*outSize) bytes. } (progress == NULL) is allowed. Decoding with Code() function ----------------------------- You can request some interfaces before decoding - ICompressSetDecoderProperties2 - ICompressSetFinishMode If you need to decode full stream: { 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1); 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known. } If you need to decode only part of stream: { 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0); 2) Call the Code() function with specified (inSize = NULL) and specified (outSize). } Encoding with Code() function ----------------------------- You can request some interfaces : - ICompressSetCoderProperties - use it before encoding to set properties - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties. ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1) The rules are similar to ICompressCoder rules */ namespace NCoderPropID { enum EEnum { kDefaultProp = 0, kDictionarySize, // VT_UI4 kUsedMemorySize, // VT_UI4 kOrder, // VT_UI4 kBlockSize, // VT_UI4 or VT_UI8 kPosStateBits, // VT_UI4 kLitContextBits, // VT_UI4 kLitPosBits, // VT_UI4 kNumFastBytes, // VT_UI4 kMatchFinder, // VT_BSTR kMatchFinderCycles, // VT_UI4 kNumPasses, // VT_UI4 kAlgorithm, // VT_UI4 kNumThreads, // VT_UI4 kEndMarker, // VT_BOOL kLevel, // VT_UI4 kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed // encoder can use this value to reduce dictionary size and allocate data buffers kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt : // it's estimated size of current data stream // real data size can differ from that size // encoder can use this value to optimize encoder initialization kBlockSize2, // VT_UI4 or VT_UI8 kCheckSize, // VT_UI4 : size of digest in bytes kFilter, // VT_BSTR kMemUse, // VT_UI8 kAffinity, // VT_UI8 kBranchOffset, // VT_UI4 kHashBits, // VT_UI4 /* // kHash3Bits, // VT_UI4 // kHash2Bits, // VT_UI4 // kChainBits, // VT_UI4 kChainSize, // VT_UI4 kNativeLevel, // VT_UI4 kFast, // VT_UI4 kMinMatch, // VT_UI4 The minimum slen is 3 and the maximum is 7. kOverlapLog, // VT_UI4 The minimum ovlog is 0 and the maximum is 9. (default: 6) kRowMatchFinder, // VT_BOOL kLdmEnable, // VT_BOOL // kLdmWindowSizeLog, // VT_UI4 kLdmWindowSize, // VT_UI4 kLdmHashLog, // VT_UI4 The minimum ldmhlog is 6 and the maximum is 26 (default: 20). kLdmMinMatchLength, // VT_UI4 The minimum ldmslen is 4 and the maximum is 4096 (default: 64). kLdmBucketSizeLog, // VT_UI4 The minimum ldmblog is 0 and the maximum is 8 (default: 3). kLdmHashRateLog, // VT_UI4 The default value is wlog - ldmhlog. kWriteUnpackSizeFlag, // VT_BOOL kUsePledged, // VT_BOOL kUseSizeHintPledgedForSmall, // VT_BOOL kUseSizeHintForEach, // VT_BOOL kUseSizeHintGlobal, // VT_BOOL kParamSelectMode, // VT_UI4 // kSearchLog, // VT_UI4 The minimum slog is 1 and the maximum is 26 // kTargetLen, // VT_UI4 The minimum tlen is 0 and the maximum is 999. */ k_NUM_DEFINED }; } #define Z7_IFACEM_ICompressSetCoderPropertiesOpt(x) \ x(SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) Z7_IFACE_CONSTR_CODER(ICompressSetCoderPropertiesOpt, 0x1F) #define Z7_IFACEM_ICompressSetCoderProperties(x) \ x(SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) Z7_IFACE_CONSTR_CODER(ICompressSetCoderProperties, 0x20) /* #define Z7_IFACEM_ICompressSetDecoderProperties(x) \ x(SetDecoderProperties(ISequentialInStream *inStream)) Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties, 0x21) */ #define Z7_IFACEM_ICompressSetDecoderProperties2(x) \ x(SetDecoderProperties2(const Byte *data, UInt32 size)) Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties2, 0x22) /* returns: S_OK E_NOTIMP : unsupported properties E_INVALIDARG : incorrect (or unsupported) properties E_OUTOFMEMORY : memory allocation error */ #define Z7_IFACEM_ICompressWriteCoderProperties(x) \ x(WriteCoderProperties(ISequentialOutStream *outStream)) Z7_IFACE_CONSTR_CODER(ICompressWriteCoderProperties, 0x23) #define Z7_IFACEM_ICompressGetInStreamProcessedSize(x) \ x(GetInStreamProcessedSize(UInt64 *value)) Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize, 0x24) #define Z7_IFACEM_ICompressSetCoderMt(x) \ x(SetNumberOfThreads(UInt32 numThreads)) Z7_IFACE_CONSTR_CODER(ICompressSetCoderMt, 0x25) #define Z7_IFACEM_ICompressSetFinishMode(x) \ x(SetFinishMode(UInt32 finishMode)) Z7_IFACE_CONSTR_CODER(ICompressSetFinishMode, 0x26) /* finishMode: 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined. 1 : full decoding. The stream must be finished at the end of decoding. */ #define Z7_IFACEM_ICompressGetInStreamProcessedSize2(x) \ x(GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)) Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize2, 0x27) #define Z7_IFACEM_ICompressSetMemLimit(x) \ x(SetMemLimit(UInt64 memUsage)) Z7_IFACE_CONSTR_CODER(ICompressSetMemLimit, 0x28) /* ICompressReadUnusedFromInBuf is supported by ICoder object call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...). ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed to read from inStream to internal buffers more data than minimal data required for decoding. So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input data from the internal buffer. in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code(). */ #define Z7_IFACEM_ICompressReadUnusedFromInBuf(x) \ x(ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize)) Z7_IFACE_CONSTR_CODER(ICompressReadUnusedFromInBuf, 0x29) #define Z7_IFACEM_ICompressGetSubStreamSize(x) \ x(GetSubStreamSize(UInt64 subStream, UInt64 *value)) Z7_IFACE_CONSTR_CODER(ICompressGetSubStreamSize, 0x30) /* returns: S_OK : (*value) contains the size or estimated size (can be incorrect size) S_FALSE : size is undefined E_NOTIMP : the feature is not implemented Let's (read_size) is size of data that was already read by ISequentialInStream::Read(). The caller should call GetSubStreamSize() after each Read() and check sizes: if (start_of_subStream + *value < read_size) { // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream: start_of_subStream += *value; subStream++; } */ #define Z7_IFACEM_ICompressSetInStream(x) \ x(SetInStream(ISequentialInStream *inStream)) \ x(ReleaseInStream()) Z7_IFACE_CONSTR_CODER(ICompressSetInStream, 0x31) #define Z7_IFACEM_ICompressSetOutStream(x) \ x(SetOutStream(ISequentialOutStream *outStream)) \ x(ReleaseOutStream()) Z7_IFACE_CONSTR_CODER(ICompressSetOutStream, 0x32) /* #define Z7_IFACEM_ICompressSetInStreamSize(x) \ x(SetInStreamSize(const UInt64 *inSize)) \ Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize, 0x33) */ #define Z7_IFACEM_ICompressSetOutStreamSize(x) \ x(SetOutStreamSize(const UInt64 *outSize)) Z7_IFACE_CONSTR_CODER(ICompressSetOutStreamSize, 0x34) /* That function initializes decoder structures. Call this function only for stream version of decoder. if (outSize == NULL), then output size is unknown if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */ #define Z7_IFACEM_ICompressSetBufSize(x) \ x(SetInBufSize(UInt32 streamIndex, UInt32 size)) \ x(SetOutBufSize(UInt32 streamIndex, UInt32 size)) Z7_IFACE_CONSTR_CODER(ICompressSetBufSize, 0x35) #define Z7_IFACEM_ICompressInitEncoder(x) \ x(InitEncoder()) Z7_IFACE_CONSTR_CODER(ICompressInitEncoder, 0x36) /* That function initializes encoder structures. Call this function only for stream version of encoder. */ #define Z7_IFACEM_ICompressSetInStream2(x) \ x(SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)) \ x(ReleaseInStream2(UInt32 streamIndex)) Z7_IFACE_CONSTR_CODER(ICompressSetInStream2, 0x37) /* #define Z7_IFACEM_ICompressSetOutStream2(x) \ x(SetOutStream2(UInt32 streamIndex, ISequentialOutStream *outStream)) x(ReleaseOutStream2(UInt32 streamIndex)) Z7_IFACE_CONSTR_CODER(ICompressSetOutStream2, 0x38) #define Z7_IFACEM_ICompressSetInStreamSize2(x) \ x(SetInStreamSize2(UInt32 streamIndex, const UInt64 *inSize)) Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize2, 0x39) */ /* #define Z7_IFACEM_ICompressInSubStreams(x) \ x(GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)) Z7_IFACE_CONSTR_CODER(ICompressInSubStreams, 0x3A) #define Z7_IFACEM_ICompressOutSubStreams(x) \ x(GetNextOutSubStream(UInt64 *streamIndexRes, ISequentialOutStream **stream)) Z7_IFACE_CONSTR_CODER(ICompressOutSubStreams, 0x3B) */ /* ICompressFilter Filter(Byte *data, UInt32 size) (size) converts as most as possible bytes required for fast processing. Some filters have (smallest_fast_block). For example, (smallest_fast_block == 16) for AES CBC/CTR filters. If data stream is not finished, caller must call Filter() for larger block: where (size >= smallest_fast_block). if (size >= smallest_fast_block) { The filter can leave some bytes at the end of data without conversion: if there are data alignment reasons or speed reasons. The caller can read additional data from stream and call Filter() again. } If data stream was finished, caller can call Filter() for (size < smallest_fast_block) (data) parameter: Some filters require alignment for any Filter() call: 1) (stream_offset % alignment_size) == (data % alignment_size) 2) (alignment_size == 2^N) where (stream_offset) - is the number of bytes that were already filtered before. The callers of Filter() are required to meet these requirements. (alignment_size) can be different: 16 : for AES filters 4 or 2 : for some branch convert filters 1 : for another filters (alignment_size >= 16) is enough for all current filters of 7-Zip. But the caller can use larger (alignment_size). Recommended alignment for (data) of Filter() call is (alignment_size == 64). Also it's recommended to use aligned value for (size): (size % alignment_size == 0), if it's not last call of Filter() for current stream. returns: (outSize): if (outSize == 0) : Filter have not converted anything. So the caller can stop processing, if data stream was finished. if (outSize <= size) : Filter have converted outSize bytes if (outSize > size) : Filter have not converted anything. and it needs at least outSize bytes to convert one block (it's for crypto block algorithms). */ #define Z7_IFACEM_ICompressFilter(x) \ x(Init()) \ x##2(UInt32, Filter(Byte *data, UInt32 size)) Z7_IFACE_CONSTR_CODER(ICompressFilter, 0x40) #define Z7_IFACEM_ICompressCodecsInfo(x) \ x(GetNumMethods(UInt32 *numMethods)) \ x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \ x(CreateDecoder(UInt32 index, const GUID *iid, void* *coder)) \ x(CreateEncoder(UInt32 index, const GUID *iid, void* *coder)) Z7_IFACE_CONSTR_CODER(ICompressCodecsInfo, 0x60) #define Z7_IFACEM_ISetCompressCodecsInfo(x) \ x(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) Z7_IFACE_CONSTR_CODER(ISetCompressCodecsInfo, 0x61) #define Z7_IFACEM_ICryptoProperties(x) \ x(SetKey(const Byte *data, UInt32 size)) \ x(SetInitVector(const Byte *data, UInt32 size)) Z7_IFACE_CONSTR_CODER(ICryptoProperties, 0x80) /* x(ResetSalt()) Z7_IFACE_CONSTR_CODER(ICryptoResetSalt, 0x88) */ #define Z7_IFACEM_ICryptoResetInitVector(x) \ x(ResetInitVector()) Z7_IFACE_CONSTR_CODER(ICryptoResetInitVector, 0x8C) /* Call ResetInitVector() only for encoding. Call ResetInitVector() before encoding and before WriteCoderProperties(). Crypto encoder can create random IV in that function. */ #define Z7_IFACEM_ICryptoSetPassword(x) \ x(CryptoSetPassword(const Byte *data, UInt32 size)) Z7_IFACE_CONSTR_CODER(ICryptoSetPassword, 0x90) #define Z7_IFACEM_ICryptoSetCRC(x) \ x(CryptoSetCRC(UInt32 crc)) Z7_IFACE_CONSTR_CODER(ICryptoSetCRC, 0xA0) namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kPackStreams, kUnpackStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned, kDigestSize, kIsFilter }; } namespace NModuleInterfaceType { /* virtual destructor in IUnknown: - no : 7-Zip (Windows) - no : 7-Zip (Linux) (v23) in default mode - yes : p7zip - yes : 7-Zip (Linux) before v23 - yes : 7-Zip (Linux) (v23), if Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN is defined */ const UInt32 k_IUnknown_VirtDestructor_No = 0; const UInt32 k_IUnknown_VirtDestructor_Yes = 1; const UInt32 k_IUnknown_VirtDestructor_ThisModule = #if !defined(_WIN32) && defined(Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN) k_IUnknown_VirtDestructor_Yes; #else k_IUnknown_VirtDestructor_No; #endif } namespace NModulePropID { enum EEnum { kInterfaceType, // VT_UI4 kVersion // VT_UI4 }; } #define Z7_IFACEM_IHasher(x) \ x##2(void, Init()) \ x##2(void, Update(const void *data, UInt32 size)) \ x##2(void, Final(Byte *digest)) \ x##2(UInt32, GetDigestSize()) Z7_IFACE_CONSTR_CODER(IHasher, 0xC0) #define Z7_IFACEM_IHashers(x) \ x##2(UInt32, GetNumHashers()) \ x(GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) \ x(CreateHasher(UInt32 index, IHasher **hasher)) Z7_IFACE_CONSTR_CODER(IHashers, 0xC1) extern "C" { typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject); typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject); typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo); typedef HRESULT (WINAPI *Func_GetModuleProp)(PROPID propID, PROPVARIANT *value); } Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/IDecl.h0000444000175000001440000000520614554701240016612 0ustar nabijaczleweliusers// IDecl.h #ifndef ZIP7_INC_IDECL_H #define ZIP7_INC_IDECL_H #include "../Common/Common0.h" #include "../Common/MyUnknown.h" #define k_7zip_GUID_Data1 0x23170F69 #define k_7zip_GUID_Data2 0x40C1 #define k_7zip_GUID_Data3_Common 0x278A #define k_7zip_GUID_Data3_Decoder 0x2790 #define k_7zip_GUID_Data3_Encoder 0x2791 #define k_7zip_GUID_Data3_Hasher 0x2792 #define Z7_DECL_IFACE_7ZIP_SUB(i, _base, groupId, subId) \ Z7_DEFINE_GUID(IID_ ## i, \ k_7zip_GUID_Data1, \ k_7zip_GUID_Data2, \ k_7zip_GUID_Data3_Common, \ 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct Z7_DECLSPEC_NOVTABLE i: public _base #define Z7_DECL_IFACE_7ZIP(i, groupId, subId) \ Z7_DECL_IFACE_7ZIP_SUB(i, IUnknown, groupId, subId) #ifdef COM_DECLSPEC_NOTHROW #define Z7_COMWF_B COM_DECLSPEC_NOTHROW STDMETHODIMP #define Z7_COMWF_B_(t) COM_DECLSPEC_NOTHROW STDMETHODIMP_(t) #else #define Z7_COMWF_B STDMETHODIMP #define Z7_COMWF_B_(t) STDMETHODIMP_(t) #endif #if defined(_MSC_VER) && !defined(COM_DECLSPEC_NOTHROW) #define Z7_COM7F_B __declspec(nothrow) STDMETHODIMP #define Z7_COM7F_B_(t) __declspec(nothrow) STDMETHODIMP_(t) #else #define Z7_COM7F_B Z7_COMWF_B #define Z7_COM7F_B_(t) Z7_COMWF_B_(t) #endif // #define Z7_COM7F_E Z7_noexcept #define Z7_COM7F_E throw() #define Z7_COM7F_EO Z7_COM7F_E Z7_override #define Z7_COM7F_EOF Z7_COM7F_EO Z7_final #define Z7_COM7F_IMF(f) Z7_COM7F_B f Z7_COM7F_E #define Z7_COM7F_IMF2(t, f) Z7_COM7F_B_(t) f Z7_COM7F_E #define Z7_COM7F_PURE(f) virtual Z7_COM7F_IMF(f) =0; #define Z7_COM7F_PURE2(t, f) virtual Z7_COM7F_IMF2(t, f) =0; #define Z7_COM7F_IMP(f) Z7_COM7F_IMF(f) Z7_override Z7_final; #define Z7_COM7F_IMP2(t, f) Z7_COM7F_IMF2(t, f) Z7_override Z7_final; #define Z7_COM7F_IMP_NONFINAL(f) Z7_COM7F_IMF(f) Z7_override; #define Z7_COM7F_IMP_NONFINAL2(t, f) Z7_COM7F_IMF2(t, f) Z7_override; #define Z7_IFACE_PURE(name) Z7_IFACEN_ ## name(=0;) #define Z7_IFACE_IMP(name) Z7_IFACEN_ ## name(Z7_override Z7_final;) #define Z7_IFACE_COM7_PURE(name) Z7_IFACEM_ ## name(Z7_COM7F_PURE) #define Z7_IFACE_COM7_IMP(name) Z7_IFACEM_ ## name(Z7_COM7F_IMP) #define Z7_IFACE_COM7_IMP_NONFINAL(name) Z7_IFACEM_ ## name(Z7_COM7F_IMP_NONFINAL) #define Z7_IFACE_DECL_PURE(name) \ DECLARE_INTERFACE(name) \ { Z7_IFACE_PURE(name) }; #define Z7_IFACE_DECL_PURE_(name, baseiface) \ DECLARE_INTERFACE_(name, baseiface) \ { Z7_IFACE_PURE(name) }; #endif tmp41wklro_/CPP/7zip/IPassword.h0000444000175000001440000000305514407301260017540 0ustar nabijaczleweliusers// IPassword.h #ifndef ZIP7_INC_IPASSWORD_H #define ZIP7_INC_IPASSWORD_H #include "../Common/MyTypes.h" #include "IDecl.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACE_CONSTR_PASSWORD(i, n) \ Z7_DECL_IFACE_7ZIP(i, 5, n) \ { Z7_IFACE_COM7_PURE(i) }; /* How to use output parameter (BSTR *password): in: The caller is required to set BSTR value as NULL (no string). The callee (in 7-Zip code) ignores the input value stored in BSTR variable, out: The callee rewrites BSTR variable (*password) with new allocated string pointer. The caller must free BSTR string with function SysFreeString(); */ #define Z7_IFACEM_ICryptoGetTextPassword(x) \ x(CryptoGetTextPassword(BSTR *password)) Z7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword, 0x10) /* CryptoGetTextPassword2() in: The caller is required to set BSTR value as NULL (no string). The caller is not required to set (*passwordIsDefined) value. out: Return code: != S_OK : error code Return code: S_OK : success if (*passwordIsDefined == 1), the variable (*password) contains password string if (*passwordIsDefined == 0), the password is not defined, but the callee still could set (*password) to some allocated string, for example, as empty string. The caller must free BSTR string with function SysFreeString() */ #define Z7_IFACEM_ICryptoGetTextPassword2(x) \ x(CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)) Z7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword2, 0x11) Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/IProgress.h0000444000175000001440000000060614366524240017552 0ustar nabijaczleweliusers// IProgress.h #ifndef ZIP7_INC_IPROGRESS_H #define ZIP7_INC_IPROGRESS_H #include "../Common/MyTypes.h" #include "IDecl.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACEM_IProgress(x) \ x(SetTotal(UInt64 total)) \ x(SetCompleted(const UInt64 *completeValue)) \ Z7_DECL_IFACE_7ZIP(IProgress, 0, 5) { Z7_IFACE_COM7_PURE(IProgress) }; Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/IStream.h0000444000175000001440000001551214554701240017177 0ustar nabijaczleweliusers// IStream.h #ifndef ZIP7_INC_ISTREAM_H #define ZIP7_INC_ISTREAM_H #include "../Common/Common0.h" #include "../Common/MyTypes.h" #include "../Common/MyWindows.h" #include "IDecl.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACE_CONSTR_STREAM_SUB(i, base, n) \ Z7_DECL_IFACE_7ZIP_SUB(i, base, 3, n) \ { Z7_IFACE_COM7_PURE(i) }; #define Z7_IFACE_CONSTR_STREAM(i, n) \ Z7_IFACE_CONSTR_STREAM_SUB(i, IUnknown, n) /* ISequentialInStream::Read() The requirement for caller: (processedSize != NULL). The callee can allow (processedSize == NULL) for compatibility reasons. if (size == 0), this function returns S_OK and (*processedSize) is set to 0. if (size != 0) { Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size), where (avail_size) is the size of remaining bytes in stream. If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0). You must call Read() in loop, if you need to read exact amount of data. } If seek pointer before Read() call was changed to position past the end of stream: if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0. ERROR CASES: If the function returns error code, then (*processedSize) is size of data written to (data) buffer (it can be data before error or data with errors). The recommended way for callee to work with reading errors: 1) write part of data before error to (data) buffer and return S_OK. 2) return error code for further calls of Read(). */ #define Z7_IFACEM_ISequentialInStream(x) \ x(Read(void *data, UInt32 size, UInt32 *processedSize)) Z7_IFACE_CONSTR_STREAM(ISequentialInStream, 0x01) /* ISequentialOutStream::Write() The requirement for caller: (processedSize != NULL). The callee can allow (processedSize == NULL) for compatibility reasons. if (size != 0) { Partial write is allowed: (*processedSize <= size), but this function must write at least 1 byte: (*processedSize > 0). You must call Write() in loop, if you need to write exact amount of data. } ERROR CASES: If the function returns error code, then (*processedSize) is size of data written from (data) buffer. */ #define Z7_IFACEM_ISequentialOutStream(x) \ x(Write(const void *data, UInt32 size, UInt32 *processedSize)) Z7_IFACE_CONSTR_STREAM(ISequentialOutStream, 0x02) #ifdef _WIN32 #ifdef __HRESULT_FROM_WIN32 #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) #else #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) #endif #else #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY_E_ERROR_NEGATIVE_SEEK #endif /* IInStream::Seek() / IOutStream::Seek() If you seek to position before the beginning of the stream, Seek() function returns error code: Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). or STG_E_INVALIDFUNCTION It is allowed to seek past the end of the stream. if Seek() returns error, then the value of *newPosition is undefined. */ #define Z7_IFACEM_IInStream(x) \ x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) Z7_IFACE_CONSTR_STREAM_SUB(IInStream, ISequentialInStream, 0x03) #define Z7_IFACEM_IOutStream(x) \ x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) \ x(SetSize(UInt64 newSize)) Z7_IFACE_CONSTR_STREAM_SUB(IOutStream, ISequentialOutStream, 0x04) #define Z7_IFACEM_IStreamGetSize(x) \ x(GetSize(UInt64 *size)) Z7_IFACE_CONSTR_STREAM(IStreamGetSize, 0x06) #define Z7_IFACEM_IOutStreamFinish(x) \ x(OutStreamFinish()) Z7_IFACE_CONSTR_STREAM(IOutStreamFinish, 0x07) #define Z7_IFACEM_IStreamGetProps(x) \ x(GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) Z7_IFACE_CONSTR_STREAM(IStreamGetProps, 0x08) struct CStreamFileProps { UInt64 Size; UInt64 VolID; UInt64 FileID_Low; UInt64 FileID_High; UInt32 NumLinks; UInt32 Attrib; FILETIME CTime; FILETIME ATime; FILETIME MTime; }; #define Z7_IFACEM_IStreamGetProps2(x) \ x(GetProps2(CStreamFileProps *props)) Z7_IFACE_CONSTR_STREAM(IStreamGetProps2, 0x09) #define Z7_IFACEM_IStreamGetProp(x) \ x(GetProperty(PROPID propID, PROPVARIANT *value)) \ x(ReloadProps()) Z7_IFACE_CONSTR_STREAM(IStreamGetProp, 0x0a) /* IStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end) It sets region of data in output stream that is restricted. For restricted region it's expected (or allowed) that the caller can write to same region with different calls of Write()/SetSize(). Another regions of output stream will be supposed as non-restricted: - The callee usually doesn't flush the data in restricted region. - The callee usually can flush data from non-restricted region after writing. Actual restiction rules depend also from current stream position. It's recommended to call SetRestriction() just before the Write() call. So the callee can optimize writing and flushing, if that Write() operation is not restricted. Note: Each new call of SetRestriction() sets new restictions, so previous restrction calls has no effect anymore. inputs: (begin > end) is not allowed, and returns E_FAIL; if (begin == end) { No restriction. The caller will call Write() in sequential order. After SetRestriction(begin, begin), but before next call of SetRestriction() { Additional condition: it's expected that current stream seek position is equal to stream size. The callee can make final flushing for any data before current stream seek position. For each Write(size) call: The callee can make final flushing for that new written data. } The pair of values (begin == 0 && end == 0) is recommended to remove write restriction. } if (begin < end) { it means that callee must NOT flush any data in region [begin, end). The caller is allowed to Seek() to that region and rewrite the data in that restriction region. if (end == (UInt64)(Int64)-1) { there is no upper bound for restricted region. So non-restricted region will be [0, begin) in that case } } returns: - if (begin > end) it return ERROR code (E_FAIL) - S_OK : if no errors. - Also the call of SetRestriction() can initiate the flushing of already written data. So it can return the result of that flushing. Note: IOutStream::SetSize() also can change the data. So it's not expected the call IOutStream::SetSize() to region that was written before as unrestricted. */ #define Z7_IFACEM_IStreamSetRestriction(x) \ x(SetRestriction(UInt64 begin, UInt64 end)) \ Z7_IFACE_CONSTR_STREAM(IStreamSetRestriction, 0x10) Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/LzFindOpt.mak0000444000175000001440000000023714060070265020021 0ustar nabijaczleweliusers!IF defined(USE_C_LZFINDOPT) || "$(PLATFORM)" != "x64" C_OBJS = $(C_OBJS) \ $O\LzFindOpt.obj !ELSE ASM_OBJS = $(ASM_OBJS) \ $O\LzFindOpt.obj !ENDIF tmp41wklro_/CPP/7zip/LzmaDec.mak0000444000175000001440000000030414570034600017461 0ustar nabijaczleweliusers!IF "$(PLATFORM)" == "x64" || ("$(PLATFORM)" == "arm64" && !defined(NO_ASM_GNU)) !IFNDEF NO_ASM CFLAGS_C_SPEC = -DZ7_LZMA_DEC_OPT ASM_OBJS = $(ASM_OBJS) \ $O\LzmaDecOpt.obj !ENDIF !ENDIF tmp41wklro_/CPP/7zip/LzmaDec_gcc.mak0000444000175000001440000000026314026714371020307 0ustar nabijaczleweliusersifdef USE_ASM ifdef IS_X64 USE_LZMA_DEC_ASM=1 endif ifdef IS_ARM64 USE_LZMA_DEC_ASM=1 endif endif ifdef USE_LZMA_DEC_ASM LZMA_DEC_OPT_OBJS= $O/LzmaDecOpt.o endif tmp41wklro_/CPP/7zip/MyVersion.h0000444000175000001440000000007212535523407017565 0ustar nabijaczleweliusers#define USE_COPYRIGHT_CR #include "../../C/7zVersion.h" tmp41wklro_/CPP/7zip/MyVersionInfo.rc0000444000175000001440000000007114375140120020544 0ustar nabijaczleweliusers#include "MyVersion.h" #include "../../C/7zVersion.rc" tmp41wklro_/CPP/7zip/PropID.h0000444000175000001440000001032614357314620016771 0ustar nabijaczleweliusers// PropID.h #ifndef ZIP7_INC_7ZIP_PROP_ID_H #define ZIP7_INC_7ZIP_PROP_ID_H #include "../Common/MyTypes.h" enum { kpidNoProperty = 0, kpidMainSubfile, kpidHandlerItemIndex, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidId, kpidShortName, kpidCreatorApp, kpidSectorSize, kpidPosixAttrib, kpidSymLink, kpidError, kpidTotalSize, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName, kpidProvider, kpidNtSecure, kpidIsAltStream, kpidIsAux, kpidIsDeleted, kpidIsTree, kpidSha1, kpidSha256, kpidErrorType, kpidNumErrors, kpidErrorFlags, kpidWarningFlags, kpidWarning, kpidNumStreams, kpidNumAltStreams, kpidAltStreamsSize, kpidVirtualSize, kpidUnpackSize, kpidTotalPhySize, kpidVolumeIndex, kpidSubType, kpidShortComment, kpidCodePage, kpidIsNotArcType, kpidPhySizeCantBeDetected, kpidZerosTailIsAllowed, kpidTailSize, kpidEmbeddedStubSize, kpidNtReparse, kpidHardLink, kpidINode, kpidStreamId, kpidReadOnly, kpidOutName, kpidCopyLink, kpidArcFileName, kpidIsHash, kpidChangeTime, kpidUserId, kpidGroupId, kpidDeviceMajor, kpidDeviceMinor, kpidDevMajor, kpidDevMinor, kpid_NUM_DEFINED, kpidUserDefined = 0x10000 }; extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0; const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1; const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2; const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3; const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4; const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5; const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6; const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7; const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8; const UInt32 kpv_ErrorFlags_DataError = 1 << 9; const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; // const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; /* linux ctime : file metadata was last changed. changing the file modification time counts as a metadata change, so will also have the side effect of updating the ctime. PROPVARIANT for timestamps in 7-Zip: { vt = VT_FILETIME wReserved1: set precision level 0 : base value (backward compatibility value) only filetime is used (7 digits precision). wReserved2 and wReserved3 can contain random data 1 : Unix (1 sec) 2 : DOS (2 sec) 3 : High Precision (1 ns) 16 - 3 : (reserved) = 1 day 16 - 2 : (reserved) = 1 hour 16 - 1 : (reserved) = 1 minute 16 + 0 : 1 sec (0 digits after point) 16 + (1,2,3,4,5,6,7,8,9) : set subsecond precision level : (number of decimal digits after point) 16 + 9 : 1 ns (9 digits after point) wReserved2 = ns % 100 : if (8 or 9 digits pecision) = 0 : if not (8 or 9 digits pecision) wReserved3 = 0; filetime } NOTE: TAR-PAX archives created by GNU TAR don't keep whole information about original level of precision, and timestamp are stored in reduced form, where tail zero digits after point are removed. So 7-Zip can return different precision levels for different items for such TAR archives. */ /* TimePrec returned by IOutArchive::GetFileTimeType() is used only for updating, when we compare MTime timestamp from archive with timestamp from directory. */ #endif tmp41wklro_/CPP/7zip/Sha256.mak0000444000175000001440000000060314021626033017112 0ustar nabijaczleweliusersCOMMON_OBJS = $(COMMON_OBJS) \ $O\Sha256Prepare.obj C_OBJS = $(C_OBJS) \ $O\Sha256.obj !IF defined(USE_C_SHA) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" C_OBJS = $(C_OBJS) \ $O\Sha256Opt.obj !ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" ASM_OBJS = $(ASM_OBJS) \ $O\Sha256Opt.obj !ENDIF tmp41wklro_/CPP/7zip/SubBuild.mak0000444000175000001440000000006010272677234017665 0ustar nabijaczleweliusers cd $(@D) $(MAKE) -nologo $(TARGETS) cd .. tmp41wklro_/CPP/7zip/UI/0000700000175000001440000000000014706260545015772 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/Client7z/0000700000175000001440000000000014706260545017471 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/Client7z/Client7z.cpp0000444000175000001440000006730714574240340021713 0ustar nabijaczleweliusers// Client7z.cpp #include "StdAfx.h" #include #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/Defs.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/NtCheck.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #if 0 // for password request functions: #include "../../UI/Console/UserInputUtils.h" #endif #include "../../IPassword.h" #include "../../../../C/7zVersion.h" #ifdef _WIN32 extern HINSTANCE g_hInstance; HINSTANCE g_hInstance = NULL; #endif Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION // You can find full list of all GUIDs supported by 7-Zip in Guid.txt file. // 7z format GUID: {23170F69-40C1-278A-1000-000110070000} #define DEFINE_GUID_ARC(name, id) Z7_DEFINE_GUID(name, \ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, id, 0x00, 0x00); enum { kId_Zip = 1, kId_BZip2 = 2, kId_7z = 7, kId_Xz = 0xC, kId_Tar = 0xEE, kId_GZip = 0xEF }; // use another id, if you want to support other formats (zip, Xz, ...). // DEFINE_GUID_ARC (CLSID_Format, kId_Zip) // DEFINE_GUID_ARC (CLSID_Format, kId_BZip2) // DEFINE_GUID_ARC (CLSID_Format, kId_Xz) // DEFINE_GUID_ARC (CLSID_Format, kId_Tar) // DEFINE_GUID_ARC (CLSID_Format, kId_GZip) DEFINE_GUID_ARC (CLSID_Format, kId_7z) using namespace NWindows; using namespace NFile; using namespace NDir; #ifdef _WIN32 #define kDllName "7z.dll" #else #define kDllName "7z.so" #endif static const char * const kCopyrightString = "\n" "7-Zip" " (" kDllName " client)" " " MY_VERSION " : " MY_COPYRIGHT_DATE "\n"; static const char * const kHelpString = "Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n" "Examples:\n" " 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " 7zcl.exe l archive.7z : List contents of archive.7z\n" " 7zcl.exe x archive.7z : eXtract files from archive.7z\n"; static void Convert_UString_to_AString(const UString &s, AString &temp) { int codePage = CP_OEMCP; /* int g_CodePage = -1; int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, temp); else */ UnicodeStringToMultiByte2(temp, s, (UINT)codePage); } static FString CmdStringToFString(const char *s) { return us2fs(GetUnicodeString(s)); } static void Print(const char *s) { fputs(s, stdout); } static void Print(const AString &s) { Print(s.Ptr()); } static void Print(const UString &s) { AString as; Convert_UString_to_AString(s, as); Print(as); } static void Print(const wchar_t *s) { Print(UString(s)); } static void PrintNewLine() { Print("\n"); } static void PrintStringLn(const char *s) { Print(s); PrintNewLine(); } static void PrintError(const char *message) { Print("Error: "); PrintNewLine(); Print(message); PrintNewLine(); } static void PrintError(const char *message, const FString &name) { PrintError(message); Print(name); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)) if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t * const kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback Z7_final: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(IArchiveOpenCallback, ICryptoGetTextPassword) public: bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; Z7_COM7F_IMF(CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)) { return S_OK; } Z7_COM7F_IMF(CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)) { return S_OK; } Z7_COM7F_IMF(CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)) { if (!PasswordIsDefined) { // You can ask real password here from user #if 0 RINOK(GetPassword_HRESULT(&g_StdOut, Password)) PasswordIsDefined = true; #else PrintError("Password is not defined"); return E_ABORT; #endif } return StringToBstr(Password, password); } static const char * const kIncorrectCommand = "incorrect command"; ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const char * const kTestingString = "Testing "; static const char * const kExtractingString = "Extracting "; static const char * const kSkippingString = "Skipping "; static const char * const kReadingString = "Reading "; static const char * const kUnsupportedMethod = "Unsupported Method"; static const char * const kCRCFailed = "CRC Failed"; static const char * const kDataError = "Data Error"; static const char * const kUnavailableData = "Unavailable data"; static const char * const kUnexpectedEnd = "Unexpected end of data"; static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; static const char * const kIsNotArc = "Is not archive"; static const char * const kHeadersError = "Headers Error"; struct CArcTime { FILETIME FT; UInt16 Prec; Byte Ns100; bool Def; CArcTime() { Clear(); } void Clear() { FT.dwHighDateTime = FT.dwLowDateTime = 0; Prec = 0; Ns100 = 0; Def = false; } bool IsZero() const { return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0; } int GetNumDigits() const { if (Prec == k_PropVar_TimePrec_Unix || Prec == k_PropVar_TimePrec_DOS) return 0; if (Prec == k_PropVar_TimePrec_HighPrec) return 9; if (Prec == k_PropVar_TimePrec_0) return 7; int digits = (int)Prec - (int)k_PropVar_TimePrec_Base; if (digits < 0) digits = 0; return digits; } void Write_To_FiTime(CFiTime &dest) const { #ifdef _WIN32 dest = FT; #else if (FILETIME_To_timespec(FT, dest)) if ((Prec == k_PropVar_TimePrec_Base + 8 || Prec == k_PropVar_TimePrec_Base + 9) && Ns100 != 0) { dest.tv_nsec += Ns100; } #endif } void Set_From_Prop(const PROPVARIANT &prop) { FT = prop.filetime; unsigned prec = 0; unsigned ns100 = 0; const unsigned prec_Temp = prop.wReserved1; if (prec_Temp != 0 && prec_Temp <= k_PropVar_TimePrec_1ns && prop.wReserved3 == 0) { const unsigned ns100_Temp = prop.wReserved2; if (ns100_Temp < 100) { ns100 = ns100_Temp; prec = prec_Temp; } } Prec = (UInt16)prec; Ns100 = (Byte)ns100; Def = true; } }; class CArchiveExtractCallback Z7_final: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(IArchiveExtractCallback, ICryptoGetTextPassword) Z7_IFACE_COM7_IMP(IProgress) CMyComPtr _archiveHandler; FString _directoryPath; // Output directory UString _filePath; // name inside arcvhive FString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { CArcTime MTime; UInt32 Attrib; bool isDir; bool Attrib_Defined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; public: void Init(IInArchive *archiveHandler, const FString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NName::NormalizeDirPathPrefix(_directoryPath); } Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 /* size */)) { return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)) { return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) { *outStream = NULL; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)) UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)) if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.Attrib_Defined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.Attrib_Defined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)) { _processedFileInfo.MTime.Clear(); // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)) switch (prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime.Set_From_Prop(prop); break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)) UInt64 newFileSize; /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize); } { // Create folders for file int slashPos = _filePath.ReverseFind_PathSepar(); if (slashPos >= 0) CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos))); } FString fullProcessedPath = _directoryPath + us2fs(_filePath); _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { CreateComplexDir(fullProcessedPath); } else { NFind::CFileInfo fi; if (fi.Find(fullProcessedPath)) { if (!DeleteFileAlways(fullProcessedPath)) { PrintError("Cannot delete output file", fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Create_ALWAYS(fullProcessedPath)) { PrintError("Cannot open output file", fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; } switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break; case NArchive::NExtract::NAskMode::kReadExternal: Print(kReadingString); break; default: Print("??? "); break; } Print(_filePath); return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 operationResult)) { switch (operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; Print(" : "); const char *s = NULL; switch (operationResult) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: s = kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: s = kCRCFailed; break; case NArchive::NExtract::NOperationResult::kDataError: s = kDataError; break; case NArchive::NExtract::NOperationResult::kUnavailable: s = kUnavailableData; break; case NArchive::NExtract::NOperationResult::kUnexpectedEnd: s = kUnexpectedEnd; break; case NArchive::NExtract::NOperationResult::kDataAfterEnd: s = kDataAfterEnd; break; case NArchive::NExtract::NOperationResult::kIsNotArc: s = kIsNotArc; break; case NArchive::NExtract::NOperationResult::kHeadersError: s = kHeadersError; break; } if (s) { Print("Error : "); Print(s); } else { char temp[16]; ConvertUInt32ToString((UInt32)operationResult, temp); Print("Error #"); Print(temp); } } } if (_outFileStream) { if (_processedFileInfo.MTime.Def) { CFiTime ft; _processedFileInfo.MTime.Write_To_FiTime(ft); _outFileStreamSpec->SetMTime(&ft); } RINOK(_outFileStreamSpec->Close()) } _outFileStream.Release(); if (_extractMode && _processedFileInfo.Attrib_Defined) SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)) { if (!PasswordIsDefined) { #if 0 // You can ask real password here from user RINOK(GetPassword_HRESULT(&g_StdOut, Password)) PasswordIsDefined = true; #else PrintError("Password is not defined"); return E_ABORT; #endif } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase { UString Path_For_Handler; FString FullPath; // for filesystem CDirItem(const NWindows::NFile::NFind::CFileInfo &fi): CFileInfoBase(fi) {} }; class CArchiveUpdateCallback Z7_final: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IArchiveUpdateCallback) public: CRecordVector VolumesSizes; UString VolName; UString VolExt; FString DirPrefix; const CObjectVector *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; FStringVector FailedFiles; CRecordVector FailedCodes; CArchiveUpdateCallback(): DirItems(NULL), PasswordIsDefined(false), AskPassword(false) {} ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; Z7_COM7F_IMF(CArchiveUpdateCallback::SetTotal(UInt64 /* size */)) { return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)) { return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)) { if (newData) *newData = BoolToInt(true); if (newProperties) *newProperties = BoolToInt(true); if (indexInArchive) *indexInArchive = (UInt32)(Int32)-1; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &di = (*DirItems)[index]; switch (propID) { case kpidPath: prop = di.Path_For_Handler; break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break; case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break; case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break; case kpidAttrib: prop = (UInt32)di.GetWinAttrib(); break; case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { Print("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; Print(name); } Z7_COM7F_IMF(CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)) { RINOK(Finilize()) const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Path_For_Handler); if (dirItem.IsDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); FString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { const DWORD sysError = ::GetLastError(); FailedCodes.Add(HRESULT_FROM_WIN32(sysError)); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // Print(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)) { m_NeedBeClosed = true; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)) { wchar_t temp[16]; ConvertUInt32ToString(index + 1, temp); UString res = temp; while (res.Len() < 2) res.InsertAtFront(L'0'); UString fileName = VolName; fileName.Add_Dot(); fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr streamLoc(streamSpec); if (!streamSpec->Create_NEW(us2fs(fileName))) return GetLastError_noZero_HRESULT(); *volumeStream = streamLoc.Detach(); return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)) { if (!PasswordIsDefined) { if (AskPassword) { #if 0 RINOK(GetPassword_HRESULT(&g_StdOut, Password)) PasswordIsDefined = true; #else PrintError("Password is not defined"); return E_ABORT; #endif } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } // Main function #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; #endif int Z7_CDECL main(int numArgs, const char *args[]) { NT_CHECK #ifdef ENV_HAVE_LOCALE MY_SetLocale(); #endif PrintStringLn(kCopyrightString); if (numArgs < 2) { PrintStringLn(kHelpString); return 0; } FString dllPrefix; #ifdef _WIN32 dllPrefix = NDLL::GetModuleDirPrefix(); #else { AString s (args[0]); int sep = s.ReverseFind_PathSepar(); s.DeleteFrom(sep + 1); dllPrefix = s; } #endif NDLL::CLibrary lib; if (!lib.Load(dllPrefix + FTEXT(kDllName))) { PrintError("Cannot load 7-zip library"); return 1; } #if defined(__clang__) #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" #endif #ifdef _WIN32 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION #endif Func_CreateObject f_CreateObject = Z7_GET_PROC_ADDRESS( Func_CreateObject, lib.Get_HMODULE(), "CreateObject"); if (!f_CreateObject) { PrintError("Cannot get CreateObject"); return 1; } char c = 0; UString password; bool passwordIsDefined = false; CObjectVector params; for (int curCmd = 1; curCmd < numArgs; curCmd++) { AString a(args[curCmd]); if (!a.IsEmpty()) { if (a[0] == '-') { if (!passwordIsDefined && a[1] == 'p') { password = GetUnicodeString(a.Ptr(2)); passwordIsDefined = true; continue; } } else { if (c) { params.Add(CmdStringToFString(a)); continue; } if (a.Len() == 1) { c = (char)MyCharLower_Ascii(a[0]); continue; } } } { PrintError(kIncorrectCommand); return 1; } } if (!c || params.Size() < 1) { PrintError(kIncorrectCommand); return 1; } const FString &archiveName = params[0]; if (c == 'a') { // create archive command if (params.Size() < 2) { PrintError(kIncorrectCommand); return 1; } CObjectVector dirItems; { unsigned i; for (i = 1; i < params.Size(); i++) { const FString &name = params[i]; NFind::CFileInfo fi; if (!fi.Find(name)) { PrintError("Can't find file", name); return 1; } CDirItem di(fi); di.Path_For_Handler = fs2us(name); di.FullPath = name; dirItems.Add(di); } } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create_NEW(archiveName)) { PrintError("can't create archive file"); return 1; } CMyComPtr outArchive; if (f_CreateObject(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Cannot get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); updateCallbackSpec->PasswordIsDefined = passwordIsDefined; updateCallbackSpec->Password = password; /* { const wchar_t *names[] = { L"m", L"s", L"x" }; const unsigned kNumProps = Z7_ARRAY_SIZE(names); NCOM::CPropVariant values[kNumProps] = { L"lzma", false, // solid mode OFF (UInt32)9 // compression level = 9 - ultra }; CMyComPtr setProperties; outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) { PrintError("ISetProperties unsupported"); return 1; } if (setProperties->SetProperties(names, values, kNumProps) != S_OK) { PrintError("SetProperties() error"); return 1; } } */ HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } FOR_VECTOR (i, updateCallbackSpec->FailedFiles) { PrintNewLine(); PrintError("Error for file", updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (params.Size() != 1) { PrintError(kIncorrectCommand); return 1; } bool listCommand; if (c == 'l') listCommand = true; else if (c == 'x') listCommand = false; else { PrintError(kIncorrectCommand); return 1; } CMyComPtr archive; if (f_CreateObject(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Cannot get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Cannot open archive file", archiveName); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = passwordIsDefined; openCallbackSpec->Password = password; const UInt64 scanSize = 1 << 23; if (archive->Open(file, &scanSize, openCallback) != S_OK) { PrintError("Cannot open file as archive", archiveName); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); char s[64]; ConvertPropVariantToShortString(prop, s); Print(s); Print(" "); } { // Get name of file NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); if (prop.vt == VT_BSTR) Print(prop.bstrVal); else if (prop.vt != VT_EMPTY) Print("ERROR!"); } PrintNewLine(); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = passwordIsDefined; extractCallbackSpec->Password = password; /* const wchar_t *names[] = { L"mt", L"mtf" }; const unsigned kNumProps = sizeof(names) / sizeof(names[0]); NCOM::CPropVariant values[kNumProps] = { (UInt32)1, false }; CMyComPtr setProperties; archive->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (setProperties) { if (setProperties->SetProperties(names, values, kNumProps) != S_OK) { PrintError("SetProperties() error"); return 1; } } */ HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } tmp41wklro_/CPP/7zip/UI/Client7z/Client7z.dsp0000444000175000001440000002101214576504560021707 0ustar nabijaczleweliusers# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe" !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\NtCheck.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\TimeUtils.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\Common.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyLinux.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyTypes.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\UniqBlocks.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zVersion.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zWindows.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compiler.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\CpuArch.h # End Source File # End Group # Begin Group "7zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\IDecl.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\IArchive.h # End Source File # End Target # End Project tmp41wklro_/CPP/7zip/UI/Client7z/Client7z.dsw0000444000175000001440000000103307526213504021707 0ustar nabijaczleweliusersMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tmp41wklro_/CPP/7zip/UI/Client7z/makefile0000444000175000001440000000100514576504560021200 0ustar nabijaczleweliusersPROG = 7zcl.exe MY_CONSOLE = 1 CURRENT_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\MyVector.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ !include "../../7zip.mak" tmp41wklro_/CPP/7zip/UI/Client7z/makefile.gcc0000444000175000001440000000155314264253300021726 0ustar nabijaczleweliusersPROG = 7zcl IS_NOT_STANDALONE = 1 # IS_X64 = 1 ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif ifdef IS_MINGW SYS_OBJS = \ $O/resource.o \ else SYS_OBJS = \ $O/MyWindows.o \ $O/TimeUtils.o \ endif LOCAL_FLAGS = \ CURRENT_OBJS = \ $O/Client7z.o \ COMMON_OBJS = \ $O/IntToString.o \ $O/MyString.o \ $O/MyVector.o \ $O/NewHandler.o \ $O/StringConvert.o \ $O/StringToInt.o \ $O/UTFConvert.o \ $O/Wildcard.o \ WIN_OBJS = \ $O/DLL.o \ $O/FileDir.o \ $O/FileFind.o \ $O/FileIO.o \ $O/FileName.o \ $O/PropVariant.o \ $O/PropVariantConv.o \ 7ZIP_COMMON_OBJS = \ $O/FileStreams.o \ OBJS = \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(SYS_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(CURRENT_OBJS) \ include ../../7zip_gcc.mak tmp41wklro_/CPP/7zip/UI/Client7z/resource.rc0000444000175000001440000000012313046055420021640 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip client" , "7zcl") tmp41wklro_/CPP/7zip/UI/Client7z/StdAfx.cpp0000444000175000001440000000004610126330612021357 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/UI/Client7z/StdAfx.h0000444000175000001440000000036114360505460021035 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/UI/Common/0000700000175000001440000000000014706260545017222 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/Common/ArchiveCommandLine.cpp0000444000175000001440000014006414634013460023423 0ustar nabijaczleweliusers// ArchiveCommandLine.cpp #include "StdAfx.h" #undef printf #undef sprintf #ifdef _WIN32 #ifndef UNDER_CE #include #endif #else // for isatty() #include #endif #include #ifdef Z7_LARGE_PAGES #include "../../../../C/Alloc.h" #endif #include "../../../Common/IntToString.h" #include "../../../Common/ListFileUtils.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariantConv.h" #include "../../../Windows/System.h" #ifdef _WIN32 #include "../../../Windows/FileMapping.h" #include "../../../Windows/MemoryLock.h" #include "../../../Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "EnumDirItems.h" #include "Update.h" #include "UpdateAction.h" extern bool g_CaseSensitive; extern bool g_PathTrailReplaceMode; #ifdef Z7_LARGE_PAGES extern bool g_LargePagesMode; bool g_LargePagesMode = false; #endif /* #ifdef ENV_HAVE_LSTAT EXTERN_C_BEGIN extern int global_use_lstat; EXTERN_C_END #endif */ #ifdef UNDER_CE #define MY_IS_TERMINAL(x) false; #else // #define MY_isatty_fileno(x) (isatty(fileno(x))) // #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); static inline bool MY_IS_TERMINAL(FILE *x) { return ( #if defined(_MSC_VER) && (_MSC_VER >= 1400) _isatty(_fileno(x)) #else isatty(fileno(x)) #endif != 0); } #endif using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; static bool StringToUInt32(const wchar_t *s, UInt32 &v) { if (*s == 0) return false; const wchar_t *end; v = ConvertStringToUInt32(s, &end); return *end == 0; } namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kShowTime, kLogLevel, kOutStream, kErrStream, kPercentStream, kYes, kShowDialog, kOverwrite, kArchiveType, kExcludedArcType, kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kAffinity, kSfx, kEmail, kHash, // kHashGenFile, kHashDir, kExtractMemLimit, kStdIn, kStdOut, kLargePages, kListfileCharSet, kConsoleCharSet, kTechMode, kListFields, kListPathSlash, kListTimestampUTC, kPreserveATime, kShareForWrite, kStopAfterOpenError, kCaseSensitive, kArcNameMode, kUseSlashMark, kDisableWildcardParsing, kElimDup, kFullPathMode, kHardLinks, kSymLinks_AllowDangerous, kSymLinks, kNtSecurity, kStoreOwnerId, kStoreOwnerName, kZoneFile, kAltStreams, kReplaceColonForAltStream, kWriteToAltStreamIfColon, kNameTrailReplace, kDeleteAfterCompressing, kSetArcMTime #ifndef Z7_NO_CRYPTO , kPassword #endif }; } static const wchar_t kRecursedIDChar = 'r'; static const char * const kRecursedPostCharSet = "0-"; static const char * const k_ArcNameMode_PostCharSet = "sea"; static const char * const k_Stream_PostCharSet = "012"; static inline EArcNameMode ParseArcNameMode(int postCharIndex) { switch (postCharIndex) { case 1: return k_ArcNameMode_Exact; case 2: return k_ArcNameMode_Add; default: return k_ArcNameMode_Smart; } } namespace NRecursedPostCharIndex { enum EEnum { kWildcardRecursionOnly = 0, kNoRecursion = 1 }; } // static const char #define kImmediateNameID '!' #ifdef _WIN32 #define kMapNameID '#' #endif #define kFileListID '@' static const Byte kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be static const Byte kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be static const char * const kOverwritePostCharSet = "asut"; static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kOverwrite, NExtract::NOverwriteMode::kSkip, NExtract::NOverwriteMode::kRename, NExtract::NOverwriteMode::kRenameExisting }; #define SWFRM_3(t, mu, mi) t, mu, mi, NULL #define SWFRM_1(t) SWFRM_3(t, false, 0) #define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) #define SWFRM_MINUS SWFRM_1(NSwitchType::kMinus) #define SWFRM_STRING SWFRM_1(NSwitchType::kString) #define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) #define SWFRM_STRING_MULT(mi) SWFRM_3(NSwitchType::kString, true, mi) static const CSwitchForm kSwitchForms[] = { { "?", SWFRM_SIMPLE }, { "h", SWFRM_SIMPLE }, { "-help", SWFRM_SIMPLE }, { "ba", SWFRM_SIMPLE }, { "bd", SWFRM_SIMPLE }, { "bt", SWFRM_SIMPLE }, { "bb", SWFRM_STRING_SINGL(0) }, { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, { "y", SWFRM_SIMPLE }, { "ad", SWFRM_SIMPLE }, { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, { "t", SWFRM_STRING_SINGL(1) }, { "stx", SWFRM_STRING_MULT(1) }, { "m", SWFRM_STRING_MULT(1) }, { "o", SWFRM_STRING_SINGL(1) }, { "w", SWFRM_STRING }, { "i", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, { "x", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, { "ai", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, { "ax", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, { "an", SWFRM_SIMPLE }, { "u", SWFRM_STRING_MULT(1) }, { "v", SWFRM_STRING_MULT(1) }, { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, { "stm", SWFRM_STRING }, { "sfx", SWFRM_STRING }, { "seml", SWFRM_STRING_SINGL(0) }, { "scrc", SWFRM_STRING_MULT(0) }, // { "scrf", SWFRM_STRING_SINGL(1) }, { "shd", SWFRM_STRING_SINGL(1) }, { "smemx", SWFRM_STRING }, { "si", SWFRM_STRING }, { "so", SWFRM_SIMPLE }, { "slp", SWFRM_STRING }, { "scs", SWFRM_STRING }, { "scc", SWFRM_STRING }, { "slt", SWFRM_SIMPLE }, { "slf", SWFRM_STRING_SINGL(1) }, { "slsl", SWFRM_MINUS }, { "slmu", SWFRM_MINUS }, { "ssp", SWFRM_SIMPLE }, { "ssw", SWFRM_SIMPLE }, { "sse", SWFRM_SIMPLE }, { "ssc", SWFRM_MINUS }, { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, { "spm", SWFRM_STRING_SINGL(0) }, { "spd", SWFRM_SIMPLE }, { "spe", SWFRM_MINUS }, { "spf", SWFRM_STRING_SINGL(0) }, { "snh", SWFRM_MINUS }, { "snld", SWFRM_MINUS }, { "snl", SWFRM_MINUS }, { "sni", SWFRM_SIMPLE }, { "snoi", SWFRM_MINUS }, { "snon", SWFRM_MINUS }, { "snz", SWFRM_STRING_SINGL(0) }, { "sns", SWFRM_MINUS }, { "snr", SWFRM_SIMPLE }, { "snc", SWFRM_SIMPLE }, { "snt", SWFRM_MINUS }, { "sdel", SWFRM_SIMPLE }, { "stl", SWFRM_SIMPLE } #ifndef Z7_NO_CRYPTO , { "p", SWFRM_STRING } #endif }; static const char * const kUniversalWildcard = "*"; static const unsigned kMinNonSwitchWords = 1; static const unsigned kCommandIndex = 0; // static const char * const kUserErrorMessage = "Incorrect command line"; // static const char * const kCannotFindListFile = "Cannot find listfile"; static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char * const kTerminalOutError = "I won't write compressed data to a terminal"; static const char * const kSameTerminalError = "I won't write data and program's messages to same stream"; static const char * const kEmptyFilePath = "Empty file path"; bool CArcCommand::IsFromExtractGroup() const { switch ((int)CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kExtractFull: return true; default: return false; } } NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const { switch ((int)CommandType) { case NCommandType::kTest: case NCommandType::kExtractFull: return NExtract::NPathMode::kFullPaths; default: return NExtract::NPathMode::kNoPaths; } } bool CArcCommand::IsFromUpdateGroup() const { switch ((int)CommandType) { case NCommandType::kAdd: case NCommandType::kUpdate: case NCommandType::kDelete: case NCommandType::kRename: return true; default: return false; } } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildcardRecursionOnly: return NRecursedType::kWildcardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static const char *g_Commands = "audtexlbih"; static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) { UString s (commandString); s.MakeLower_Ascii(); if (s.Len() == 1) { if (s[0] > 0x7F) return false; int index = FindCharPosInString(g_Commands, (char)s[0]); if (index < 0) return false; command.CommandType = (NCommandType::EEnum)index; return true; } if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n') { command.CommandType = (NCommandType::kRename); return true; } return false; } // ------------------------------------------------------------------ // filenames functions struct CNameOption { bool Include; bool WildcardMatching; Byte MarkMode; NRecursedType::EEnum RecursedType; CNameOption(): Include(true), WildcardMatching(true), MarkMode(NWildcard::kMark_FileOrDir), RecursedType(NRecursedType::kNonRecursed) {} }; static void AddNameToCensor(NWildcard::CCensor &censor, const CNameOption &nop, const UString &name) { bool recursed = false; switch ((int)nop.RecursedType) { case NRecursedType::kWildcardOnlyRecursed: recursed = DoesNameContainWildcard(name); break; case NRecursedType::kRecursed: recursed = true; break; default: break; } NWildcard::CCensorPathProps props; props.Recursive = recursed; props.WildcardMatching = nop.WildcardMatching; props.MarkMode = nop.MarkMode; censor.AddPreItem(nop.Include, name, props); } #ifndef Z7_EXTRACT_ONLY static void AddRenamePair(CObjectVector *renamePairs, const UString &oldName, const UString &newName, NRecursedType::EEnum type, bool wildcardMatching) { CRenamePair &pair = renamePairs->AddNew(); pair.OldName = oldName; pair.NewName = newName; pair.RecursedType = type; pair.WildcardParsing = wildcardMatching; if (!pair.Prepare()) { UString val; val += pair.OldName; val.Add_LF(); val += pair.NewName; val.Add_LF(); if (type == NRecursedType::kRecursed) val += "-r"; else if (type == NRecursedType::kWildcardOnlyRecursed) val += "-r0"; throw CArcCmdLineException("Unsupported rename command:", val); } } #endif static void AddToCensorFromListFile( CObjectVector *renamePairs, NWildcard::CCensor &censor, const CNameOption &nop, LPCWSTR fileName, UInt32 codePage) { UStringVector names; /* if (!NFind::DoesFileExist_FollowLink(us2fs(fileName))) throw CArcCmdLineException(kCannotFindListFile, fileName); */ DWORD lastError = 0; if (!ReadNamesFromListFile2(us2fs(fileName), names, codePage, lastError)) { if (lastError != 0) { UString m; m = "The file operation error for listfile"; m.Add_LF(); m += NError::MyFormatMessage(lastError); throw CArcCmdLineException(m, fileName); } throw CArcCmdLineException(kIncorrectListFile, fileName); } if (renamePairs) { #ifndef Z7_EXTRACT_ONLY if ((names.Size() & 1) != 0) throw CArcCmdLineException(kIncorrectListFile, fileName); for (unsigned i = 0; i < names.Size(); i += 2) { // change type !!!! AddRenamePair(renamePairs, names[i], names[i + 1], nop.RecursedType, nop.WildcardMatching); } #else throw "not implemented"; #endif } else FOR_VECTOR (i, names) AddNameToCensor(censor, nop, names[i]); } static void AddToCensorFromNonSwitchesStrings( CObjectVector *renamePairs, unsigned startIndex, NWildcard::CCensor &censor, const UStringVector &nonSwitchStrings, int stopSwitchIndex, const CNameOption &nop, bool thereAreSwitchIncludes, UInt32 codePage) { // another default if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) { /* for rename command: -i switch sets the mask for archive item reading. if (thereAreSwitchIncludes), { we don't use UniversalWildcard. } also for non-rename command: we set UniversalWildcard, only if there are no nonSwitches. */ // we use default fileds in (CNameOption) for UniversalWildcard. CNameOption nop2; // recursive mode is not important for UniversalWildcard (*) // nop2.RecursedType = nop.RecursedType; // we don't need it /* nop2.RecursedType = NRecursedType::kNonRecursed; nop2.Include = true; nop2.WildcardMatching = true; nop2.MarkMode = NWildcard::kMark_FileOrDir; */ AddNameToCensor(censor, nop2, UString(kUniversalWildcard)); } int oldIndex = -1; if (stopSwitchIndex < 0) stopSwitchIndex = (int)nonSwitchStrings.Size(); for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s.IsEmpty()) throw CArcCmdLineException(kEmptyFilePath); if (i < (unsigned)stopSwitchIndex && s[0] == kFileListID) AddToCensorFromListFile(renamePairs, censor, nop, s.Ptr(1), codePage); else if (renamePairs) { #ifndef Z7_EXTRACT_ONLY if (oldIndex == -1) oldIndex = (int)i; else { // NRecursedType::EEnum type is used for global wildcard (-i! switches) AddRenamePair(renamePairs, nonSwitchStrings[(unsigned)oldIndex], s, NRecursedType::kNonRecursed, nop.WildcardMatching); // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); oldIndex = -1; } #else throw "not implemented"; #endif } else AddNameToCensor(censor, nop, s); } if (oldIndex != -1) { throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[(unsigned)oldIndex]); } } #ifdef _WIN32 struct CEventSetEnd { UString Name; CEventSetEnd(const wchar_t *name): Name(name) {} ~CEventSetEnd() { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0) event.Set(); } }; static const char * const k_IncorrectMapCommand = "Incorrect Map command"; static const char *ParseMapWithPaths( NWildcard::CCensor &censor, const UString &s2, const CNameOption &nop) { UString s (s2); const int pos = s.Find(L':'); if (pos < 0) return k_IncorrectMapCommand; const int pos2 = s.Find(L':', (unsigned)(pos + 1)); if (pos2 < 0) return k_IncorrectMapCommand; CEventSetEnd eventSetEnd((const wchar_t *)s + (unsigned)(pos2 + 1)); s.DeleteFrom((unsigned)pos2); UInt32 size; if (!StringToUInt32(s.Ptr((unsigned)(pos + 1)), size) || size < sizeof(wchar_t) || size > ((UInt32)1 << 31) || size % sizeof(wchar_t) != 0) return "Unsupported Map data size"; s.DeleteFrom((unsigned)pos); CFileMapping map; if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) return "Cannot open mapping"; const LPVOID data = map.Map(FILE_MAP_READ, 0, size); if (!data) return "MapViewOfFile error"; CFileUnmapper unmapper(data); UString name; const wchar_t *p = (const wchar_t *)data; if (*p != 0) // data format marker return "Unsupported Map data"; const UInt32 numChars = size / sizeof(wchar_t); for (UInt32 i = 1; i < numChars; i++) { const wchar_t c = p[i]; if (c == 0) { // MessageBoxW(0, name, L"7-Zip", 0); AddNameToCensor(censor, nop, name); name.Empty(); } else name += c; } if (!name.IsEmpty()) return "Map data error"; return NULL; } #endif static void AddSwitchWildcardsToCensor( NWildcard::CCensor &censor, const UStringVector &strings, const CNameOption &nop, UInt32 codePage) { const char *errorMessage = NULL; unsigned i; for (i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; unsigned pos = 0; if (name.Len() < kSomeCludePostStringMinSize) { errorMessage = "Too short switch"; break; } if (!nop.Include) { if (name.IsEqualTo_Ascii_NoCase("td")) { censor.ExcludeDirItems = true; continue; } if (name.IsEqualTo_Ascii_NoCase("tf")) { censor.ExcludeFileItems = true; continue; } } CNameOption nop2 = nop; bool type_WasUsed = false; bool recursed_WasUsed = false; bool matching_WasUsed = false; bool error = false; for (;;) { wchar_t c = ::MyCharLower_Ascii(name[pos]); if (c == kRecursedIDChar) { if (recursed_WasUsed) { error = true; break; } recursed_WasUsed = true; pos++; c = name[pos]; int index = -1; if (c <= 0x7F) index = FindCharPosInString(kRecursedPostCharSet, (char)c); nop2.RecursedType = GetRecursedTypeFromIndex(index); if (index >= 0) { pos++; continue; } } if (c == 'w') { if (matching_WasUsed) { error = true; break; } matching_WasUsed = true; nop2.WildcardMatching = true; pos++; if (name[pos] == '-') { nop2.WildcardMatching = false; pos++; } } else if (c == 'm') { if (type_WasUsed) { error = true; break; } type_WasUsed = true; pos++; nop2.MarkMode = NWildcard::kMark_StrictFile; c = name[pos]; if (c == '-') { nop2.MarkMode = NWildcard::kMark_FileOrDir; pos++; } else if (c == '2') { nop2.MarkMode = NWildcard::kMark_StrictFile_IfWildcard; pos++; } } else break; } if (error) { errorMessage = "inorrect switch"; break; } if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize) { errorMessage = "Too short switch"; break; } const UString tail = name.Ptr(pos + 1); const wchar_t c = name[pos]; if (c == kImmediateNameID) AddNameToCensor(censor, nop2, tail); else if (c == kFileListID) AddToCensorFromListFile(NULL, censor, nop2, tail, codePage); #ifdef _WIN32 else if (c == kMapNameID) { errorMessage = ParseMapWithPaths(censor, tail, nop2); if (errorMessage) break; } #endif else { errorMessage = "Incorrect wildcard type marker"; break; } } if (i != strings.Size()) throw CArcCmdLineException(errorMessage, strings[i]); } /* static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch (i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } */ static const char * const kUpdatePairStateIDSet = "pqrxyzw"; static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; static const unsigned kNumUpdatePairActions = 4; static const char * const kUpdateIgnoreItselfPostStringID = "-"; static const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (unsigned i = 0; i < command.Len();) { wchar_t c = MyCharLower_Ascii(command[i]); int statePos = FindCharPosInString(kUpdatePairStateIDSet, (char)c); if (c > 0x7F || statePos < 0) { postString = command.Ptr(i); return true; } i++; if (i >= command.Len()) return false; c = command[i]; if (c < '0' || c >= (wchar_t)('0' + kNumUpdatePairActions)) return false; unsigned actionPos = (unsigned)(c - '0'); actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { const char *errorMessage = "incorrect update switch command"; unsigned i; for (i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID)) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) break; if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (postString[0] != kUpdateNewArchivePostCharID) break; CUpdateArchiveCommand uc; UString archivePath = postString.Ptr(1); if (archivePath.IsEmpty()) break; uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } if (i != updatePostStrings.Size()) throw CArcCmdLineException(errorMessage, updatePostStrings[i]); } bool ParseComplexSize(const wchar_t *s, UInt64 &result); static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch ((int)commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::k_ActionSet_Add; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::k_ActionSet_Delete; break; default: defaultActionSet = NUpdateArchive::k_ActionSet_Update; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDir::MyGetTempPath(options.WorkingDir); else options.WorkingDir = us2fs(postString); } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]); if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; FOR_VECTOR (i, sv) { UInt64 size; if (!ParseComplexSize(sv[i], size)) throw CArcCmdLineException("Incorrect volume size:", sv[i]); if (i == sv.Size() - 1 && size == 0) throw CArcCmdLineException("zero size last volume is not allowed"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector &properties) { if (parser[NKey::kProperty].ThereIs) { FOR_VECTOR (i, parser[NKey::kProperty].PostStrings) { CProperty prop; prop.Name = parser[NKey::kProperty].PostStrings[i]; int index = prop.Name.Find(L'='); if (index >= 0) { prop.Value = prop.Name.Ptr((unsigned)(index + 1)); prop.Name.DeleteFrom((unsigned)index); } properties.Add(prop); } } } static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) { if (sw.ThereIs) res = (unsigned)sw.PostCharIndex; } #if defined(_WIN32) && !defined(UNDER_CE) static void PrintHex(UString &s, UInt64 v) { char temp[32]; ConvertUInt64ToHex(v, temp); s += temp; } #endif void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options) { Parse1Log.Empty(); if (!parser.ParseStrings(kSwitchForms, Z7_ARRAY_SIZE(kSwitchForms), commandStrings)) throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; options.YesToAll = parser[NKey::kYes].ThereIs; options.StdInMode = parser[NKey::kStdIn].ThereIs; options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; if (parser[NKey::kListFields].ThereIs) { const UString &s = parser[NKey::kListFields].PostStrings[0]; options.ListFields = GetAnsiString(s); } if (parser[NKey::kListPathSlash].ThereIs) { options.ListPathSeparatorSlash.Val = !parser[NKey::kListPathSlash].WithMinus; options.ListPathSeparatorSlash.Def = true; } if (parser[NKey::kListTimestampUTC].ThereIs) g_Timestamp_Show_UTC = !parser[NKey::kListTimestampUTC].WithMinus; options.TechMode = parser[NKey::kTechMode].ThereIs; options.ShowTime = parser[NKey::kShowTime].ThereIs; if (parser[NKey::kDisablePercents].ThereIs) options.DisablePercents = true; if (parser[NKey::kDisablePercents].ThereIs || options.StdOutMode || !options.IsStdOutTerminal) options.Number_for_Percents = k_OutStream_disabled; if (options.StdOutMode) options.Number_for_Out = k_OutStream_disabled; SetStreamMode(parser[NKey::kOutStream], options.Number_for_Out); SetStreamMode(parser[NKey::kErrStream], options.Number_for_Errors); SetStreamMode(parser[NKey::kPercentStream], options.Number_for_Percents); if (parser[NKey::kLogLevel].ThereIs) { const UString &s = parser[NKey::kLogLevel].PostStrings[0]; if (s.IsEmpty()) options.LogLevel = 1; else { UInt32 v; if (!StringToUInt32(s, v)) throw CArcCmdLineException("Unsupported switch postfix -bb", s); options.LogLevel = (unsigned)v; } } if (parser[NKey::kCaseSensitive].ThereIs) { options.CaseSensitive = g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; options.CaseSensitive_Change = true; } #if defined(_WIN32) && !defined(UNDER_CE) NSecurity::EnablePrivilege_SymLink(); #endif // options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { UInt32 slp = 0; const UString &s = parser[NKey::kLargePages].PostStrings[0]; if (s.IsEmpty()) slp = 1; else if (s != L"-") { if (!StringToUInt32(s, slp)) throw CArcCmdLineException("Unsupported switch postfix for -slp", s); } #ifdef Z7_LARGE_PAGES if (slp > #if defined(_WIN32) && !defined(UNDER_CE) (unsigned)NSecurity::Get_LargePages_RiskLevel() #else 0 #endif ) { #ifdef _WIN32 // change it ! SetLargePageSize(); #endif // note: this process also can inherit that Privilege from parent process g_LargePagesMode = #if defined(_WIN32) && !defined(UNDER_CE) NSecurity::EnablePrivilege_LockMemory(); #else true; #endif } #endif } #ifndef UNDER_CE if (parser[NKey::kAffinity].ThereIs) { const UString &s = parser[NKey::kAffinity].PostStrings[0]; if (!s.IsEmpty()) { AString a; a.SetFromWStr_if_Ascii(s); Parse1Log += "Set process affinity mask: "; bool isError = false; #ifdef _WIN32 UInt64 v = 0; { const char *end; v = ConvertHexStringToUInt64(a, &end); if (*end != 0) a.Empty(); } if (a.IsEmpty()) isError = true; else { #ifndef _WIN64 if (v >= ((UInt64)1 << 32)) throw CArcCmdLineException("unsupported value -stm", s); else #endif { PrintHex(Parse1Log, v); if (!SetProcessAffinityMask(GetCurrentProcess(), (DWORD_PTR)v)) { const DWORD lastError = GetLastError(); Parse1Log += " : ERROR : "; Parse1Log += NError::MyFormatMessage(lastError); } } } #else // _WIN32 if (a.Len() != s.Len()) isError = true; else { Parse1Log += a; NSystem::CProcessAffinity aff; aff.CpuZero(); unsigned cpu = 0; unsigned i = a.Len(); while (i) { unsigned v = (Byte)a[--i]; Z7_PARSE_HEX_DIGIT(v, { isError = true; break; }) for (unsigned mask = 1; mask != 1u << 4; mask <<= 1, cpu++) if (v & mask) aff.CpuSet(cpu); } if (!isError) if (!aff.SetProcAffinity()) { const DWORD lastError = GetLastError(); Parse1Log += " : ERROR : "; Parse1Log += NError::MyFormatMessage(lastError); } } #endif // _WIN32 if (isError) throw CArcCmdLineException("Unsupported switch postfix -stm", s); Parse1Log.Add_LF(); } } #endif } struct CCodePagePair { const char *Name; UInt32 CodePage; }; static const unsigned kNumByteOnlyCodePages = 3; static const CCodePagePair g_CodePagePairs[] = { { "utf-8", CP_UTF8 }, { "win", CP_ACP }, { "dos", CP_OEMCP }, { "utf-16le", Z7_WIN_CP_UTF16 }, { "utf-16be", Z7_WIN_CP_UTF16BE } }; static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex, bool byteOnlyCodePages, Int32 defaultVal) { if (!parser[keyIndex].ThereIs) return defaultVal; UString name (parser[keyIndex].PostStrings.Back()); UInt32 v; if (StringToUInt32(name, v)) if (v < ((UInt32)1 << 16)) return (Int32)v; name.MakeLower_Ascii(); const unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : Z7_ARRAY_SIZE(g_CodePagePairs); for (unsigned i = 0;; i++) { if (i == num) // to disable warnings from different compilers throw CArcCmdLineException("Unsupported charset:", name); const CCodePagePair &pair = g_CodePagePairs[i]; if (name.IsEqualTo(pair.Name)) return (Int32)pair.CodePage; } } static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) { bp.Def = parser[switchID].ThereIs; if (bp.Def) bp.Val = !parser[switchID].WithMinus; } static bool ParseSizeString(const wchar_t *s, UInt64 &res) { const wchar_t *end; const UInt64 v = ConvertStringToUInt64(s, &end); if (s == end) return false; const wchar_t c = *end; if (c == 0) { res = v; return true; } if (end[1] != 0) return false; unsigned numBits; switch (MyCharLower_Ascii(c)) { case 'b': numBits = 0; break; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; default: return false; } const UInt64 val2 = v << numBits; if ((val2 >> numBits) != v) return false; res = val2; return true; } void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; const unsigned numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) throw CArcCmdLineException("The command must be specified"); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); if (parser[NKey::kHash].ThereIs) options.HashMethods = parser[NKey::kHash].PostStrings; /* if (parser[NKey::kHashGenFile].ThereIs) { const UString &s = parser[NKey::kHashGenFile].PostStrings[0]; for (unsigned i = 0 ; i < s.Len();) { const wchar_t c = s[i++]; if (!options.HashOptions.ParseFlagCharOption(c, true)) { if (c != '=') throw CArcCmdLineException("Unsupported hash mode switch:", s); options.HashOptions.HashFilePath = s.Ptr(i); break; } } } */ if (parser[NKey::kHashDir].ThereIs) options.ExtractOptions.HashDir = parser[NKey::kHashDir].PostStrings[0]; if (parser[NKey::kExtractMemLimit].ThereIs) { const UString &s = parser[NKey::kExtractMemLimit].PostStrings[0]; if (!ParseSizeString(s, options.ExtractOptions.NtOptions.MemLimit)) throw CArcCmdLineException("Unsupported -smemx:", s); } if (parser[NKey::kElimDup].ThereIs) { options.ExtractOptions.ElimDup.Def = true; options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; } NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; if (fullPathMode) { censorPathMode = NWildcard::k_AbsPath; const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; if (!s.IsEmpty()) { if (s == L"2") censorPathMode = NWildcard::k_FullPath; else throw CArcCmdLineException("Unsupported -spf:", s); } } if (parser[NKey::kNameTrailReplace].ThereIs) g_PathTrailReplaceMode = !parser[NKey::kNameTrailReplace].WithMinus; CNameOption nop; if (parser[NKey::kRecursed].ThereIs) nop.RecursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); if (parser[NKey::kDisableWildcardParsing].ThereIs) nop.WildcardMatching = false; if (parser[NKey::kUseSlashMark].ThereIs) { const UString &s = parser[NKey::kUseSlashMark].PostStrings[0]; if (s.IsEmpty()) nop.MarkMode = NWildcard::kMark_StrictFile; else if (s.IsEqualTo_Ascii_NoCase("-")) nop.MarkMode = NWildcard::kMark_FileOrDir; else if (s.IsEqualTo_Ascii_NoCase("2")) nop.MarkMode = NWildcard::kMark_StrictFile_IfWildcard; else throw CArcCmdLineException("Unsupported -spm:", s); } options.ConsoleCodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); const UInt32 codePage = (UInt32)FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; nop.Include = true; AddSwitchWildcardsToCensor(options.Censor, parser[NKey::kInclude].PostStrings, nop, codePage); } if (parser[NKey::kExclude].ThereIs) { nop.Include = false; AddSwitchWildcardsToCensor(options.Censor, parser[NKey::kExclude].PostStrings, nop, codePage); } unsigned curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo && options.Command.CommandType != NCommandType::kHash; const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); const bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; const bool isRename = options.Command.CommandType == NCommandType::kRename; if ((isExtractOrList || isRename) && options.StdInMode) thereIsArchiveName = false; if (parser[NKey::kArcNameMode].ThereIs) options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex); if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) throw CArcCmdLineException("Cannot find archive name"); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; if (options.ArchiveName.IsEmpty()) throw CArcCmdLineException("Archive name cannot by empty"); #ifdef _WIN32 // options.ArchiveName.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif } nop.Include = true; AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, curCommandIndex, options.Censor, nonSwitchStrings, parser.StopSwitchIndex, nop, thereAreSwitchIncludes, codePage); #ifndef Z7_NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings; SetMethodOptions(parser, options.Properties); if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId); SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName); CBoolPair symLinks_AllowDangerous; SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); /* bool supportSymLink = options.SymLinks.Val; if (!options.SymLinks.Def) { if (isExtractOrList) supportSymLink = true; else supportSymLink = false; } #ifdef ENV_HAVE_LSTAT if (supportSymLink) global_use_lstat = 1; else global_use_lstat = 0; #endif */ if (isExtractOrList) { CExtractOptionsBase &eo = options.ExtractOptions; eo.ExcludeDirItems = options.Censor.ExcludeDirItems; eo.ExcludeFileItems = options.Censor.ExcludeFileItems; { CExtractNtOptions &nt = eo.NtOptions; nt.NtSecurity = options.NtSecurity; nt.AltStreams = options.AltStreams; if (!options.AltStreams.Def) nt.AltStreams.Val = true; nt.HardLinks = options.HardLinks; if (!options.HardLinks.Def) nt.HardLinks.Val = true; nt.SymLinks = options.SymLinks; if (!options.SymLinks.Def) nt.SymLinks.Val = true; nt.SymLinks_AllowDangerous = symLinks_AllowDangerous; nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; nt.ExtractOwner = options.StoreOwnerId.Val; // StoreOwnerName if (parser[NKey::kPreserveATime].ThereIs) nt.PreserveATime = true; if (parser[NKey::kShareForWrite].ThereIs) nt.OpenShareForWrite = true; } if (parser[NKey::kZoneFile].ThereIs) { eo.ZoneMode = NExtract::NZoneIdMode::kAll; const UString &s = parser[NKey::kZoneFile].PostStrings[0]; if (!s.IsEmpty()) { if (s == L"0") eo.ZoneMode = NExtract::NZoneIdMode::kNone; else if (s == L"1") eo.ZoneMode = NExtract::NZoneIdMode::kAll; else if (s == L"2") eo.ZoneMode = NExtract::NZoneIdMode::kOffice; else throw CArcCmdLineException("Unsupported -snz:", s); } } options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); options.Censor.ExtendExclude(); // are there paths that look as non-relative (!Prefix.IsEmpty()) if (!options.Censor.AllAreRelative()) throw CArcCmdLineException("Cannot use absolute pathnames for this command"); NWildcard::CCensor &arcCensor = options.arcCensor; CNameOption nopArc; // nopArc.RecursedType = NRecursedType::kNonRecursed; // default: we don't want recursing for archives, if -r specified // is it OK, external switches can disable WildcardMatching and MarcMode for arc. nopArc.WildcardMatching = nop.WildcardMatching; nopArc.MarkMode = nop.MarkMode; if (parser[NKey::kArInclude].ThereIs) { nopArc.Include = true; AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, nopArc, codePage); } if (parser[NKey::kArExclude].ThereIs) { nopArc.Include = false; AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, nopArc, codePage); } if (thereIsArchiveName) { nopArc.Include = true; AddNameToCensor(arcCensor, nopArc, options.ArchiveName); } arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); #ifdef _WIN32 ConvertToLongNames(arcCensor); #endif arcCensor.ExtendExclude(); if (options.StdInMode) options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front(); if (isExtractGroupCommand) { if (options.StdOutMode) { if ( options.Number_for_Percents == k_OutStream_stdout // || options.Number_for_Out == k_OutStream_stdout // || options.Number_for_Errors == k_OutStream_stdout || ( (options.IsStdOutTerminal && options.IsStdErrTerminal) && ( options.Number_for_Percents != k_OutStream_disabled // || options.Number_for_Out != k_OutStream_disabled // || options.Number_for_Errors != k_OutStream_disabled ) ) ) throw CArcCmdLineException(kSameTerminalError); } if (parser[NKey::kOutputDir].ThereIs) { eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); #ifdef _WIN32 NFile::NName::NormalizeDirSeparators(eo.OutputDir); #endif NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); } eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; if (parser[NKey::kOverwrite].ThereIs) { eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex]; eo.OverwriteMode_Force = true; } else if (options.YesToAll) { eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; eo.OverwriteMode_Force = true; } } eo.PathMode = options.Command.GetPathMode(); if (censorPathMode == NWildcard::k_AbsPath) { eo.PathMode = NExtract::NPathMode::kAbsPaths; eo.PathMode_Force = true; } else if (censorPathMode == NWildcard::k_FullPath) { eo.PathMode = NExtract::NPathMode::kFullPaths; eo.PathMode_Force = true; } } else if (options.Command.IsFromUpdateGroup()) { if (parser[NKey::kArInclude].ThereIs) throw CArcCmdLineException("-ai switch is not supported for this command"); CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); updateOptions.MethodMode.Properties = options.Properties; if (parser[NKey::kPreserveATime].ThereIs) updateOptions.PreserveATime = true; if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; if (parser[NKey::kStopAfterOpenError].ThereIs) updateOptions.StopAfterOpenError = true; updateOptions.PathMode = censorPathMode; updateOptions.AltStreams = options.AltStreams; updateOptions.NtSecurity = options.NtSecurity; updateOptions.HardLinks = options.HardLinks; updateOptions.SymLinks = options.SymLinks; updateOptions.StoreOwnerId = options.StoreOwnerId; updateOptions.StoreOwnerName = options.StoreOwnerName; updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Len() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs; updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw CArcCmdLineException("stdout mode and email mode cannot be combined"); if (updateOptions.StdOutMode) { if (options.IsStdOutTerminal) throw CArcCmdLineException(kTerminalOutError); if (options.Number_for_Percents == k_OutStream_stdout || options.Number_for_Out == k_OutStream_stdout || options.Number_for_Errors == k_OutStream_stdout) throw CArcCmdLineException(kSameTerminalError); } if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); if (options.Command.CommandType == NCommandType::kRename) if (updateOptions.Commands.Size() != 1) throw CArcCmdLineException("Only one archive can be created with rename command"); } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumIterations = 1; options.NumIterations_Defined = false; if (curCommandIndex < numNonSwitchStrings) { if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) throw CArcCmdLineException("Incorrect number of benchmark iterations", nonSwitchStrings[curCommandIndex]); curCommandIndex++; options.NumIterations_Defined = true; } } else if (options.Command.CommandType == NCommandType::kHash) { options.Censor.AddPathsToCensor(censorPathMode); options.Censor.ExtendExclude(); CHashOptions &hashOptions = options.HashOptions; hashOptions.PathMode = censorPathMode; hashOptions.Methods = options.HashMethods; // hashOptions.HashFilePath = options.HashFilePath; if (parser[NKey::kPreserveATime].ThereIs) hashOptions.PreserveATime = true; if (parser[NKey::kShareForWrite].ThereIs) hashOptions.OpenShareForWrite = true; hashOptions.StdInMode = options.StdInMode; hashOptions.AltStreamsMode = options.AltStreams.Val; hashOptions.SymLinks = options.SymLinks; } else if (options.Command.CommandType == NCommandType::kInfo) { } else throw 20150919; } #ifndef _WIN32 static AString g_ModuleDirPrefix; void Set_ModuleDirPrefix_From_ProgArg0(const char *s); void Set_ModuleDirPrefix_From_ProgArg0(const char *s) { AString a (s); int sep = a.ReverseFind_PathSepar(); a.DeleteFrom((unsigned)(sep + 1)); g_ModuleDirPrefix = a; } namespace NWindows { namespace NDLL { FString GetModuleDirPrefix(); FString GetModuleDirPrefix() { FString s; s = fas2fs(g_ModuleDirPrefix); if (s.IsEmpty()) s = FTEXT(".") FSTRING_PATH_SEPARATOR; return s; /* setenv("_7ZIP_HOME_DIR", "/test/", 0); const char *home = getenv("_7ZIP_HOME_DIR"); if (home) s = home; else s = FTEXT(".") FSTRING_PATH_SEPARATOR; return s; */ } }} #endif // ! _WIN32 tmp41wklro_/CPP/7zip/UI/Common/ArchiveCommandLine.h0000444000175000001440000000647414630241120023066 0ustar nabijaczleweliusers// ArchiveCommandLine.h #ifndef ZIP7_INC_ARCHIVE_COMMAND_LINE_H #define ZIP7_INC_ARCHIVE_COMMAND_LINE_H #include "../../../Common/CommandLineParser.h" #include "../../../Common/Wildcard.h" #include "EnumDirItems.h" #include "Extract.h" #include "HashCalc.h" #include "Update.h" typedef CMessagePathException CArcCmdLineException; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kExtractFull, kList, kBenchmark, kInfo, kHash, kRename };} struct CArcCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestCommand() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; enum { k_OutStream_disabled = 0, k_OutStream_stdout = 1, k_OutStream_stderr = 2 }; struct CArcCmdLineOptions { bool HelpMode; // bool LargePages; bool CaseSensitive_Change; bool CaseSensitive; bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool DisablePercents; bool YesToAll; bool ShowDialog; bool TechMode; bool ShowTime; CBoolPair ListPathSeparatorSlash; CBoolPair NtSecurity; CBoolPair AltStreams; CBoolPair HardLinks; CBoolPair SymLinks; CBoolPair StoreOwnerId; CBoolPair StoreOwnerName; AString ListFields; int ConsoleCodePage; NWildcard::CCensor Censor; CArcCommand Command; UString ArchiveName; #ifndef Z7_NO_CRYPTO bool PasswordEnabled; UString Password; #endif UStringVector HashMethods; // UString HashFilePath; // bool AppendName; // UStringVector ArchivePathsSorted; // UStringVector ArchivePathsFullSorted; NWildcard::CCensor arcCensor; UString ArcName_for_StdInMode; CObjectVector Properties; CExtractOptionsBase ExtractOptions; CUpdateOptions UpdateOptions; CHashOptions HashOptions; UString ArcType; UStringVector ExcludedArcTypes; unsigned Number_for_Out; unsigned Number_for_Errors; unsigned Number_for_Percents; unsigned LogLevel; // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; } // Benchmark UInt32 NumIterations; bool NumIterations_Defined; CArcCmdLineOptions(): HelpMode(false), // LargePages(false), CaseSensitive_Change(false), CaseSensitive(false), IsInTerminal(false), IsStdOutTerminal(false), IsStdErrTerminal(false), StdInMode(false), StdOutMode(false), EnableHeaders(false), DisablePercents(false), YesToAll(false), ShowDialog(false), TechMode(false), ShowTime(false), ConsoleCodePage(-1), Number_for_Out(k_OutStream_stdout), Number_for_Errors(k_OutStream_stderr), Number_for_Percents(k_OutStream_stdout), LogLevel(0) { ListPathSeparatorSlash.Val = #ifdef _WIN32 false; #else true; #endif } }; class CArcCmdLineParser { NCommandLineParser::CParser parser; public: UString Parse1Log; void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); void Parse2(CArcCmdLineOptions &options); }; #endif tmp41wklro_/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp0000444000175000001440000020602614576243000024265 0ustar nabijaczleweliusers// ArchiveExtractCallback.cpp #include "StdAfx.h" #undef sprintf #undef printf // #include // #include "../../../../C/CpuTicks.h" #include "../../../../C/Alloc.h" #include "../../../../C/CpuArch.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) #define Z7_USE_SECURITY_CODE #include "../../../Windows/SecurityUtils.h" #endif #include "../../Common/FilePathAutoRename.h" #include "../../Common/StreamUtils.h" #include "../Common/ExtractingFilePath.h" #include "../Common/PropIDUtils.h" #include "ArchiveExtractCallback.h" using namespace NWindows; using namespace NFile; using namespace NDir; static const char * const kCantAutoRename = "Cannot create file with auto name"; static const char * const kCantRenameFile = "Cannot rename existing file"; static const char * const kCantDeleteOutputFile = "Cannot delete output file"; static const char * const kCantDeleteOutputDir = "Cannot delete output folder"; static const char * const kCantOpenOutFile = "Cannot open output file"; #ifndef Z7_SFX static const char * const kCantOpenInFile = "Cannot open input file"; #endif static const char * const kCantSetFileLen = "Cannot set length for output file"; #ifdef SUPPORT_LINKS static const char * const kCantCreateHardLink = "Cannot create hard link"; static const char * const kCantCreateSymLink = "Cannot create symbolic link"; #endif #ifndef Z7_SFX Z7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)) { HRESULT result = S_OK; if (_stream) result = _stream->Write(data, size, &size); if (_calculate) _hash->Update(data, size); _size += size; if (processedSize) *processedSize = size; return result; } #endif // Z7_SFX #ifdef Z7_USE_SECURITY_CODE bool InitLocalPrivileges(); bool InitLocalPrivileges() { NSecurity::CAccessToken token; if (!token.OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES)) return false; TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) return false; if (!token.AdjustPrivileges(&tp)) return false; return (GetLastError() == ERROR_SUCCESS); } #endif // Z7_USE_SECURITY_CODE #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) static const char * const kOfficeExtensions = " doc dot wbk" " docx docm dotx dotm docb wll wwl" " xls xlt xlm" " xlsx xlsm xltx xltm xlsb xla xlam" " ppt pot pps ppa ppam" " pptx pptm potx potm ppam ppsx ppsm sldx sldm" " "; static bool FindExt2(const char *p, const UString &name) { const int pathPos = name.ReverseFind_PathSepar(); const int dotPos = name.ReverseFind_Dot(); if (dotPos < 0 || dotPos < pathPos || dotPos == (int)name.Len() - 1) return false; AString s; for (unsigned pos = (unsigned)(dotPos + 1);; pos++) { const wchar_t c = name[pos]; if (c <= 0) break; if (c >= 0x80) return false; s.Add_Char((char)MyCharLower_Ascii((char)c)); } for (unsigned i = 0; p[i] != 0;) { unsigned j; for (j = i; p[j] != ' '; j++); if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0) return true; i = j + 1; } return false; } static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf) { FString fileName (fileName2); fileName += k_ZoneId_StreamName; buf.Free(); NIO::CInFile file; if (!file.Open(fileName)) return; UInt64 fileSize; if (!file.GetLength(fileSize)) return; if (fileSize == 0 || fileSize >= ((UInt32)1 << 16)) return; buf.Alloc((size_t)fileSize); size_t processed; if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize) return; buf.Free(); } bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf) { FString path (fileName); path += k_ZoneId_StreamName; NIO::COutFile file; if (!file.Create_ALWAYS(path)) return false; return file.WriteFull(buf, buf.Size()); } #endif #ifdef SUPPORT_LINKS int CHardLinkNode::Compare(const CHardLinkNode &a) const { if (StreamId < a.StreamId) return -1; if (StreamId > a.StreamId) return 1; return MyCompare(INode, a.INode); } static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) { h.INode = 0; h.StreamId = (UInt64)(Int64)-1; defined = false; { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidINode, &prop)) if (!ConvertPropVariantToUInt64(prop, h.INode)) return S_OK; } { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidStreamId, &prop)) ConvertPropVariantToUInt64(prop, h.StreamId); } defined = true; return S_OK; } HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector *realIndices) { _hardLinks.Clear(); if (!_arc->Ask_INode) return S_OK; IInArchive *archive = _arc->Archive; CRecordVector &hardIDs = _hardLinks.IDs; { UInt32 numItems; if (realIndices) numItems = realIndices->Size(); else { RINOK(archive->GetNumberOfItems(&numItems)) } for (UInt32 i = 0; i < numItems; i++) { CHardLinkNode h; bool defined; const UInt32 realIndex = realIndices ? (*realIndices)[i] : i; RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined)) if (defined) { bool isAltStream = false; RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream)) if (!isAltStream) { bool isDir = false; RINOK(Archive_IsItem_Dir(archive, realIndex, isDir)) if (!isDir) hardIDs.Add(h); } } } } hardIDs.Sort2(); { // we keep only items that have 2 or more items unsigned k = 0; unsigned numSame = 1; for (unsigned i = 1; i < hardIDs.Size(); i++) { if (hardIDs[i].Compare(hardIDs[i - 1]) != 0) numSame = 1; else if (++numSame == 2) { if (i - 1 != k) hardIDs[k] = hardIDs[i - 1]; k++; } } hardIDs.DeleteFrom(k); } _hardLinks.PrepareLinks(); return S_OK; } #endif // SUPPORT_LINKS CArchiveExtractCallback::CArchiveExtractCallback(): _arc(NULL), Write_CTime(true), Write_ATime(true), Write_MTime(true), Is_elimPrefix_Mode(false), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; #ifdef Z7_USE_SECURITY_CODE _saclEnabled = InitLocalPrivileges(); #endif } void CArchiveExtractCallback::InitBeforeNewArchive() { #if defined(_WIN32) && !defined(UNDER_CE) ZoneBuf.Free(); #endif } void CArchiveExtractCallback::Init( const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, const FString &directoryPath, const UStringVector &removePathParts, bool removePartsForAltStreams, UInt64 packSize) { ClearExtractedDirsInfo(); _outFileStream.Release(); _bufPtrSeqOutStream.Release(); #ifdef SUPPORT_LINKS _hardLinks.Clear(); #endif #ifdef SUPPORT_ALT_STREAMS _renamedFiles.Clear(); #endif _ntOptions = ntOptions; _wildcardCensor = wildcardCensor; _stdOutMode = stdOutMode; _testMode = testMode; // _progressTotal = 0; // _progressTotal_Defined = false; _packTotal = packSize; _progressTotal = packSize; _progressTotal_Defined = true; _extractCallback2 = extractCallback2; /* _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); _callbackMessage.Release(); _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage); */ _folderArchiveExtractCallback2.Release(); _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); #ifndef Z7_SFX ExtractToStreamCallback.Release(); _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); if (ExtractToStreamCallback) { Int32 useStreams = 0; if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) useStreams = 0; if (useStreams == 0) ExtractToStreamCallback.Release(); } #endif LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _removePathParts = removePathParts; _removePartsForAltStreams = removePartsForAltStreams; #ifndef Z7_SFX _baseParentFolder = (UInt32)(Int32)-1; _use_baseParentFolder_mode = false; #endif _arc = arc; _dirPathPrefix = directoryPath; _dirPathPrefix_Full = directoryPath; #if defined(_WIN32) && !defined(UNDER_CE) if (!NName::IsAltPathPrefix(_dirPathPrefix)) #endif { NName::NormalizeDirPathPrefix(_dirPathPrefix); NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full); NName::NormalizeDirPathPrefix(_dirPathPrefix_Full); } } Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size)) { COM_TRY_BEGIN _progressTotal = size; _progressTotal_Defined = true; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; UInt64 packCur; if (_multiArchives) { packCur = LocalProgressSpec->InSize; if (completeValue && _progressTotal_Defined) packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); completeValue = &packCur; } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { // we use (_item.IsDir) in this function bool isAbsPath = false; if (!dirPathParts.IsEmpty()) { const UString &s = dirPathParts[0]; if (s.IsEmpty()) isAbsPath = true; #if defined(_WIN32) && !defined(UNDER_CE) else { if (NName::IsDrivePath2(s)) isAbsPath = true; } #endif } if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) fullPath.Empty(); else fullPath = _dirPathPrefix; FOR_VECTOR (i, dirPathParts) { if (i != 0) fullPath.Add_PathSepar(); const UString &s = dirPathParts[i]; fullPath += us2fs(s); const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir); if (fullPath.IsEmpty()) { if (isFinalDir) _itemFailure = true; continue; } #if defined(_WIN32) && !defined(UNDER_CE) if (_pathMode == NExtract::NPathMode::kAbsPaths) if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) { if (isFinalDir) { // we don't want to call SetAttrib() for root drive path _itemFailure = true; } continue; } #endif HRESULT hres = S_OK; if (!CreateDir(fullPath)) hres = GetLastError_noZero_HRESULT(); if (isFinalDir) { if (!NFile::NFind::DoesDirExist(fullPath)) { _itemFailure = true; SendMessageError_with_Error(hres, "Cannot create folder", fullPath); } } } } HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, CArcTime &ft) { ft.Clear(); NCOM::CPropVariant prop; RINOK(_arc->Archive->GetProperty(index, propID, &prop)) if (prop.vt == VT_FILETIME) ft.Set_From_Prop(prop); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CArchiveExtractCallback::GetUnpackSize() { return _arc->GetItem_Size(_index, _curSize, _curSize_Defined); } static void AddPathToMessage(UString &s, const FString &path) { s += " : "; s += fs2us(path); } HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) { UString s (message); AddPathToMessage(s, path); return _extractCallback2->MessageError(s); } HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) { UString s (message); if (errorCode != S_OK) { s += " : "; s += NError::MyFormatMessage(errorCode); } AddPathToMessage(s, path); return _extractCallback2->MessageError(s); } HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) { const HRESULT errorCode = GetLastError_noZero_HRESULT(); return SendMessageError_with_Error(errorCode, message, path); } HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) { UString s (message); if (errorCode != 0) { s += " : "; s += NError::MyFormatMessage(errorCode); } AddPathToMessage(s, path1); AddPathToMessage(s, path2); return _extractCallback2->MessageError(s); } #ifndef Z7_SFX Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) { /* if (propID == kpidName) { COM_TRY_BEGIN NCOM::CPropVariant prop = Name; prop.Detach(value); return S_OK; COM_TRY_END } */ return Arc->Archive->GetProperty(IndexInArc, propID, value); } #endif // Z7_SFX #ifdef SUPPORT_LINKS static UString GetDirPrefixOf(const UString &src) { UString s (src); if (!s.IsEmpty()) { if (IsPathSepar(s.Back())) s.DeleteBack(); int pos = s.ReverseFind_PathSepar(); s.DeleteFrom((unsigned)(pos + 1)); } return s; } #endif // SUPPORT_LINKS struct CLinkLevelsInfo { bool IsAbsolute; int LowLevel; int FinalLevel; void Parse(const UString &path); }; void CLinkLevelsInfo::Parse(const UString &path) { IsAbsolute = NName::IsAbsolutePath(path); LowLevel = 0; FinalLevel = 0; UStringVector parts; SplitPathToParts(path, parts); int level = 0; FOR_VECTOR (i, parts) { const UString &s = parts[i]; if (s.IsEmpty()) { if (i == 0) IsAbsolute = true; continue; } if (s == L".") continue; if (s == L"..") { level--; if (LowLevel > level) LowLevel = level; } else level++; } FinalLevel = level; } bool IsSafePath(const UString &path); bool IsSafePath(const UString &path) { CLinkLevelsInfo levelsInfo; levelsInfo.Parse(path); return !levelsInfo.IsAbsolute && levelsInfo.LowLevel >= 0 && levelsInfo.FinalLevel > 0; } bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) { bool found = false; // CheckPathVect() doesn't check path to Parent nodes if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include)) { if (!include) return true; #ifdef SUPPORT_ALT_STREAMS if (!item.IsAltStream) return true; #endif found = true; } #ifdef SUPPORT_ALT_STREAMS if (!item.IsAltStream) return false; UStringVector pathParts2 = item.PathParts; if (pathParts2.IsEmpty()) pathParts2.AddNew(); UString &back = pathParts2.Back(); back.Add_Colon(); back += item.AltStreamName; bool include2; if (node.CheckPathVect(pathParts2, true, // isFile, include2)) { include = include2; return true; } #endif // SUPPORT_ALT_STREAMS return found; } bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item) { bool include; if (CensorNode_CheckPath2(node, item, include)) return include; return false; } static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) { FString s (prefix); #if defined(_WIN32) && !defined(UNDER_CE) if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back())) { if (!NName::IsDriveRootPath_SuperAllowed(prefix)) s.DeleteBack(); } #endif s += path; return s; } #ifdef SUPPORT_LINKS /* struct CTempMidBuffer { void *Buf; CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); } ~CTempMidBuffer() { ::MidFree(Buf); } }; HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) { const size_t kBufSize = 1 << 16; CTempMidBuffer buf(kBufSize); if (!buf.Buf) return E_OUTOFMEMORY; NIO::CInFile inFile; NIO::COutFile outFile; if (!inFile.Open(_copyFile_Path)) return SendMessageError_with_LastError("Open error", _copyFile_Path); for (;;) { UInt32 num; if (!inFile.Read(buf.Buf, kBufSize, num)) return SendMessageError_with_LastError("Read error", _copyFile_Path); if (num == 0) return S_OK; RINOK(WriteStream(outStream, buf.Buf, num)); } } */ HRESULT CArchiveExtractCallback::ReadLink() { IInArchive *archive = _arc->Archive; const UInt32 index = _index; _link.Clear(); { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidHardLink, &prop)) if (prop.vt == VT_BSTR) { _link.isHardLink = true; // _link.isCopyLink = false; _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; } /* { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); if (prop.vt == VT_BSTR) { _link.isHardLink = false; _link.isCopyLink = true; _link.isRelative = false; // RAR5: copy links are from root folder of archive _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; } */ { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidSymLink, &prop)) if (prop.vt == VT_BSTR) { _link.isHardLink = false; // _link.isCopyLink = false; _link.isRelative = true; // RAR5, TAR: symbolic links can be relative _link.linkPath.SetFromBstr(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; } NtReparse_Data = NULL; NtReparse_Size = 0; if (_link.linkPath.IsEmpty() && _arc->GetRawProps) { const void *data; UInt32 dataSize; UInt32 propType; _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); // if (dataSize == 1234567) // for debug: unpacking without reparse if (dataSize != 0) { if (propType != NPropDataType::kRaw) return E_FAIL; // 21.06: we need kpidNtReparse in linux for wim archives created in Windows // #ifdef _WIN32 NtReparse_Data = data; NtReparse_Size = dataSize; CReparseAttr reparse; bool isOkReparse = reparse.Parse((const Byte *)data, dataSize); if (isOkReparse) { _link.isHardLink = false; // _link.isCopyLink = false; _link.linkPath = reparse.GetPath(); _link.isJunction = reparse.IsMountPoint(); if (reparse.IsSymLink_WSL()) { _link.isWSL = true; _link.isRelative = reparse.IsRelative_WSL(); } else _link.isRelative = reparse.IsRelative_Win(); // const AString s = GetAnsiString(_link.linkPath); // printf("\n_link.linkPath: %s\n", s.Ptr()); #ifndef _WIN32 _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } // #endif } } if (_link.linkPath.IsEmpty()) return S_OK; { #ifdef _WIN32 _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif // rar5 uses "\??\" prefix for absolute links if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) { _link.isRelative = false; _link.linkPath.DeleteFrontal(4); } for (;;) // while (NName::IsAbsolutePath(linkPath)) { unsigned n = NName::GetRootPrefixSize(_link.linkPath); if (n == 0) break; _link.isRelative = false; _link.linkPath.DeleteFrontal(n); } } if (_link.linkPath.IsEmpty()) return S_OK; if (!_link.isRelative && _removePathParts.Size() != 0) { UStringVector pathParts; SplitPathToParts(_link.linkPath, pathParts); bool badPrefix = false; FOR_VECTOR (i, _removePathParts) { if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) { badPrefix = true; break; } } if (!badPrefix) pathParts.DeleteFrontal(_removePathParts.Size()); _link.linkPath = MakePathFromParts(pathParts); } /* if (!_link.linkPath.IsEmpty()) { printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr()); } */ return S_OK; } #endif // SUPPORT_LINKS #ifndef _WIN32 static HRESULT GetOwner(IInArchive *archive, UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res) { { NWindows::NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, pidId, &prop)) if (prop.vt == VT_UI4) { res.Id_Defined = true; res.Id = prop.ulVal; // for debug // res.Id++; // for debug // if (pidId == kpidGroupId) res.Id += 7; // for debug // res.Id = 0; // for debug } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; } { NWindows::NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, pidName, &prop)) if (prop.vt == VT_BSTR) { const UString s = prop.bstrVal; ConvertUnicodeToUTF8(s, res.Name); } else if (prop.vt == VT_UI4) { res.Id_Defined = true; res.Id = prop.ulVal; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; } return S_OK; } #endif HRESULT CArchiveExtractCallback::Read_fi_Props() { IInArchive *archive = _arc->Archive; const UInt32 index = _index; _fi.Attrib_Defined = false; #ifndef _WIN32 _fi.Owner.Clear(); _fi.Group.Clear(); #endif { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPosixAttrib, &prop)) if (prop.vt == VT_UI4) { _fi.SetFromPosixAttrib(prop.ulVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; } { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidAttrib, &prop)) if (prop.vt == VT_UI4) { _fi.Attrib = prop.ulVal; _fi.Attrib_Defined = true; } else if (prop.vt != VT_EMPTY) return E_FAIL; } RINOK(GetTime(index, kpidCTime, _fi.CTime)) RINOK(GetTime(index, kpidATime, _fi.ATime)) RINOK(GetTime(index, kpidMTime, _fi.MTime)) #ifndef _WIN32 if (_ntOptions.ExtractOwner) { // SendMessageError_with_LastError("_ntOptions.ExtractOwner", _diskFilePath); GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner); GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group); } #endif return S_OK; } void CArchiveExtractCallback::CorrectPathParts() { UStringVector &pathParts = _item.PathParts; #ifdef SUPPORT_ALT_STREAMS if (!_item.IsAltStream || !pathParts.IsEmpty() || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)) #endif Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir); #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream) { UString s (_item.AltStreamName); Correct_AltStream_Name(s); bool needColon = true; if (pathParts.IsEmpty()) { pathParts.AddNew(); if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) needColon = false; } #ifdef _WIN32 else if (_pathMode == NExtract::NPathMode::kAbsPaths && NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size()) pathParts.AddNew(); #endif UString &name = pathParts.Back(); if (needColon) name.Add_Char((char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':')); name += s; } #endif // SUPPORT_ALT_STREAMS } void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt) { pt.CTime_Defined = false; pt.ATime_Defined = false; pt.MTime_Defined = false; if (Write_MTime) { if (_fi.MTime.Def) { _fi.MTime.Write_To_FiTime(pt.MTime); pt.MTime_Defined = true; } else if (_arc->MTime.Def) { _arc->MTime.Write_To_FiTime(pt.MTime); pt.MTime_Defined = true; } } if (Write_CTime && _fi.CTime.Def) { _fi.CTime.Write_To_FiTime(pt.CTime); pt.CTime_Defined = true; } if (Write_ATime && _fi.ATime.Def) { _fi.ATime.Write_To_FiTime(pt.ATime); pt.ATime_Defined = true; } } void CArchiveExtractCallback::CreateFolders() { // 21.04 : we don't change original (_item.PathParts) here UStringVector pathParts = _item.PathParts; // bool is_DirOp = false; if (!pathParts.IsEmpty()) { /* v23: if we extract symlink, and we know that it links to dir: Linux: we don't create dir item (symlink_from_path) here. Windows: SetReparseData() will create dir item, if it doesn't exist, but if we create dir item here, it's not problem. */ if (!_item.IsDir #ifdef SUPPORT_LINKS #ifndef WIN32 || !_link.linkPath.IsEmpty() #endif #endif ) pathParts.DeleteBack(); // else is_DirOp = true; } if (pathParts.IsEmpty()) { /* if (_some_pathParts_wereRemoved && Is_elimPrefix_Mode), then we can have empty pathParts() here for root folder. v24.00: fixed: we set timestamps for such folder still. */ if (!_some_pathParts_wereRemoved || !Is_elimPrefix_Mode) return; // return; // ignore empty paths case } /* if (is_DirOp) { RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) _op_WasReported = true; } */ FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); /* if (is_DirOp) { RINOK(SetOperationResult( // _itemFailure ? NArchive::NExtract::NOperationResult::kDataError : NArchive::NExtract::NOperationResult::kOK )) } */ if (!_item.IsDir) return; if (fullPathNew.IsEmpty()) return; if (_itemFailure) return; CDirPathTime pt; GetFiTimesCAM(pt); if (pt.IsSomeTimeDefined()) { pt.Path = fullPathNew; pt.SetDirTime(); _extractedFolders.Add(pt); } } /* CheckExistFile(fullProcessedPath) it can change: fullProcessedPath, _isRenamed, _overwriteMode (needExit = true) means that we must exit GetStream() even for S_OK result. */ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool &needExit) { needExit = true; // it was set already before NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { if (_overwriteMode == NExtract::NOverwriteMode::kSkip) return S_OK; if (_overwriteMode == NExtract::NOverwriteMode::kAsk) { const int slashPos = fullProcessedPath.ReverseFind_PathSepar(); const FString realFullProcessedPath = fullProcessedPath.Left((unsigned)(slashPos + 1)) + fileInfo.Name; /* (fileInfo) can be symbolic link. we can show final file properties here. */ FILETIME ft1; FiTime_To_FILETIME(fileInfo.MTime, ft1); Int32 overwriteResult; RINOK(_extractCallback2->AskOverwrite( fs2us(realFullProcessedPath), &ft1, &fileInfo.Size, _item.Path, _fi.MTime.Def ? &_fi.MTime.FT : NULL, _curSize_Defined ? &_curSize : NULL, &overwriteResult)) switch (overwriteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break; default: return E_FAIL; } } // NExtract::NOverwriteMode::kAsk if (_overwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(fullProcessedPath)) { RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)) return E_FAIL; } _isRenamed = true; } else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) { FString existPath (fullProcessedPath); if (!AutoRenamePath(existPath)) { RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)) return E_FAIL; } // MyMoveFile can rename folders. So it's OK to use it for folders too if (!MyMoveFile(fullProcessedPath, existPath)) { HRESULT errorCode = GetLastError_noZero_HRESULT(); RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath)) return E_FAIL; } } else // not Rename* { if (fileInfo.IsDir()) { // do we need to delete all files in folder? if (!RemoveDir(fullProcessedPath)) { RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath)) return S_OK; } } else // fileInfo is not Dir { if (NFind::DoesFileExist_Raw(fullProcessedPath)) if (!DeleteFileAlways(fullProcessedPath)) if (GetLastError() != ERROR_FILE_NOT_FOUND) // check it in linux { RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath)) return S_OK; // return E_FAIL; } } // fileInfo is not Dir } // not Rename* } else // not Find(fullProcessedPath) { #if defined(_WIN32) && !defined(UNDER_CE) // we need to clear READ-ONLY of parent before creating alt stream int colonPos = NName::FindAltStreamColon(fullProcessedPath); if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) { FString parentFsPath (fullProcessedPath); parentFsPath.DeleteFrom((unsigned)colonPos); NFind::CFileInfo parentFi; if (parentFi.Find(parentFsPath)) { if (parentFi.IsReadOnly()) SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); } } #endif // defined(_WIN32) && !defined(UNDER_CE) } needExit = false; return S_OK; } HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr &outStreamLoc, bool &needExit) { needExit = true; RINOK(Read_fi_Props()) #ifdef SUPPORT_LINKS IInArchive *archive = _arc->Archive; #endif const UInt32 index = _index; bool isAnti = false; RINOK(_arc->IsItem_Anti(index, isAnti)) CorrectPathParts(); UString processedPath (MakePathFromParts(_item.PathParts)); if (!isAnti) { // 21.04: CreateFolders doesn't change (_item.PathParts) CreateFolders(); } FString fullProcessedPath (us2fs(processedPath)); if (_pathMode != NExtract::NPathMode::kAbsPaths || !NName::IsAbsolutePath(processedPath)) { fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath); } #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) { const int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex)); if (renIndex != -1) { const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex]; fullProcessedPath = pair.Path; fullProcessedPath.Add_Colon(); UString s (_item.AltStreamName); Correct_AltStream_Name(s); fullProcessedPath += us2fs(s); } } #endif // SUPPORT_ALT_STREAMS if (_item.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) RemoveDir(_diskFilePath); #ifdef SUPPORT_LINKS if (_link.linkPath.IsEmpty()) #endif { if (!isAnti) SetAttrib(); return S_OK; } } else if (!_isSplit) { RINOK(CheckExistFile(fullProcessedPath, needExit)) if (needExit) return S_OK; needExit = true; } _diskFilePath = fullProcessedPath; if (isAnti) { needExit = false; return S_OK; } // not anti #ifdef SUPPORT_LINKS if (!_link.linkPath.IsEmpty()) { #ifndef UNDER_CE { bool linkWasSet = false; RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)) if (linkWasSet) { _isSymLinkCreated = _link.IsSymLink(); SetAttrib(); // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); } } #endif // UNDER_CE // if (_copyFile_Path.IsEmpty()) { needExit = false; return S_OK; } } if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream && !_item.IsDir) { CHardLinkNode h; bool defined; RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)) if (defined) { const int linkIndex = _hardLinks.IDs.FindInSorted2(h); if (linkIndex != -1) { FString &hl = _hardLinks.Links[(unsigned)linkIndex]; if (hl.IsEmpty()) hl = fullProcessedPath; else { if (!MyCreateHardLink(fullProcessedPath, hl)) { const HRESULT errorCode = GetLastError_noZero_HRESULT(); RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)) return S_OK; } // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); // _needSetAttrib = true; // do we need to set attribute ? SetAttrib(); needExit = false; return S_OK; } } } } #endif // SUPPORT_LINKS // ---------- CREATE WRITE FILE ----- _outFileStreamSpec = new COutFileStream; CMyComPtr outFileStream_Loc(_outFileStreamSpec); if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath)) return S_OK; } } _needSetAttrib = true; bool is_SymLink_in_Data = false; if (_curSize_Defined && _curSize > 0 && _curSize < (1 << 12)) { if (_fi.IsLinuxSymLink()) { is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = true; } else if (_fi.IsReparse()) { is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = false; } } if (is_SymLink_in_Data) { _outMemBuf.Alloc((size_t)_curSize); _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream; _bufPtrSeqOutStream = _bufPtrSeqOutStream_Spec; _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); outStreamLoc = _bufPtrSeqOutStream; } else // not reprase { if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12)) { // UInt64 ticks = GetCpuTicks(); _fileLength_that_WasSet = _curSize; bool res = _outFileStreamSpec->File.SetLength(_curSize); _fileLength_WasSet = res; // ticks = GetCpuTicks() - ticks; // printf("\nticks = %10d\n", (unsigned)ticks); if (!res) { RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath)) } /* _outFileStreamSpec->File.Close(); ticks = GetCpuTicks() - ticks; printf("\nticks = %10d\n", (unsigned)ticks); return S_FALSE; */ /* File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow, if we don't write any data. File.SetLength() for remote share file (exFAT) can be slow in some cases, and the Windows can return "network error" after 1 minute, while remote file still can grow. We need some way to detect such bad cases and disable PreAllocateOutFile mode. */ res = _outFileStreamSpec->SeekToBegin_bool(); if (!res) { RINOK(SendMessageError_with_LastError("Cannot seek to begin of file", fullProcessedPath)) } } // PreAllocateOutFile #ifdef SUPPORT_ALT_STREAMS if (_isRenamed && !_item.IsAltStream) { CIndexToPathPair pair(index, fullProcessedPath); unsigned oldSize = _renamedFiles.Size(); unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair); if (oldSize == _renamedFiles.Size()) _renamedFiles[insertIndex].Path = fullProcessedPath; } #endif // SUPPORT_ALT_STREAMS if (_isSplit) { RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL)) } outStreamLoc = outFileStream_Loc; } // if not reprase _outFileStream = outFileStream_Loc; needExit = false; return S_OK; } HRESULT CArchiveExtractCallback::GetItem(UInt32 index) { #ifndef Z7_SFX _item._use_baseParentFolder_mode = _use_baseParentFolder_mode; if (_use_baseParentFolder_mode) { _item._baseParentFolder = (int)_baseParentFolder; if (_pathMode == NExtract::NPathMode::kFullPaths || _pathMode == NExtract::NPathMode::kAbsPaths) _item._baseParentFolder = -1; } #endif // Z7_SFX #ifdef SUPPORT_ALT_STREAMS _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon; #endif return _arc->GetItem(index, _item); } Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) { COM_TRY_BEGIN *outStream = NULL; #ifndef Z7_SFX if (_hashStream) _hashStreamSpec->ReleaseStream(); _hashStreamWasUsed = false; #endif _outFileStream.Release(); _bufPtrSeqOutStream.Release(); _encrypted = false; _position = 0; _isSplit = false; _curSize = 0; _curSize_Defined = false; _fileLength_WasSet = false; _fileLength_that_WasSet = 0; _index = index; _diskFilePath.Empty(); _isRenamed = false; // _fi.Clear(); // _is_SymLink_in_Data = false; _is_SymLink_in_Data_Linux = false; _needSetAttrib = false; _isSymLinkCreated = false; _itemFailure = false; _some_pathParts_wereRemoved = false; // _op_WasReported = false; #ifdef SUPPORT_LINKS // _copyFile_Path.Empty(); _link.Clear(); #endif _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: if (_testMode) { // askExtractMode = NArchive::NExtract::NAskMode::kTest; } else _extractMode = true; break; default: break; } IInArchive *archive = _arc->Archive; RINOK(GetItem(index)) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPosition, &prop)) if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } #ifdef SUPPORT_LINKS RINOK(ReadLink()) #endif // SUPPORT_LINKS RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)) RINOK(GetUnpackSize()) #ifdef SUPPORT_ALT_STREAMS if (!_ntOptions.AltStreams.Val && _item.IsAltStream) return S_OK; #endif // SUPPORT_ALT_STREAMS // we can change (_item.PathParts) in this function UStringVector &pathParts = _item.PathParts; if (_wildcardCensor) { if (!CensorNode_CheckPath(*_wildcardCensor, _item)) return S_OK; } #ifndef Z7_SFX if (_use_baseParentFolder_mode) { if (!pathParts.IsEmpty()) { unsigned numRemovePathParts = 0; #ifdef SUPPORT_ALT_STREAMS if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream) numRemovePathParts = pathParts.Size(); else #endif if (_pathMode == NExtract::NPathMode::kNoPaths || _pathMode == NExtract::NPathMode::kNoPathsAlt) numRemovePathParts = pathParts.Size() - 1; pathParts.DeleteFrontal(numRemovePathParts); } } else #endif // Z7_SFX { if (pathParts.IsEmpty()) { if (_item.IsDir) return S_OK; /* #ifdef SUPPORT_ALT_STREAMS if (!_item.IsAltStream) #endif return E_FAIL; */ } unsigned numRemovePathParts = 0; switch ((int)_pathMode) { case NExtract::NPathMode::kFullPaths: case NExtract::NPathMode::kCurPaths: { if (_removePathParts.IsEmpty()) break; bool badPrefix = false; if (pathParts.Size() < _removePathParts.Size()) badPrefix = true; else { if (pathParts.Size() == _removePathParts.Size()) { if (_removePartsForAltStreams) { #ifdef SUPPORT_ALT_STREAMS if (!_item.IsAltStream) #endif badPrefix = true; } else { if (!_item.MainIsDir) badPrefix = true; } } if (!badPrefix) FOR_VECTOR (i, _removePathParts) { if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) { badPrefix = true; break; } } } if (badPrefix) { if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) return E_FAIL; } else { numRemovePathParts = _removePathParts.Size(); _some_pathParts_wereRemoved = true; } break; } case NExtract::NPathMode::kNoPaths: { if (!pathParts.IsEmpty()) numRemovePathParts = pathParts.Size() - 1; break; } case NExtract::NPathMode::kNoPathsAlt: { #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream) numRemovePathParts = pathParts.Size(); else #endif if (!pathParts.IsEmpty()) numRemovePathParts = pathParts.Size() - 1; break; } case NExtract::NPathMode::kAbsPaths: default: break; } pathParts.DeleteFrontal(numRemovePathParts); } #ifndef Z7_SFX if (ExtractToStreamCallback) { if (!GetProp) { GetProp_Spec = new CGetProp; GetProp = GetProp_Spec; } GetProp_Spec->Arc = _arc; GetProp_Spec->IndexInArc = index; UString name (MakePathFromParts(pathParts)); #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream) { if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt)) name.Add_Colon(); name += _item.AltStreamName; } #endif return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp); } #endif // Z7_SFX CMyComPtr outStreamLoc; if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { if (_stdOutMode) outStreamLoc = new CStdOutFileStream; else { bool needExit = true; RINOK(GetExtractStream(outStreamLoc, needExit)) if (needExit) return S_OK; } } #ifndef Z7_SFX if (_hashStream) { if (askExtractMode == NArchive::NExtract::NAskMode::kExtract || askExtractMode == NArchive::NExtract::NAskMode::kTest) { _hashStreamSpec->SetStream(outStreamLoc); outStreamLoc = _hashStream; _hashStreamSpec->Init(true); _hashStreamWasUsed = true; } } #endif // Z7_SFX if (outStreamLoc) { /* #ifdef SUPPORT_LINKS if (!_copyFile_Path.IsEmpty()) { RINOK(PrepareOperation(askExtractMode)); RINOK(MyCopyFile(outStreamLoc)); return SetOperationResult(NArchive::NExtract::NOperationResult::kOK); } if (_link.isCopyLink && _testMode) return S_OK; #endif */ *outStream = outStreamLoc.Detach(); } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)) { COM_TRY_BEGIN #ifndef Z7_SFX // if (!_op_WasReported) if (ExtractToStreamCallback) return ExtractToStreamCallback->PrepareOperation7(askExtractMode); #endif _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: if (_testMode) askExtractMode = NArchive::NExtract::NAskMode::kTest; else _extractMode = true; break; default: break; } // if (_op_WasReported) return S_OK; return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir), askExtractMode, _isSplit ? &_position: NULL); COM_TRY_END } HRESULT CArchiveExtractCallback::CloseFile() { if (!_outFileStream) return S_OK; HRESULT hres = S_OK; const UInt64 processedSize = _outFileStreamSpec->ProcessedSize; if (_fileLength_WasSet && _fileLength_that_WasSet > processedSize) { const bool res = _outFileStreamSpec->File.SetLength(processedSize); _fileLength_WasSet = res; if (!res) { const HRESULT hres2 = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path)); if (hres == S_OK) hres = hres2; } } _curSize = processedSize; _curSize_Defined = true; #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) if (ZoneBuf.Size() != 0 && !_item.IsAltStream) { // if (NFind::DoesFileExist_Raw(tempFilePath)) if (ZoneMode != NExtract::NZoneIdMode::kOffice || FindExt2(kOfficeExtensions, fs2us(_diskFilePath))) { // we must write zone file before setting of timestamps if (!WriteZoneFile_To_BaseFile(_diskFilePath, ZoneBuf)) { // we can't write it in FAT // SendMessageError_with_LastError("Can't write Zone.Identifier stream", path); } } } #endif CFiTimesCAM t; GetFiTimesCAM(t); // #ifdef _WIN32 if (t.IsSomeTimeDefined()) _outFileStreamSpec->SetTime( t.CTime_Defined ? &t.CTime : NULL, t.ATime_Defined ? &t.ATime : NULL, t.MTime_Defined ? &t.MTime : NULL); // #endif RINOK(_outFileStreamSpec->Close()) _outFileStream.Release(); return hres; } #ifdef SUPPORT_LINKS HRESULT CArchiveExtractCallback::SetFromLinkPath( const FString &fullProcessedPath, const CLinkInfo &linkInfo, bool &linkWasSet) { linkWasSet = false; if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink) return S_OK; UString relatPath; /* if (linkInfo.isRelative) linkInfo.linkPath is final link path that must be stored to file link field else linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath. */ if (linkInfo.isRelative) relatPath = GetDirPrefixOf(_item.Path); relatPath += linkInfo.linkPath; if (!IsSafePath(relatPath)) { return SendMessageError2( 0, // errorCode "Dangerous link path was ignored", us2fs(_item.Path), us2fs(linkInfo.linkPath)); // us2fs(relatPath) } FString existPath; if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative) { if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) { RINOK(SendMessageError("Incorrect path", us2fs(relatPath))) } } else { existPath = us2fs(linkInfo.linkPath); // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr()); } if (existPath.IsEmpty()) return SendMessageError("Empty link", fullProcessedPath); if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */) { // if (linkInfo.isHardLink) { if (!MyCreateHardLink(fullProcessedPath, existPath)) { const HRESULT errorCode = GetLastError_noZero_HRESULT(); RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)) } /* RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) _op_WasReported = true; RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK)) */ linkWasSet = true; return S_OK; } /* // IsCopyLink { NFind::CFileInfo fi; if (!fi.Find(existPath)) { RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath)); } else { if (_curSize_Defined && _curSize == fi.Size) _copyFile_Path = existPath; else { RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); } // RINOK(MyCopyFile(existPath, fullProcessedPath)); } } */ } // is Symbolic link /* if (_item.IsDir && !isRelative) { // Windows before Vista doesn't support symbolic links. // we could convert such symbolic links to Junction Points // isJunction = true; // convertToAbs = true; } */ if (!_ntOptions.SymLinks_AllowDangerous.Val) { #ifdef _WIN32 if (_item.IsDir) #endif if (linkInfo.isRelative) { CLinkLevelsInfo levelsInfo; levelsInfo.Parse(linkInfo.linkPath); if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute) { return SendMessageError2( 0, // errorCode "Dangerous symbolic link path was ignored", us2fs(_item.Path), us2fs(linkInfo.linkPath)); } } } #ifdef _WIN32 CByteBuffer data; // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr()); if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL)) return SendMessageError("Cannot fill link data", us2fs(_item.Path)); /* if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) { SendMessageError("reconstructed Reparse is different", fs2us(existPath)); } */ CReparseAttr attr; if (!attr.Parse(data, data.Size())) { RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))) return S_OK; } if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) { RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) return S_OK; } linkWasSet = true; return S_OK; #else // ! _WIN32 if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath)) { RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) return S_OK; } linkWasSet = true; return S_OK; #endif // ! _WIN32 } bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) { Clear(); // this->isLinux = isLinuxData; if (isLinuxData) { isJunction = false; isHardLink = false; AString utf; if (dataSize >= (1 << 12)) return false; utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); UString u; if (!ConvertUTF8ToUnicode(utf, u)) return false; linkPath = u; // in linux symbolic data: we expect that linux separator '/' is used // if windows link was created, then we also must use linux separator if (u.IsEmpty()) return false; const wchar_t c = u[0]; isRelative = !IS_PATH_SEPAR(c); return true; } CReparseAttr reparse; if (!reparse.Parse(data, dataSize)) return false; isHardLink = false; // isCopyLink = false; linkPath = reparse.GetPath(); isJunction = reparse.IsMountPoint(); if (reparse.IsSymLink_WSL()) { isWSL = true; isRelative = reparse.IsRelative_WSL(); } else isRelative = reparse.IsRelative_Win(); // FIXME !!! #ifndef _WIN32 linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif return true; } #endif // SUPPORT_LINKS HRESULT CArchiveExtractCallback::CloseReparseAndFile() { HRESULT res = S_OK; #ifdef SUPPORT_LINKS size_t reparseSize = 0; bool repraseMode = false; bool needSetReparse = false; CLinkInfo linkInfo; if (_bufPtrSeqOutStream) { repraseMode = true; reparseSize = _bufPtrSeqOutStream_Spec->GetPos(); if (_curSize_Defined && reparseSize == _outMemBuf.Size()) { /* CReparseAttr reparse; DWORD errorCode = 0; needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); if (needSetReparse) { UString linkPath = reparse.GetPath(); #ifndef _WIN32 linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } */ needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux); if (!needSetReparse) res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); } else { res = SendMessageError_with_LastError("Unknown reparse stream", us2fs(_item.Path)); } if (!needSetReparse && _outFileStream) { const HRESULT res2 = WriteStream(_outFileStream, _outMemBuf, reparseSize); if (res == S_OK) res = res2; } _bufPtrSeqOutStream.Release(); } #endif // SUPPORT_LINKS const HRESULT res2 = CloseFile(); if (res == S_OK) res = res2; RINOK(res) #ifdef SUPPORT_LINKS if (repraseMode) { _curSize = reparseSize; _curSize_Defined = true; #ifdef SUPPORT_LINKS if (needSetReparse) { // in Linux : we must delete empty file before symbolic link creation // in Windows : we can create symbolic link even without file deleting if (!DeleteFileAlways(_diskFilePath)) { RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)) } { /* // for DEBUG ONLY: we can extract sym links as WSL links // to eliminate (non-admin) errors for sym links. #ifdef _WIN32 if (!linkInfo.isHardLink && !linkInfo.isJunction) linkInfo.isWSL = true; #endif */ bool linkWasSet = false; RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)) if (linkWasSet) _isSymLinkCreated = linkInfo.IsSymLink(); else _needSetAttrib = false; } /* if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) { res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath); } */ } #endif } #endif return res; } void CArchiveExtractCallback::SetAttrib() { #ifndef _WIN32 // Linux now doesn't support permissions for symlinks if (_isSymLinkCreated) return; #endif if (_itemFailure || _diskFilePath.IsEmpty() || _stdOutMode || !_extractMode) return; #ifndef _WIN32 if (_fi.Owner.Id_Defined && _fi.Group.Id_Defined) { if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0) { SendMessageError_with_LastError("Cannot set owner", _diskFilePath); } } #endif if (_fi.Attrib_Defined) { // const AString s = GetAnsiString(_diskFilePath); // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); if (!res) { // do we need error message here in Windows and in posix? SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); } } } Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) { COM_TRY_BEGIN // printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath)); #ifndef Z7_SFX if (ExtractToStreamCallback) { GetUnpackSize(); return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize); } #endif #ifndef Z7_SFX if (_hashStreamWasUsed) { _hashStreamSpec->_hash->Final(_item.IsDir, #ifdef SUPPORT_ALT_STREAMS _item.IsAltStream #else false #endif , _item.Path); _curSize = _hashStreamSpec->GetSize(); _curSize_Defined = true; _hashStreamSpec->ReleaseStream(); _hashStreamWasUsed = false; } #endif // Z7_SFX RINOK(CloseReparseAndFile()) #ifdef Z7_USE_SECURITY_CODE if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) { const void *data; UInt32 dataSize; UInt32 propType; _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); if (dataSize != 0) { if (propType != NPropDataType::kRaw) return E_FAIL; if (CheckNtSecure((const Byte *)data, dataSize)) { SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; if (_saclEnabled) securInfo |= SACL_SECURITY_INFORMATION; ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); } } } #endif // Z7_USE_SECURITY_CODE if (!_curSize_Defined) GetUnpackSize(); if (_curSize_Defined) { #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream) AltStreams_UnpackSize += _curSize; else #endif UnpackSize += _curSize; } if (_item.IsDir) NumFolders++; #ifdef SUPPORT_ALT_STREAMS else if (_item.IsAltStream) NumAltStreams++; #endif else NumFiles++; if (_needSetAttrib) SetAttrib(); RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))) return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)) { if (_folderArchiveExtractCallback2) { bool isEncrypted = false; UString s; if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1) { CReadArcItem item; RINOK(_arc->GetItem(index, item)) s = item.Path; RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted)) } else { s = '#'; s.Add_UInt32(index); // if (indexType == NArchive::NEventIndexType::kBlockIndex) {} } return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s); } return S_OK; } Z7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)) } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } #ifndef Z7_SFX // ---------- HASH functions ---------- FString CArchiveExtractCallback::Hash_GetFullFilePath() { // this function changes _item.PathParts. CorrectPathParts(); const UStringVector &pathParts = _item.PathParts; const UString processedPath (MakePathFromParts(pathParts)); FString fullProcessedPath (us2fs(processedPath)); if (_pathMode != NExtract::NPathMode::kAbsPaths || !NName::IsAbsolutePath(processedPath)) { fullProcessedPath = MakePath_from_2_Parts( DirPathPrefix_for_HashFiles, // _dirPathPrefix, fullProcessedPath); } return fullProcessedPath; } Z7_COM7F_IMF(CArchiveExtractCallback::GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (propID == kpidSize) { RINOK(GetItem(index)) const FString fullProcessedPath = Hash_GetFullFilePath(); NFile::NFind::CFileInfo fi; if (fi.Find_FollowLink(fullProcessedPath)) if (!fi.IsDir()) prop = (UInt64)fi.Size; } prop.Detach(value); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)) { COM_TRY_BEGIN *inStream = NULL; // if (index != _index) return E_FAIL; if (mode != NUpdateNotifyOp::kHashRead) return E_FAIL; RINOK(GetItem(index)) const FString fullProcessedPath = Hash_GetFullFilePath(); CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamRef = inStreamSpec; inStreamSpec->Set_PreserveATime(_ntOptions.PreserveATime); if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite)) { RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath)) return S_OK; } *inStream = inStreamRef.Detach(); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::ReportOperation( UInt32 /* indexType */, UInt32 /* index */, UInt32 /* op */)) { // COM_TRY_BEGIN return S_OK; // COM_TRY_END } Z7_COM7F_IMF(CArchiveExtractCallback::RequestMemoryUse( UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path, UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags)) { if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0) { const UInt64 memLimit = _ntOptions.MemLimit; if (memLimit != (UInt64)(Int64)-1) { // we overwrite allowedSize *allowedSize = memLimit; if (requiredSize <= memLimit) { *answerFlags = NRequestMemoryAnswerFlags::k_Allow; return S_OK; } *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded; if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc; flags |= NRequestMemoryUseFlags::k_SLimit_Exceeded | NRequestMemoryUseFlags::k_AllowedSize_WasForced; } } if (!_requestMemoryUseCallback) { _extractCallback2.QueryInterface(IID_IArchiveRequestMemoryUseCallback, &_requestMemoryUseCallback); if (!_requestMemoryUseCallback) { // keep default (answerFlags) from caller or (answerFlags) that was set in this function return S_OK; } } #if 0 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0) if (requiredSize <= *allowedSize) { // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already, // because it's default answer for (requiredSize <= *allowedSize) case. *answerFlags = NRequestMemoryAnswerFlags::k_Allow; // optional code } else { // we clear *answerFlags, because we want to disable dafault "Allow", if it's set. // *answerFlags = 0; /* NRequestMemoryAnswerFlags::k_SkipArc | NRequestMemoryAnswerFlags::k_Limit_Exceeded; */ } #endif UString s; if (!path && indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1 && _arc) { RINOK(_arc->GetItem_Path(index, s)) path = s.Ptr(); } return _requestMemoryUseCallback->RequestMemoryUse( flags, indexType, index, path, requiredSize, allowedSize, answerFlags); } #endif // Z7_SFX // ------------ After Extracting functions ------------ void CDirPathSortPair::SetNumSlashes(const FChar *s) { for (unsigned numSlashes = 0;;) { FChar c = *s++; if (c == 0) { Len = numSlashes; return; } if (IS_PATH_SEPAR(c)) numSlashes++; } } bool CDirPathTime::SetDirTime() const { return NDir::SetDirTime(Path, CTime_Defined ? &CTime : NULL, ATime_Defined ? &ATime : NULL, MTime_Defined ? &MTime : NULL); } HRESULT CArchiveExtractCallback::SetDirsTimes() { if (!_arc) return S_OK; CRecordVector pairs; pairs.ClearAndSetSize(_extractedFolders.Size()); unsigned i; for (i = 0; i < _extractedFolders.Size(); i++) { CDirPathSortPair &pair = pairs[i]; pair.Index = i; pair.SetNumSlashes(_extractedFolders[i].Path); } pairs.Sort2(); HRESULT res = S_OK; for (i = 0; i < pairs.Size(); i++) { const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; if (!dpt.SetDirTime()) { // result = E_FAIL; // do we need error message here in Windows and in posix? // SendMessageError_with_LastError("Cannot set directory time", dpt.Path); } } /* #ifndef _WIN32 for (i = 0; i < _delayedSymLinks.Size(); i++) { const CDelayedSymLink &link = _delayedSymLinks[i]; if (!link.Create()) { if (res == S_OK) res = GetLastError_noZero_HRESULT(); // res = E_FAIL; // do we need error message here in Windows and in posix? SendMessageError_with_LastError("Cannot create Symbolic Link", link._source); } } #endif // _WIN32 */ ClearExtractedDirsInfo(); return res; } HRESULT CArchiveExtractCallback::CloseArc() { HRESULT res = CloseReparseAndFile(); const HRESULT res2 = SetDirsTimes(); if (res == S_OK) res = res2; _arc = NULL; return res; } tmp41wklro_/CPP/7zip/UI/Common/ArchiveExtractCallback.h0000444000175000001440000003243414576044340023740 0ustar nabijaczleweliusers// ArchiveExtractCallback.h #ifndef ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H #define ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H #include "../../../Common/MyCom.h" #include "../../../Common/MyLinux.h" #include "../../../Common/Wildcard.h" #include "../../IPassword.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "../../Archive/IArchive.h" #include "ExtractMode.h" #include "IFileExtractCallback.h" #include "OpenArchive.h" #include "HashCalc.h" #ifndef Z7_SFX Z7_CLASS_IMP_NOQIB_1( COutStreamWithHash , ISequentialOutStream ) bool _calculate; CMyComPtr _stream; UInt64 _size; public: IHashCalc *_hash; void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { InitCRC(); _size = 0; _calculate = calculate; } void EnableCalc(bool calculate) { _calculate = calculate; } void InitCRC() { _hash->InitForNewFile(); } UInt64 GetSize() const { return _size; } }; #endif struct CExtractNtOptions { CBoolPair NtSecurity; CBoolPair SymLinks; CBoolPair SymLinks_AllowDangerous; CBoolPair HardLinks; CBoolPair AltStreams; bool ReplaceColonForAltStream; bool WriteToAltStreamIfColon; bool ExtractOwner; bool PreAllocateOutFile; // used for hash arcs only, when we open external files bool PreserveATime; bool OpenShareForWrite; UInt64 MemLimit; CExtractNtOptions(): ReplaceColonForAltStream(false), WriteToAltStreamIfColon(false), ExtractOwner(false), PreserveATime(false), OpenShareForWrite(false), MemLimit((UInt64)(Int64)-1) { SymLinks.Val = true; SymLinks_AllowDangerous.Val = false; HardLinks.Val = true; AltStreams.Val = true; PreAllocateOutFile = #ifdef _WIN32 true; #else false; #endif } }; #ifndef Z7_SFX Z7_CLASS_IMP_COM_1( CGetProp , IGetProp ) public: UInt32 IndexInArc; const CArc *Arc; // UString Name; // relative path }; #endif #ifndef Z7_SFX #ifndef UNDER_CE #define SUPPORT_LINKS #endif #endif #ifdef SUPPORT_LINKS struct CHardLinkNode { UInt64 StreamId; UInt64 INode; int Compare(const CHardLinkNode &a) const; }; class CHardLinks { public: CRecordVector IDs; CObjectVector Links; void Clear() { IDs.Clear(); Links.Clear(); } void PrepareLinks() { while (Links.Size() < IDs.Size()) Links.AddNew(); } }; #endif #ifdef SUPPORT_ALT_STREAMS struct CIndexToPathPair { UInt32 Index; FString Path; CIndexToPathPair(UInt32 index): Index(index) {} CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {} int Compare(const CIndexToPathPair &pair) const { return MyCompare(Index, pair.Index); } }; #endif struct CFiTimesCAM { CFiTime CTime; CFiTime ATime; CFiTime MTime; bool CTime_Defined; bool ATime_Defined; bool MTime_Defined; bool IsSomeTimeDefined() const { return CTime_Defined | ATime_Defined | MTime_Defined; } }; struct CDirPathTime: public CFiTimesCAM { FString Path; bool SetDirTime() const; }; #ifdef SUPPORT_LINKS struct CLinkInfo { // bool isCopyLink; bool isHardLink; bool isJunction; bool isRelative; bool isWSL; UString linkPath; bool IsSymLink() const { return !isHardLink; } CLinkInfo(): // IsCopyLink(false), isHardLink(false), isJunction(false), isRelative(false), isWSL(false) {} void Clear() { // IsCopyLink = false; isHardLink = false; isJunction = false; isRelative = false; isWSL = false; linkPath.Empty(); } bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); }; #endif // SUPPORT_LINKS #ifndef _WIN32 struct COwnerInfo { bool Id_Defined; UInt32 Id; AString Name; void Clear() { Id_Defined = false; Id = 0; Name.Empty(); } }; #endif class CArchiveExtractCallback Z7_final: public IArchiveExtractCallback, public IArchiveExtractCallbackMessage2, public ICryptoGetTextPassword, public ICompressProgressInfo, #ifndef Z7_SFX public IArchiveUpdateCallbackFile, public IArchiveGetDiskProperty, public IArchiveRequestMemoryUseCallback, #endif public CMyUnknownImp { /* IArchiveExtractCallback, */ Z7_COM_QI_BEGIN2(IArchiveExtractCallbackMessage2) Z7_COM_QI_ENTRY(ICryptoGetTextPassword) Z7_COM_QI_ENTRY(ICompressProgressInfo) #ifndef Z7_SFX Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile) Z7_COM_QI_ENTRY(IArchiveGetDiskProperty) Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IArchiveExtractCallback) Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2) Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) Z7_IFACE_COM7_IMP(ICompressProgressInfo) #ifndef Z7_SFX Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile) Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty) Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) #endif const CArc *_arc; CExtractNtOptions _ntOptions; bool _isSplit; bool _extractMode; bool Write_CTime; bool Write_ATime; bool Write_MTime; bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; bool _encrypted; // bool _is_SymLink_in_Data; bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX bool _needSetAttrib; bool _isSymLinkCreated; bool _itemFailure; bool _some_pathParts_wereRemoved; public: bool Is_elimPrefix_Mode; private: bool _curSize_Defined; bool _fileLength_WasSet; bool _removePartsForAltStreams; bool _stdOutMode; bool _testMode; bool _multiArchives; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) CMyComPtr _extractCallback2; // CMyComPtr _compressProgress; // CMyComPtr _callbackMessage; CMyComPtr _folderArchiveExtractCallback2; CMyComPtr _cryptoGetTextPassword; FString _dirPathPrefix; FString _dirPathPrefix_Full; #ifndef Z7_SFX CMyComPtr ExtractToStreamCallback; CGetProp *GetProp_Spec; CMyComPtr GetProp; CMyComPtr _requestMemoryUseCallback; #endif CReadArcItem _item; FString _diskFilePath; UInt64 _position; struct CProcessedFileInfo { CArcTime CTime; CArcTime ATime; CArcTime MTime; UInt32 Attrib; bool Attrib_Defined; #ifndef _WIN32 COwnerInfo Owner; COwnerInfo Group; #endif bool IsReparse() const { return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); } bool IsLinuxSymLink() const { return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16)); } void SetFromPosixAttrib(UInt32 a) { // here we set only part of combined attribute required by SetFileAttrib() call #ifdef _WIN32 // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. Attrib = MY_LIN_S_ISDIR(a) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE; if ((a & 0222) == 0) // (& S_IWUSR) in p7zip Attrib |= FILE_ATTRIBUTE_READONLY; // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink() a &= MY_LIN_S_IFMT; if (a == MY_LIN_S_IFLNK) Attrib |= (a << 16); #else Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; #endif Attrib_Defined = true; } } _fi; UInt32 _index; UInt64 _curSize; UInt64 _fileLength_that_WasSet; COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; CByteBuffer _outMemBuf; CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; CMyComPtr _bufPtrSeqOutStream; #ifndef Z7_SFX COutStreamWithHash *_hashStreamSpec; CMyComPtr _hashStream; bool _hashStreamWasUsed; bool _use_baseParentFolder_mode; UInt32 _baseParentFolder; #endif UStringVector _removePathParts; CMyComPtr _localProgress; UInt64 _packTotal; UInt64 _progressTotal; bool _progressTotal_Defined; CObjectVector _extractedFolders; #ifndef _WIN32 // CObjectVector _delayedSymLinks; #endif #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) bool _saclEnabled; #endif void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft); HRESULT GetUnpackSize(); FString Hash_GetFullFilePath(); void SetAttrib(); public: HRESULT SendMessageError(const char *message, const FString &path); HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path); HRESULT SendMessageError_with_LastError(const char *message, const FString &path); HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); public: #if defined(_WIN32) && !defined(UNDER_CE) NExtract::NZoneIdMode::EEnum ZoneMode; CByteBuffer ZoneBuf; #endif CLocalProgress *LocalProgressSpec; UInt64 NumFolders; UInt64 NumFiles; UInt64 NumAltStreams; UInt64 UnpackSize; UInt64 AltStreams_UnpackSize; FString DirPathPrefix_for_HashFiles; CArchiveExtractCallback(); void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode, NExtract::NZoneIdMode::EEnum zoneMode, bool keepAndReplaceEmptyDirPrefixes) { _multiArchives = multiArchives; _pathMode = pathMode; _overwriteMode = overwriteMode; #if defined(_WIN32) && !defined(UNDER_CE) ZoneMode = zoneMode; #else UNUSED_VAR(zoneMode) #endif _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; } #ifndef Z7_SFX void SetHashMethods(IHashCalc *hash) { if (!hash) return; _hashStreamSpec = new COutStreamWithHash; _hashStream = _hashStreamSpec; _hashStreamSpec->_hash = hash; } #endif void InitBeforeNewArchive(); void Init( const CExtractNtOptions &ntOptions, const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, const FString &directoryPath, const UStringVector &removePathParts, bool removePartsForAltStreams, UInt64 packSize); #ifdef SUPPORT_LINKS private: CHardLinks _hardLinks; CLinkInfo _link; // FString _copyFile_Path; // HRESULT MyCopyFile(ISequentialOutStream *outStream); HRESULT Link(const FString &fullProcessedPath); HRESULT ReadLink(); public: // call PrepareHardLinks() after Init() HRESULT PrepareHardLinks(const CRecordVector *realIndices); // NULL means all items #endif #ifdef SUPPORT_ALT_STREAMS CObjectVector _renamedFiles; #endif // call it after Init() #ifndef Z7_SFX void SetBaseParentFolderIndex(UInt32 indexInArc) { _baseParentFolder = indexInArc; _use_baseParentFolder_mode = true; } #endif HRESULT CloseArc(); private: void ClearExtractedDirsInfo() { _extractedFolders.Clear(); #ifndef _WIN32 // _delayedSymLinks.Clear(); #endif } HRESULT Read_fi_Props(); void CorrectPathParts(); void GetFiTimesCAM(CFiTimesCAM &pt); void CreateFolders(); bool _isRenamed; HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); HRESULT GetExtractStream(CMyComPtr &outStreamLoc, bool &needExit); HRESULT GetItem(UInt32 index); HRESULT CloseFile(); HRESULT CloseReparseAndFile(); HRESULT CloseReparseAndFile2(); HRESULT SetDirsTimes(); const void *NtReparse_Data; UInt32 NtReparse_Size; #ifdef SUPPORT_LINKS HRESULT SetFromLinkPath( const FString &fullProcessedPath, const CLinkInfo &linkInfo, bool &linkWasSet); #endif }; struct CArchiveExtractCallback_Closer { CArchiveExtractCallback *_ref; CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {} HRESULT Close() { HRESULT res = S_OK; if (_ref) { res = _ref->CloseArc(); _ref = NULL; } return res; } ~CArchiveExtractCallback_Closer() { Close(); } }; bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf); bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf); #endif tmp41wklro_/CPP/7zip/UI/Common/ArchiveName.cpp0000444000175000001440000001011514535565660022124 0ustar nabijaczleweliusers// ArchiveName.cpp #include "StdAfx.h" #include "../../../../C/Sort.h" #include "../../../Common/Wildcard.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "ArchiveName.h" #include "ExtractingFilePath.h" using namespace NWindows; using namespace NFile; static const char *g_ArcExts = "7z" "\0" "zip" "\0" "tar" "\0" "wim" "\0"; static const char *g_HashExts = "sha256" "\0"; UString CreateArchiveName( const UStringVector &paths, bool isHash, const NFind::CFileInfo *fi, UString &baseName) { bool keepName = isHash; /* if (paths.Size() == 1) { const UString &name = paths[0]; if (name.Len() > 4) if (CompareFileNames(name.RightPtr(4), L".tar") == 0) keepName = true; } */ UString name ("Archive"); NFind::CFileInfo fi3; if (paths.Size() > 1) fi = NULL; if (!fi && paths.Size() != 0) { const UString &path = paths.Front(); if (paths.Size() == 1) { if (fi3.Find(us2fs(path))) fi = &fi3; } else { // we try to use name of parent folder FString dirPrefix; if (NDir::GetOnlyDirPrefix(us2fs(path), dirPrefix)) { if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back())) { #if defined(_WIN32) && !defined(UNDER_CE) if (NName::IsDriveRootPath_SuperAllowed(dirPrefix)) { if (path != fs2us(dirPrefix)) name = dirPrefix[dirPrefix.Len() - 3]; // only letter } else #endif { dirPrefix.DeleteBack(); if (!dirPrefix.IsEmpty()) { const int slash = dirPrefix.ReverseFind_PathSepar(); if (slash >= 0 && slash != (int)dirPrefix.Len() - 1) name = dirPrefix.Ptr(slash + 1); else if (fi3.Find(dirPrefix)) name = fs2us(fi3.Name); } } } } } } if (fi) { name = fs2us(fi->Name); if (!fi->IsDir() && !keepName) { const int dotPos = name.Find(L'.'); if (dotPos > 0 && name.Find(L'.', (unsigned)dotPos + 1) < 0) name.DeleteFrom((unsigned)dotPos); } } name = Get_Correct_FsFile_Name(name); CRecordVector ids; bool simple_IsAllowed = true; // for (int y = 0; y < 10000; y++) // for debug { // ids.Clear(); UString n; FOR_VECTOR (i, paths) { const UString &a = paths[i]; const int slash = a.ReverseFind_PathSepar(); // if (name.Len() >= a.Len() - slash + 1) continue; const wchar_t *s = a.Ptr(slash + 1); if (!IsPath1PrefixedByPath2(s, name)) continue; s += name.Len(); const char *exts = isHash ? g_HashExts : g_ArcExts; for (;;) { const char *ext = exts; const unsigned len = MyStringLen(ext); if (len == 0) break; exts += len + 1; n = s; if (n.Len() <= len) continue; if (!StringsAreEqualNoCase_Ascii(n.RightPtr(len), ext)) continue; n.DeleteFrom(n.Len() - len); if (n.Back() != '.') continue; n.DeleteBack(); if (n.IsEmpty()) { simple_IsAllowed = false; break; } if (n.Len() < 2) continue; if (n[0] != '_') continue; const wchar_t *end; const UInt32 v = ConvertStringToUInt32(n.Ptr(1), &end); if (*end != 0) continue; ids.Add(v); break; } } } baseName = name; if (!simple_IsAllowed) { HeapSort(ids.NonConstData(), ids.Size()); UInt32 v = 2; const unsigned num = ids.Size(); for (unsigned i = 0; i < num; i++) { const UInt32 id = ids[i]; if (id > v) break; if (id == v) v = id + 1; } name.Add_Char('_'); name.Add_UInt32(v); } return name; } tmp41wklro_/CPP/7zip/UI/Common/ArchiveName.h0000444000175000001440000000053014357314620021557 0ustar nabijaczleweliusers// ArchiveName.h #ifndef ZIP7_INC_ARCHIVE_NAME_H #define ZIP7_INC_ARCHIVE_NAME_H #include "../../../Windows/FileFind.h" /* (fi != NULL) only if (paths.Size() == 1) */ UString CreateArchiveName( const UStringVector &paths, bool isHash, const NWindows::NFile::NFind::CFileInfo *fi, UString &baseName); #endif tmp41wklro_/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp0000444000175000001440000002305114602771500023550 0ustar nabijaczleweliusers// ArchiveOpenCallback.cpp #include "StdAfx.h" #include "../../../Common/ComTry.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/System.h" #include "../../Common/StreamUtils.h" #include "ArchiveOpenCallback.h" // #define DEBUG_VOLUMES #ifdef DEBUG_VOLUMES #include #endif #ifdef DEBUG_VOLUMES #define PRF(x) x #else #define PRF(x) #endif using namespace NWindows; HRESULT COpenCallbackImp::Init2(const FString &folderPrefix, const FString &fileName) { Volumes.Init(); FileNames.Clear(); FileNames_WasUsed.Clear(); FileSizes.Clear(); _subArchiveMode = false; // TotalSize = 0; PasswordWasAsked = false; _folderPrefix = folderPrefix; if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName)) { // throw 20121118; return GetLastError_noZero_HRESULT(); } return S_OK; } Z7_COM7F_IMF(COpenCallbackImp::SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; // TotalSize = 0; return S_OK; } Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch (propID) { case kpidName: prop = _subArchiveName; break; // case kpidSize: prop = _subArchiveSize; break; // we don't use it now default: break; } else switch (propID) { case kpidName: prop = fs2us(_fileInfo.Name); break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.GetWinAttrib(); break; case kpidPosixAttrib: prop = (UInt32)_fileInfo.GetPosixAttrib(); break; case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break; case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break; case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break; default: break; } prop.Detach(value); return S_OK; COM_TRY_END } // ---------- CInFileStreamVol ---------- Z7_class_final(CInFileStreamVol): public IInStream , public IStreamGetSize , public CMyUnknownImp { Z7_IFACES_IMP_UNK_3( IInStream, ISequentialInStream, IStreamGetSize) public: unsigned FileIndex; COpenCallbackImp *OpenCallbackImp; CMyComPtr OpenCallbackRef; HRESULT EnsureOpen() { return OpenCallbackImp->Volumes.EnsureOpen(FileIndex); } ~CInFileStreamVol() { if (OpenCallbackRef) OpenCallbackImp->AtCloseFile(FileIndex); } }; void CMultiStreams::InsertToList(unsigned index) { { CSubStream &s = Streams[index]; s.Next = Head; s.Prev = -1; } if (Head != -1) Streams[(unsigned)Head].Prev = (int)index; else { // if (Tail != -1) throw 1; Tail = (int)index; } Head = (int)index; NumListItems++; } // s must bee in List void CMultiStreams::RemoveFromList(CSubStream &s) { if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev; if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next; s.Next = -1; // optional s.Prev = -1; // optional NumListItems--; } void CMultiStreams::CloseFile(unsigned index) { CSubStream &s = Streams[index]; if (s.Stream) { s.Stream.Release(); RemoveFromList(s); // s.InFile->Close(); // s.IsOpen = false; #ifdef DEBUG_VOLUMES static int numClosing = 0; numClosing++; printf("\nCloseFile %u, total_closes = %u, num_open_files = %u\n", index, numClosing, NumListItems); #endif } } void CMultiStreams::Init() { Head = -1; Tail = -1; NumListItems = 0; Streams.Clear(); } CMultiStreams::CMultiStreams(): Head(-1), Tail(-1), NumListItems(0) { NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks(); PRF(printf("\nNumOpenFiles_Limit = %u\n", NumOpenFiles_AllowedMax)); } HRESULT CMultiStreams::PrepareToOpenNew() { if (NumListItems < NumOpenFiles_AllowedMax) return S_OK; if (Tail == -1) return E_FAIL; CMultiStreams::CSubStream &tailStream = Streams[(unsigned)Tail]; RINOK(InStream_GetPos(tailStream.Stream, tailStream.LocalPos)) CloseFile((unsigned)Tail); return S_OK; } HRESULT CMultiStreams::EnsureOpen(unsigned index) { CMultiStreams::CSubStream &s = Streams[index]; if (s.Stream) { if ((int)index != Head) { RemoveFromList(s); InsertToList(index); } } else { RINOK(PrepareToOpenNew()) { CInFileStream *inFile = new CInFileStream; CMyComPtr inStreamTemp = inFile; if (!inFile->Open(s.Path)) return GetLastError_noZero_HRESULT(); s.FileSpec = inFile; s.Stream = s.FileSpec; InsertToList(index); } // s.IsOpen = true; if (s.LocalPos != 0) { RINOK(s.Stream->Seek((Int64)s.LocalPos, STREAM_SEEK_SET, &s.LocalPos)) } #ifdef DEBUG_VOLUMES static int numOpens = 0; numOpens++; printf("\n-- %u, ReOpen, total_reopens = %u, num_open_files = %u\n", index, numOpens, NumListItems); #endif } return S_OK; } Z7_COM7F_IMF(CInFileStreamVol::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; RINOK(EnsureOpen()) CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex]; PRF(printf("\n== %u, Read =%u \n", FileIndex, size)); return s.Stream->Read(data, size, processedSize); } Z7_COM7F_IMF(CInFileStreamVol::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) { // if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; RINOK(EnsureOpen()) CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex]; PRF(printf("\n-- %u, Seek seekOrigin=%u Seek =%u\n", FileIndex, seekOrigin, (unsigned)offset)); return s.Stream->Seek(offset, seekOrigin, newPosition); } Z7_COM7F_IMF(CInFileStreamVol::GetSize(UInt64 *size)) { RINOK(EnsureOpen()) CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex]; return s.FileSpec->GetSize(size); } // from ArchiveExtractCallback.cpp bool IsSafePath(const UString &path); Z7_COM7F_IMF(COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)) { COM_TRY_BEGIN *inStream = NULL; if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()) } UString name2 = name; #ifndef Z7_SFX #ifdef _WIN32 name2.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif // if (!allowAbsVolPaths) if (!IsSafePath(name2)) return S_FALSE; #ifdef _WIN32 /* WIN32 allows wildcards in Find() function and doesn't allow wildcard in File.Open() so we can work without the following wildcard check here */ if (name2.Find(L'*') >= 0) return S_FALSE; { unsigned startPos = 0; if (name2.IsPrefixedBy_Ascii_NoCase("\\\\?\\")) startPos = 3; if (name2.Find(L'?', startPos) >= 0) return S_FALSE; } #endif #endif FString fullPath; if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath)) return S_FALSE; if (!_fileInfo.Find_FollowLink(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CMultiStreams::CSubStream s; { CInFileStream *inFile = new CInFileStream; CMyComPtr inStreamTemp = inFile; if (!inFile->Open(fullPath)) return GetLastError_noZero_HRESULT(); RINOK(Volumes.PrepareToOpenNew()) s.FileSpec = inFile; s.Stream = s.FileSpec; s.Path = fullPath; // s.Size = _fileInfo.Size; // s.IsOpen = true; } const unsigned fileIndex = Volumes.Streams.Add(s); Volumes.InsertToList(fileIndex); FileSizes.Add(_fileInfo.Size); FileNames.Add(name2); FileNames_WasUsed.Add(true); CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr inStreamTemp = inFile; inFile->FileIndex = fileIndex; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; // TotalSize += _fileInfo.Size; *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } #ifndef Z7_NO_CRYPTO Z7_COM7F_IMF(COpenCallbackImp::CryptoGetTextPassword(BSTR *password)) { COM_TRY_BEGIN if (ReOpenCallback) { Z7_DECL_CMyComPtr_QI_FROM( ICryptoGetTextPassword, getTextPassword, ReOpenCallback) if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; PasswordWasAsked = true; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif // IProgress Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */)) { return S_OK; } Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */)) { return S_OK; } tmp41wklro_/CPP/7zip/UI/Common/ArchiveOpenCallback.h0000444000175000001440000001161714574114040023220 0ustar nabijaczleweliusers// ArchiveOpenCallback.h #ifndef ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H #define ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H #include "../../../Common/MyCom.h" #include "../../../Windows/FileFind.h" #include "../../Common/FileStreams.h" #ifndef Z7_NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" Z7_PURE_INTERFACES_BEGIN #ifdef Z7_NO_CRYPTO #define Z7_IFACEM_IOpenCallbackUI_Crypto(x) #else #define Z7_IFACEM_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x \ /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x */ \ /* virtual bool Open_WasPasswordAsked() x */ \ /* virtual void Open_Clear_PasswordWasAsked_Flag() x */ \ #endif #define Z7_IFACEN_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x \ virtual HRESULT Open_Finished() x \ Z7_IFACEM_IOpenCallbackUI_Crypto(x) Z7_IFACE_DECL_PURE(IOpenCallbackUI) Z7_PURE_INTERFACES_END class CMultiStreams Z7_final { public: struct CSubStream { CMyComPtr Stream; CInFileStream *FileSpec; FString Path; // UInt64 Size; UInt64 LocalPos; int Next; // next older int Prev; // prev newer // bool IsOpen; CSubStream(): FileSpec(NULL), // Size(0), LocalPos(0), Next(-1), Prev(-1) // IsOpen(false) {} }; CObjectVector Streams; private: // we must use critical section here, if we want to access from different volumnes simultaneously int Head; // newest int Tail; // oldest unsigned NumListItems; unsigned NumOpenFiles_AllowedMax; public: CMultiStreams(); void Init(); HRESULT PrepareToOpenNew(); void InsertToList(unsigned index); void RemoveFromList(CSubStream &s); void CloseFile(unsigned index); HRESULT EnsureOpen(unsigned index); }; /* We need COpenCallbackImp class for multivolume processing. Also we use it as proxy from COM interfaces (IArchiveOpenCallback) to internal (IOpenCallbackUI) interfaces. If archive is multivolume: COpenCallbackImp object will exist after Open stage. COpenCallbackImp object will be deleted when last reference from each volume object (CInFileStreamVol) will be closed (when archive will be closed). */ class COpenCallbackImp Z7_final: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef Z7_NO_CRYPTO public ICryptoGetTextPassword, #endif public IProgress, // IProgress is used for 7zFM public CMyUnknownImp { Z7_COM_QI_BEGIN2(IArchiveOpenCallback) Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback) Z7_COM_QI_ENTRY(IArchiveOpenSetSubArchiveName) #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY(ICryptoGetTextPassword) #endif // Z7_COM_QI_ENTRY(IProgress) // the code doesn't require it Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IArchiveOpenCallback) Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback) Z7_IFACE_COM7_IMP(IProgress) public: Z7_IFACE_COM7_IMP(IArchiveOpenSetSubArchiveName) private: #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) #endif bool _subArchiveMode; public: bool PasswordWasAsked; UStringVector FileNames; CBoolVector FileNames_WasUsed; CRecordVector FileSizes; void AtCloseFile(unsigned fileIndex) { FileNames_WasUsed[fileIndex] = false; Volumes.CloseFile(fileIndex); } /* we have two ways to Callback from this object 1) IArchiveOpenCallback * ReOpenCallback - for ReOpen function, when IOpenCallbackUI is not available 2) IOpenCallbackUI *Callback - for usual callback we can't transfer IOpenCallbackUI pointer via internal interface, so we use ReOpenCallback to callback without IOpenCallbackUI. */ /* we use Callback/ReOpenCallback only at Open stage. So the CMyComPtr reference counter is not required, and we don't want additional reference to unused object, if COpenCallbackImp is not closed */ IArchiveOpenCallback *ReOpenCallback; // CMyComPtr ReOpenCallback; IOpenCallbackUI *Callback; // CMyComPtr Callback_Ref; private: FString _folderPrefix; UString _subArchiveName; NWindows::NFile::NFind::CFileInfo _fileInfo; public: CMultiStreams Volumes; // UInt64 TotalSize; COpenCallbackImp(): _subArchiveMode(false), PasswordWasAsked(false), ReOpenCallback(NULL), Callback(NULL) {} HRESULT Init2(const FString &folderPrefix, const FString &fileName); bool SetSecondFileInfo(CFSTR newName) { return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir(); } }; #endif tmp41wklro_/CPP/7zip/UI/Common/Bench.cpp0000444000175000001440000036410014655644060020762 0ustar nabijaczleweliusers// Bench.cpp #include "StdAfx.h" // #include #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif // _WIN32 #ifdef USE_POSIX_TIME #include #include #ifdef USE_POSIX_TIME2 #include #include #endif #endif // USE_POSIX_TIME #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include #else #include #endif #define BENCH_ALLOCA_VALUE(index) (((index) * 64 * 21) & 0x7FF) #endif #include "../../../../C/7zCrc.h" #include "../../../../C/RotateDefs.h" #include "../../../../C/CpuArch.h" #ifndef Z7_ST #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #include "../../../Windows/FileFind.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/SystemInfo.h" #include "../../../Common/MyBuffer2.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../../Common/Wildcard.h" #include "../../Common/MethodProps.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "Bench.h" using namespace NWindows; #ifndef Z7_ST static const UInt32 k_LZMA = 0x030101; #endif static const UInt64 kComplexInCommands = (UInt64)1 << #ifdef UNDER_CE 31; #else 34; #endif static const UInt32 kComplexInMs = 4000; static void SetComplexCommandsMs(UInt32 complexInMs, bool isSpecifiedFreq, UInt64 cpuFreq, UInt64 &complexInCommands) { complexInCommands = kComplexInCommands; const UInt64 kMinFreq = (UInt64)1000000 * 4; const UInt64 kMaxFreq = (UInt64)1000000 * 20000; if (cpuFreq < kMinFreq && !isSpecifiedFreq) cpuFreq = kMinFreq; if (cpuFreq < kMaxFreq || isSpecifiedFreq) { if (complexInMs != 0) complexInCommands = complexInMs * cpuFreq / 1000; else complexInCommands = cpuFreq >> 2; } } // const UInt64 kBenchmarkUsageMult = 1000000; // for debug static const unsigned kBenchmarkUsageMultBits = 16; static const UInt64 kBenchmarkUsageMult = 1 << kBenchmarkUsageMultBits; UInt64 Benchmark_GetUsage_Percents(UInt64 usage) { return (100 * usage + kBenchmarkUsageMult / 2) / kBenchmarkUsageMult; } static const unsigned kNumHashDictBits = 17; static const UInt32 kFilterUnpackSize = (47 << 10); // + 5; // for test static const unsigned kOldLzmaDictBits = 32; // static const size_t kAdditionalSize = (size_t)1 << 32; // for debug static const size_t kAdditionalSize = (size_t)1 << 16; static const size_t kCompressedAdditionalSize = 1 << 10; static const UInt32 kMaxMethodPropSize = 1 << 6; #define ALLOC_WITH_HRESULT(_buffer_, _size_) \ { (_buffer_)->Alloc(_size_); \ if (_size_ && !(_buffer_)->IsAllocated()) return E_OUTOFMEMORY; } class CBaseRandomGenerator { UInt32 A1; UInt32 A2; UInt32 Salt; public: CBaseRandomGenerator(UInt32 salt = 0): Salt(salt) { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} Z7_FORCE_INLINE UInt32 GetRnd() { #if 0 // for debug: return 0x0c080400; // return 0; #else return Salt ^ ( ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ) ); #endif } }; static const size_t k_RandBuf_AlignMask = 4 - 1; Z7_NO_INLINE static void RandGen_BufAfterPad(Byte *buf, size_t size) { CBaseRandomGenerator RG; for (size_t i = 0; i < size; i += 4) { const UInt32 v = RG.GetRnd(); SetUi32a(buf + i, v) } /* UInt32 v = RG.GetRnd(); for (; i < size; i++) { buf[i] = (Byte)v; v >>= 8; } */ } class CBenchRandomGenerator: public CMidAlignedBuffer { static UInt32 GetVal(UInt32 &res, unsigned numBits) { const UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } static UInt32 GetLen(UInt32 &r) { const unsigned len = (unsigned)GetVal(r, 2); return GetVal(r, 1 + len); } public: void GenerateSimpleRandom(UInt32 salt) { CBaseRandomGenerator rg(salt); const size_t bufSize = Size(); Byte *buf = (Byte *)*this; for (size_t i = 0; i < bufSize; i++) buf[i] = (Byte)rg.GetRnd(); } void GenerateLz(unsigned dictBits, UInt32 salt) { CBaseRandomGenerator rg(salt); size_t pos = 0; size_t rep0 = 1; const size_t bufSize = Size(); Byte *buf = (Byte *)*this; unsigned posBits = 1; // printf("\n dictBits = %d\n", (UInt32)dictBits); // printf("\n bufSize = 0x%p\n", (const void *)bufSize); while (pos < bufSize) { /* if (pos >= ((UInt32)1 << 31)) printf(" %x\n", pos); */ UInt32 r = rg.GetRnd(); if (GetVal(r, 1) == 0 || pos < 1024) buf[pos++] = (Byte)(r & 0xFF); else { UInt32 len; len = 1 + GetLen(r); if (GetVal(r, 3) != 0) { len += GetLen(r); while (((size_t)1 << posBits) < pos) posBits++; unsigned numBitsMax = dictBits; if (numBitsMax > posBits) numBitsMax = posBits; const unsigned kAddBits = 6; unsigned numLogBits = 5; if (numBitsMax <= (1 << 4) - 1 + kAddBits) numLogBits = 4; for (;;) { const UInt32 ppp = GetVal(r, numLogBits) + kAddBits; r = rg.GetRnd(); if (ppp > numBitsMax) continue; // rep0 = GetVal(r, ppp); rep0 = r & (((size_t)1 << ppp) - 1); if (rep0 < pos) break; r = rg.GetRnd(); } rep0++; } // len *= 300; // for debug { const size_t rem = bufSize - pos; if (len > rem) len = (UInt32)rem; } Byte *dest = buf + pos; const Byte *src = dest - rep0; pos += len; for (UInt32 i = 0; i < len; i++) *dest++ = *src++; } } // printf("\n CRC = %x\n", CrcCalc(buf, bufSize)); } }; Z7_CLASS_IMP_NOQIB_1( CBenchmarkInStream , ISequentialInStream ) const Byte *Data; size_t Pos; size_t Size; public: void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } bool WasFinished() const { return Pos == Size; } }; Z7_COM7F_IMF(CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { const UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; const size_t remain = Size - Pos; if (size > remain) size = (UInt32)remain; if (size) memcpy(data, Data + Pos, size); Pos += size; if (processedSize) *processedSize = size; return S_OK; } class CBenchmarkOutStream Z7_final: public ISequentialOutStream, public CMyUnknownImp, public CMidAlignedBuffer { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(ISequentialOutStream) // bool _overflow; public: size_t Pos; bool RealCopy; bool CalcCrc; UInt32 Crc; // CBenchmarkOutStream(): _overflow(false) {} void Init(bool realCopy, bool calcCrc) { Crc = CRC_INIT_VAL; RealCopy = realCopy; CalcCrc = calcCrc; // _overflow = false; Pos = 0; } void InitCrc() { Crc = CRC_INIT_VAL; } void Calc(const void *data, size_t size) { Crc = CrcUpdate(Crc, data, size); } size_t GetPos() const { return Pos; } // void Print() { printf("\n%8d %8d\n", (unsigned)BufferSize, (unsigned)Pos); } }; Z7_COM7F_IMF(CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { size_t curSize = Size() - Pos; if (curSize > size) curSize = size; if (curSize != 0) { if (RealCopy) memcpy(((Byte *)*this) + Pos, data, curSize); if (CalcCrc) Calc(data, curSize); Pos += curSize; } if (processedSize) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } Z7_CLASS_IMP_NOQIB_1( CCrcOutStream , ISequentialOutStream ) public: bool CalcCrc; UInt32 Crc; UInt64 Pos; CCrcOutStream(): CalcCrc(true) {} void Init() { Crc = CRC_INIT_VAL; Pos = 0; } void Calc(const void *data, size_t size) { Crc = CrcUpdate(Crc, data, size); } }; Z7_COM7F_IMF(CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (CalcCrc) Calc(data, size); Pos += size; if (processedSize) *processedSize = size; return S_OK; } // #include "../../../../C/My_sys_time.h" static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, NULL) == 0) return (UInt64)(v.tv_sec) * 1000000 + (UInt64)v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return (UInt64)value.QuadPart; return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return (UInt64)value.QuadPart; return 1000; #endif } #ifdef USE_POSIX_TIME struct CUserTime { UInt64 Sum; clock_t Prev; void Init() { // Prev = clock(); Sum = 0; Prev = 0; Update(); Sum = 0; } void Update() { tms t; /* clock_t res = */ times(&t); clock_t newVal = t.tms_utime + t.tms_stime; Sum += (UInt64)(newVal - Prev); Prev = newVal; /* clock_t v = clock(); if (v != -1) { Sum += v - Prev; Prev = v; } */ } UInt64 GetUserTime() { Update(); return Sum; } }; #else struct CUserTime { bool UseTick; DWORD Prev_Tick; UInt64 Prev; UInt64 Sum; void Init() { UseTick = false; Prev_Tick = 0; Prev = 0; Sum = 0; Update(); Sum = 0; } UInt64 GetUserTime() { Update(); return Sum; } void Update(); }; static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } void CUserTime::Update() { DWORD new_Tick = GetTickCount(); FILETIME creationTime, exitTime, kernelTime, userTime; if (!UseTick && #ifdef UNDER_CE ::GetThreadTimes(::GetCurrentThread() #else ::GetProcessTimes(::GetCurrentProcess() #endif , &creationTime, &exitTime, &kernelTime, &userTime)) { UInt64 newVal = GetTime64(userTime) + GetTime64(kernelTime); Sum += newVal - Prev; Prev = newVal; } else { UseTick = true; Sum += (UInt64)(new_Tick - (DWORD)Prev_Tick) * 10000; } Prev_Tick = new_Tick; } #endif static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME // return CLOCKS_PER_SEC; return (UInt64)sysconf(_SC_CLK_TCK); #else return 10000000; #endif } class CBenchProgressStatus Z7_final { #ifndef Z7_ST NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifndef Z7_ST NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifndef Z7_ST NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; struct CBenchInfoCalc { CBenchInfo BenchInfo; CUserTime UserTime; void SetStartTime(); void SetFinishTime(CBenchInfo &dest); }; void CBenchInfoCalc::SetStartTime() { BenchInfo.GlobalFreq = GetFreq(); BenchInfo.UserFreq = GetUserFreq(); BenchInfo.GlobalTime = ::GetTimeCount(); BenchInfo.UserTime = 0; UserTime.Init(); } void CBenchInfoCalc::SetFinishTime(CBenchInfo &dest) { dest = BenchInfo; dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime; dest.UserTime = UserTime.GetUserTime(); } class CBenchProgressInfo Z7_final: public ICompressProgressInfo, public CMyUnknownImp, public CBenchInfoCalc { Z7_COM_UNKNOWN_IMP_0 Z7_IFACE_COM7_IMP(ICompressProgressInfo) public: CBenchProgressStatus *Status; IBenchCallback *Callback; CBenchProgressInfo(): Callback(NULL) {} }; Z7_COM7F_IMF(CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!Callback) return res; /* static UInt64 inSizePrev = 0; static UInt64 outSizePrev = 0; UInt64 delta1 = 0, delta2 = 0, val1 = 0, val2 = 0; if (inSize) { val1 = *inSize; delta1 = val1 - inSizePrev; inSizePrev = val1; } if (outSize) { val2 = *outSize; delta2 = val2 - outSizePrev; outSizePrev = val2; } UInt64 percents = delta2 * 1000; if (delta1 != 0) percents /= delta1; printf("=== %7d %7d %7d %7d ratio = %4d\n", (unsigned)(val1 >> 10), (unsigned)(delta1 >> 10), (unsigned)(val2 >> 10), (unsigned)(delta2 >> 10), (unsigned)percents); */ CBenchInfo info; SetFinishTime(info); if (Status->EncodeMode) { info.UnpackSize = BenchInfo.UnpackSize + *inSize; info.PackSize = BenchInfo.PackSize + *outSize; res = Callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = Callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const unsigned kSubBits = 8; static unsigned GetLogSize(UInt64 size) { unsigned i = 0; for (;;) { i++; size >>= 1; if (size == 0) break; } return i; } static UInt32 GetLogSize_Sub(UInt64 size) { if (size <= 1) return 0; const unsigned i = GetLogSize(size) - 1; UInt32 v; if (i <= kSubBits) v = (UInt32)(size) << (kSubBits - i); else v = (UInt32)(size >> (i - kSubBits)); return ((UInt32)i << kSubBits) + (v & (((UInt32)1 << kSubBits) - 1)); } static UInt64 Get_UInt64_from_double(double v) { const UInt64 kMaxVal = (UInt64)1 << 62; if (v > (double)(Int64)kMaxVal) return kMaxVal; return (UInt64)v; } static UInt64 MyMultDiv64(UInt64 m1, UInt64 m2, UInt64 d) { if (d == 0) d = 1; const double v = (double)(Int64)m1 * (double)(Int64)m2 / (double)(Int64)d; return Get_UInt64_from_double(v); /* unsigned n1 = GetLogSize(m1); unsigned n2 = GetLogSize(m2); while (n1 + n2 > 64) { if (n1 >= n2) { m1 >>= 1; n1--; } else { m2 >>= 1; n2--; } d >>= 1; } if (d == 0) d = 1; return m1 * m2 / d; */ } UInt64 CBenchInfo::GetUsage() const { UInt64 userTime = UserTime; UInt64 userFreq = UserFreq; UInt64 globalTime = GlobalTime; UInt64 globalFreq = GlobalFreq; if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; const double v = ((double)(Int64)userTime / (double)(Int64)userFreq) * ((double)(Int64)globalFreq / (double)(Int64)globalTime) * (double)(Int64)kBenchmarkUsageMult; return Get_UInt64_from_double(v); /* return MyMultDiv64( MyMultDiv64(kBenchmarkUsageMult, userTime, userFreq), globalFreq, globalTime); */ } UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const { if (UserTime == 0) { return 0; // userTime = 1; } UInt64 globalFreq = GlobalFreq; if (globalFreq == 0) globalFreq = 1; const double v = ((double)(Int64)GlobalTime / (double)(Int64)globalFreq) * ((double)(Int64)UserFreq / (double)(Int64)UserTime) * (double)(Int64)rating; return Get_UInt64_from_double(v); /* return MyMultDiv64( MyMultDiv64(rating, UserFreq, UserTime), GlobalTime, globalFreq); */ } UInt64 CBenchInfo::GetSpeed(UInt64 numUnits) const { return MyMultDiv64(numUnits, GlobalFreq, GlobalTime); } static UInt64 GetNumCommands_from_Size_and_Complexity(UInt64 size, Int32 complexity) { return complexity >= 0 ? size * (UInt32)complexity : size / (UInt32)(-complexity); } struct CBenchProps { bool LzmaRatingMode; Int32 EncComplex; Int32 DecComplexCompr; Int32 DecComplexUnc; unsigned KeySize; CBenchProps(): LzmaRatingMode(false), KeySize(0) {} void SetLzmaCompexity(); UInt64 GetNumCommands_Enc(UInt64 unpackSize) const { const UInt32 kMinSize = 100; if (unpackSize < kMinSize) unpackSize = kMinSize; return GetNumCommands_from_Size_and_Complexity(unpackSize, EncComplex); } UInt64 GetNumCommands_Dec(UInt64 packSize, UInt64 unpackSize) const { return GetNumCommands_from_Size_and_Complexity(packSize, DecComplexCompr) + GetNumCommands_from_Size_and_Complexity(unpackSize, DecComplexUnc); } UInt64 GetRating_Enc(UInt64 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size) const; UInt64 GetRating_Dec(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations) const; }; void CBenchProps::SetLzmaCompexity() { EncComplex = 1200; DecComplexUnc = 4; DecComplexCompr = 190; LzmaRatingMode = true; } UInt64 CBenchProps::GetRating_Enc(UInt64 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size) const { if (dictSize < (1 << kBenchMinDicLogSize)) dictSize = (1 << kBenchMinDicLogSize); Int32 encComplex = EncComplex; if (LzmaRatingMode) { /* for (UInt64 uu = 0; uu < (UInt64)0xf << 60;) { unsigned rr = GetLogSize_Sub(uu); printf("\n%16I64x , log = %4x", uu, rr); uu += 1; uu += uu / 50; } */ // throw 1; const UInt32 t = GetLogSize_Sub(dictSize) - (kBenchMinDicLogSize << kSubBits); encComplex = 870 + ((t * t * 5) >> (2 * kSubBits)); } const UInt64 numCommands = GetNumCommands_from_Size_and_Complexity(size, encComplex); return MyMultDiv64(numCommands, freq, elapsedTime); } UInt64 CBenchProps::GetRating_Dec(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations) const { const UInt64 numCommands = GetNumCommands_Dec(inSize, outSize) * numIterations; return MyMultDiv64(numCommands, freq, elapsedTime); } UInt64 CBenchInfo::GetRating_LzmaEnc(UInt64 dictSize) const { CBenchProps props; props.SetLzmaCompexity(); return props.GetRating_Enc(dictSize, GlobalTime, GlobalFreq, UnpackSize * NumIterations); } UInt64 CBenchInfo::GetRating_LzmaDec() const { CBenchProps props; props.SetLzmaCompexity(); return props.GetRating_Dec(GlobalTime, GlobalFreq, UnpackSize, PackSize, NumIterations); } #ifndef Z7_ST #define NUM_CPU_LEVELS_MAX 3 struct CAffinityMode { unsigned NumBundleThreads; unsigned NumLevels; unsigned NumCoreThreads; unsigned NumCores; // unsigned DivideNum; UInt32 Sizes[NUM_CPU_LEVELS_MAX]; void SetLevels(unsigned numCores, unsigned numCoreThreads); DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; bool NeedAffinity() const { return NumBundleThreads != 0; } WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_TYPE startAddress, LPVOID parameter, UInt32 bundleIndex) const { if (NeedAffinity()) { CCpuSet cpuSet; GetAffinityMask(bundleIndex, &cpuSet); return thread.Create_With_CpuSet(startAddress, parameter, &cpuSet); } return thread.Create(startAddress, parameter); } CAffinityMode(): NumBundleThreads(0), NumLevels(0), NumCoreThreads(1) // DivideNum(1) {} }; void CAffinityMode::SetLevels(unsigned numCores, unsigned numCoreThreads) { NumCores = numCores; NumCoreThreads = numCoreThreads; NumLevels = 0; if (numCoreThreads == 0 || numCores == 0 || numCores % numCoreThreads != 0) return; UInt32 c = numCores / numCoreThreads; UInt32 c2 = 1; while ((c & 1) == 0) { c >>= 1; c2 <<= 1; } if (c2 != 1) Sizes[NumLevels++] = c2; if (c != 1) Sizes[NumLevels++] = c; if (numCoreThreads != 1) Sizes[NumLevels++] = numCoreThreads; if (NumLevels == 0) Sizes[NumLevels++] = 1; /* printf("\n Cores:"); for (unsigned i = 0; i < NumLevels; i++) { printf(" %d", Sizes[i]); } printf("\n"); */ } DWORD_PTR CAffinityMode::GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const { CpuSet_Zero(cpuSet); if (NumLevels == 0) return 0; // printf("\n%2d", bundleIndex); /* UInt32 low = 0; if (DivideNum != 1) { low = bundleIndex % DivideNum; bundleIndex /= DivideNum; } */ UInt32 numGroups = NumCores / NumBundleThreads; UInt32 m = bundleIndex % numGroups; UInt32 v = 0; for (unsigned i = 0; i < NumLevels; i++) { UInt32 size = Sizes[i]; while ((size & 1) == 0) { v *= 2; v |= (m & 1); m >>= 1; size >>= 1; } v *= size; v += m % size; m /= size; } // UInt32 nb = NumBundleThreads / DivideNum; UInt32 nb = NumBundleThreads; DWORD_PTR mask = ((DWORD_PTR)1 << nb) - 1; // v += low; mask <<= v; // printf(" %2d %8x \n ", v, (unsigned)mask); #ifdef _WIN32 *cpuSet = mask; #else { for (unsigned k = 0; k < nb; k++) CpuSet_Set(cpuSet, v + k); } #endif return mask; } struct CBenchSyncCommon { bool ExitMode; NSynchronization::CManualResetEvent StartEvent; CBenchSyncCommon(): ExitMode(false) {} }; #endif enum E_CheckCrcMode { k_CheckCrcMode_Never = 0, k_CheckCrcMode_Always = 1, k_CheckCrcMode_FirstPass = 2 }; class CEncoderInfo; class CEncoderInfo Z7_final { Z7_CLASS_NO_COPY(CEncoderInfo) public: #ifndef Z7_ST NWindows::CThread thread[2]; NSynchronization::CManualResetEvent ReadyEvent; UInt32 NumDecoderSubThreads; CBenchSyncCommon *Common; UInt32 EncoderIndex; UInt32 NumEncoderInternalThreads; CAffinityMode AffinityMode; bool IsGlobalMtMode; // if more than one benchmark encoder threads #endif CMyComPtr _encoder; CMyComPtr _encoderFilter; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr progressInfo[2]; UInt64 NumIterations; UInt32 Salt; #ifdef USE_ALLOCA size_t AllocaSize; #endif unsigned KeySize; Byte _key[32]; Byte _iv[16]; HRESULT Set_Key_and_IV(ICryptoProperties *cp) { RINOK(cp->SetKey(_key, KeySize)) return cp->SetInitVector(_iv, sizeof(_iv)); } Byte _psw[16]; bool CheckCrc_Enc; /* = 1, if we want to check packed data crcs after each pass used for filter and usual coders */ bool UseRealData_Enc; /* = 1, if we want to use only original data for each pass used only for filter */ E_CheckCrcMode CheckCrcMode_Dec; struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; bool CallbackMode; #ifdef USE_ALLOCA size_t AllocaSize; #endif }; CDecoderInfo decodersInfo[2]; CMyComPtr _decoders[2]; CMyComPtr _decoderFilter; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr outStream; IBenchCallback *callback; IBenchPrintCallback *printCallback; UInt32 crc; size_t kBufferSize; size_t compressedSize; const Byte *uncompressedDataPtr; const Byte *fileData; CBenchRandomGenerator rg; CMidAlignedBuffer rgCopy; // it must be 16-byte aligned !!! // CBenchmarkOutStream *propStreamSpec; Byte propsData[kMaxMethodPropSize]; CBufPtrSeqOutStream *propStreamSpec; CMyComPtr propStream; unsigned generateDictBits; COneMethodInfo _method; // for decode size_t _uncompressedDataSize; HRESULT Generate(); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): #ifndef Z7_ST Common(NULL), IsGlobalMtMode(true), #endif Salt(0), KeySize(0), CheckCrc_Enc(true), UseRealData_Enc(true), CheckCrcMode_Dec(k_CheckCrcMode_Always), outStreamSpec(NULL), callback(NULL), printCallback(NULL), fileData(NULL), propStreamSpec(NULL) {} #ifndef Z7_ST static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { HRESULT res; CEncoderInfo *encoder = (CEncoderInfo *)param; try { #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif res = encoder->Encode(); } catch(...) { res = E_FAIL; } encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); encoder->ReadyEvent.Set(); return THREAD_FUNC_RET_ZERO; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); // printf("\nalloca=%d\n", (unsigned)decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return THREAD_FUNC_RET_ZERO; } HRESULT CreateEncoderThread() { WRes res = 0; if (!ReadyEvent.IsCreated()) res = ReadyEvent.Create(); if (res == 0) res = AffinityMode.CreateThread_WithAffinity(thread[0], EncodeThreadFunction, this, EncoderIndex); return HRESULT_FROM_WIN32(res); } HRESULT CreateDecoderThread(unsigned index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; WRes res = AffinityMode.CreateThread_WithAffinity(thread[index], DecodeThreadFunction, &decoder, // EncoderIndex * NumEncoderInternalThreads + index EncoderIndex ); return HRESULT_FROM_WIN32(res); } #endif }; static size_t GetBenchCompressedSize(size_t bufferSize) { return kCompressedAdditionalSize + bufferSize + bufferSize / 16; // kBufferSize / 2; } HRESULT CEncoderInfo::Generate() { const COneMethodInfo &method = _method; // we need extra space, if input data is already compressed const size_t kCompressedBufferSize = _encoderFilter ? kBufferSize : GetBenchCompressedSize(kBufferSize); if (kCompressedBufferSize < kBufferSize) return E_FAIL; uncompressedDataPtr = fileData; if (fileData) { #if !defined(Z7_ST) if (IsGlobalMtMode) { /* we copy the data to local buffer of thread to eliminate using of shared buffer by different threads */ ALLOC_WITH_HRESULT(&rg, kBufferSize) memcpy((Byte *)rg, fileData, kBufferSize); uncompressedDataPtr = (const Byte *)rg; } #endif } else { ALLOC_WITH_HRESULT(&rg, kBufferSize) // DWORD ttt = GetTickCount(); if (generateDictBits == 0) rg.GenerateSimpleRandom(Salt); else { if (generateDictBits >= sizeof(size_t) * 8 && kBufferSize > ((size_t)1 << (sizeof(size_t) * 8 - 1))) return E_INVALIDARG; rg.GenerateLz(generateDictBits, Salt); // return E_ABORT; // for debug } // printf("\n%d\n ", GetTickCount() - ttt); crc = CrcCalc((const Byte *)rg, rg.Size()); uncompressedDataPtr = (const Byte *)rg; } if (!outStream) { outStreamSpec = new CBenchmarkOutStream; outStream = outStreamSpec; } ALLOC_WITH_HRESULT(outStreamSpec, kCompressedBufferSize) if (_encoderFilter) { /* we try to reduce the number of memcpy() in main encoding loop. so we copy data to temp buffers here */ ALLOC_WITH_HRESULT(&rgCopy, kBufferSize) memcpy((Byte *)*outStreamSpec, uncompressedDataPtr, kBufferSize); memcpy((Byte *)rgCopy, uncompressedDataPtr, kBufferSize); } if (!propStream) { propStreamSpec = new CBufPtrSeqOutStream; // CBenchmarkOutStream; propStream = propStreamSpec; } // ALLOC_WITH_HRESULT_2(propStreamSpec, kMaxMethodPropSize); // propStreamSpec->Init(true, false); propStreamSpec->Init(propsData, sizeof(propsData)); CMyComPtr coder; if (_encoderFilter) coder = _encoderFilter; else coder = _encoder; { CMyComPtr scp; coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { const UInt64 reduceSize = kBufferSize; /* in posix new thread uses same affinity as parent thread, so we don't need to send affinity to coder in posix */ UInt64 affMask; #if !defined(Z7_ST) && defined(_WIN32) { CCpuSet cpuSet; affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); } #else affMask = 0; #endif // affMask <<= 3; // debug line: to test no affinity in coder; // affMask = 0; RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, (affMask != 0 ? &affMask : NULL))) } else { if (method.AreThereNonOptionalProps()) return E_INVALIDARG; } CMyComPtr writeCoderProps; coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); if (writeCoderProps) { RINOK(writeCoderProps->WriteCoderProperties(propStream)) } { CMyComPtr sp; coder.QueryInterface(IID_ICryptoSetPassword, &sp); if (sp) { RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))) // we must call encoding one time to calculate password key for key cache. // it must be after WriteCoderProperties! Byte temp[16]; memset(temp, 0, sizeof(temp)); if (_encoderFilter) { _encoderFilter->Init(); _encoderFilter->Filter(temp, sizeof(temp)); } else { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; inStreamSpec->Init(temp, sizeof(temp)); CCrcOutStream *crcStreamSpec = new CCrcOutStream; CMyComPtr crcStream = crcStreamSpec; crcStreamSpec->Init(); RINOK(_encoder->Code(inStream, crcStream, NULL, NULL, NULL)) } } } } return S_OK; } static void My_FilterBench(ICompressFilter *filter, Byte *data, size_t size, UInt32 *crc) { while (size != 0) { UInt32 cur = crc ? 1 << 17 : 1 << 24; if (cur > size) cur = (UInt32)size; UInt32 processed = filter->Filter(data, cur); /* if (processed > size) (in AES filter), we must fill last block with zeros. but it is not important for benchmark. So we just copy that data without filtering. if (processed == 0) then filter can't process more */ if (processed > size || processed == 0) processed = (UInt32)size; if (crc) *crc = CrcUpdate(*crc, data, processed); data += processed; size -= processed; } } HRESULT CEncoderInfo::Encode() { // printf("\nCEncoderInfo::Generate\n"); RINOK(Generate()) // printf("\n2222\n"); #ifndef Z7_ST if (Common) { Results[0] = S_OK; WRes wres = ReadyEvent.Set(); if (wres == 0) wres = Common->StartEvent.Lock(); if (wres != 0) return HRESULT_FROM_WIN32(wres); if (Common->ExitMode) return S_OK; } else #endif { CBenchProgressInfo *bpi = progressInfoSpec[0]; bpi->SetStartTime(); } CBenchInfo &bi = progressInfoSpec[0]->BenchInfo; bi.UnpackSize = 0; bi.PackSize = 0; CMyComPtr cp; CMyComPtr coder; if (_encoderFilter) coder = _encoderFilter; else coder = _encoder; coder.QueryInterface(IID_ICryptoProperties, &cp); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; if (cp) { RINOK(Set_Key_and_IV(cp)) } compressedSize = 0; if (_encoderFilter) compressedSize = kBufferSize; // CBenchmarkOutStream *outStreamSpec = this->outStreamSpec; UInt64 prev = 0; const UInt32 mask = (CheckCrc_Enc ? 0 : 0xFFFF); const bool useCrc = (mask < NumIterations); bool crcPrev_defined = false; UInt32 crcPrev = 0; bool useRealData_Enc = UseRealData_Enc; bool data_Was_Changed = false; if (useRealData_Enc) { /* we want memcpy() for each iteration including first iteration. So results will be equal for different number of iterations */ data_Was_Changed = true; } const UInt64 numIterations = NumIterations; UInt64 i = numIterations; // printCallback->NewLine(); while (i != 0) { i--; if (printCallback && bi.UnpackSize - prev >= (1 << 26)) { prev = bi.UnpackSize; RINOK(printCallback->CheckBreak()) } /* CBenchInfo info; progressInfoSpec[0]->SetStartTime(); */ bool calcCrc = false; if (useCrc) calcCrc = (((UInt32)i & mask) == 0); if (_encoderFilter) { Byte *filterData = rgCopy; if (i == numIterations - 1 || calcCrc || useRealData_Enc) { // printf("\nfilterData = (Byte *)*outStreamSpec;\n"); filterData = (Byte *)*outStreamSpec; if (data_Was_Changed) { // printf("\nmemcpy(filterData, uncompressedDataPtr\n"); memcpy(filterData, uncompressedDataPtr, kBufferSize); } data_Was_Changed = true; } _encoderFilter->Init(); if (calcCrc) { // printf("\nInitCrc\n"); outStreamSpec->InitCrc(); } // printf("\nMy_FilterBench\n"); My_FilterBench(_encoderFilter, filterData, kBufferSize, calcCrc ? &outStreamSpec->Crc : NULL); } else { outStreamSpec->Init(true, calcCrc); // write real data for speed consistency at any number of iterations inStreamSpec->Init(uncompressedDataPtr, kBufferSize); RINOK(_encoder->Code(inStream, outStream, NULL, NULL, progressInfo[0])) if (!inStreamSpec->WasFinished()) return E_FAIL; if (compressedSize != outStreamSpec->Pos) { if (compressedSize != 0) return E_FAIL; compressedSize = outStreamSpec->Pos; } } // outStreamSpec->Print(); if (calcCrc) { const UInt32 crc2 = CRC_GET_DIGEST(outStreamSpec->Crc); if (crcPrev_defined && crcPrev != crc2) return E_FAIL; crcPrev = crc2; crcPrev_defined = true; } bi.UnpackSize += kBufferSize; bi.PackSize += compressedSize; /* { progressInfoSpec[0]->SetFinishTime(info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; info.UnpackSize = kBufferSize; info.PackSize = compressedSize; // printf("\n%7d\n", encoder.compressedSize); RINOK(callback->SetEncodeResult(info, true)) printCallback->NewLine(); } */ } _encoder.Release(); _encoderFilter.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; CMyComPtr &decoder = _decoders[decoderIndex]; CMyComPtr coder; if (_decoderFilter) { if (decoderIndex != 0) return E_FAIL; coder = _decoderFilter; } else coder = decoder; // printf("\ndecoderIndex = %d, stack = %p", decoderIndex, &coder); CMyComPtr setDecProps; coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); if (!setDecProps && propStreamSpec->GetPos() != 0) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; #ifndef Z7_ST { CMyComPtr setCoderMt; coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads)) } } #endif CMyComPtr scp; coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { const UInt64 reduceSize = _uncompressedDataSize; RINOK(_method.SetCoderProps(scp, &reduceSize)) } CMyComPtr cp; coder.QueryInterface(IID_ICryptoProperties, &cp); if (setDecProps) { RINOK(setDecProps->SetDecoderProperties2( /* (const Byte *)*propStreamSpec, */ propsData, (UInt32)propStreamSpec->GetPos())) } { CMyComPtr sp; coder.QueryInterface(IID_ICryptoSetPassword, &sp); if (sp) { RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))) } } UInt64 prev = 0; if (cp) { RINOK(Set_Key_and_IV(cp)) } CMyComPtr setFinishMode; if (_decoderFilter) { if (compressedSize > rgCopy.Size()) return E_FAIL; } else { decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); } const UInt64 numIterations = NumIterations; const E_CheckCrcMode checkCrcMode = CheckCrcMode_Dec; for (UInt64 i = 0; i < numIterations; i++) { if (printCallback && pi->BenchInfo.UnpackSize - prev >= (1 << 26)) { RINOK(printCallback->CheckBreak()) prev = pi->BenchInfo.UnpackSize; } const UInt64 outSize = kBufferSize; bool calcCrc = (checkCrcMode != k_CheckCrcMode_Never); crcOutStreamSpec->Init(); if (_decoderFilter) { Byte *filterData = (Byte *)*outStreamSpec; if (calcCrc) { calcCrc = (i == 0); if (checkCrcMode == k_CheckCrcMode_Always) { calcCrc = true; memcpy((Byte *)rgCopy, (const Byte *)*outStreamSpec, compressedSize); filterData = rgCopy; } } _decoderFilter->Init(); My_FilterBench(_decoderFilter, filterData, compressedSize, calcCrc ? &crcOutStreamSpec->Crc : NULL); } else { crcOutStreamSpec->CalcCrc = calcCrc; inStreamSpec->Init((const Byte *)*outStreamSpec, compressedSize); if (setFinishMode) { RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))) } RINOK(decoder->Code(inStream, crcOutStream, NULL, &outSize, progressInfo[decoderIndex])) if (setFinishMode) { if (!inStreamSpec->WasFinished()) return S_FALSE; CMyComPtr getInStreamProcessedSize; decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); if (getInStreamProcessedSize) { UInt64 processed; RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)) if (processed != compressedSize) return S_FALSE; } } if (crcOutStreamSpec->Pos != outSize) return S_FALSE; } if (calcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); _decoderFilter.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 12); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(NULL) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands) { if (numCommands < (1 << 4)) numCommands = (1 << 4); UInt64 res = complexInCommands / numCommands; return (res == 0 ? 1 : res); } #ifndef Z7_ST // ---------- CBenchThreadsFlusher ---------- struct CBenchThreadsFlusher { CBenchEncoders *EncodersSpec; CBenchSyncCommon Common; unsigned NumThreads; bool NeedClose; CBenchThreadsFlusher(): NumThreads(0), NeedClose(false) {} ~CBenchThreadsFlusher() { StartAndWait(true); } WRes StartAndWait(bool exitMode = false); }; WRes CBenchThreadsFlusher::StartAndWait(bool exitMode) { if (!NeedClose) return 0; Common.ExitMode = exitMode; WRes res = Common.StartEvent.Set(); for (unsigned i = 0; i < NumThreads; i++) { NWindows::CThread &t = EncodersSpec->encoders[i].thread[0]; if (t.IsCreated()) { WRes res2 = t.Wait_Close(); if (res == 0) res = res2; } } NeedClose = false; return res; } #endif // Z7_ST static void SetPseudoRand(Byte *data, size_t size, UInt32 startValue) { for (size_t i = 0; i < size; i++) { data[i] = (Byte)startValue; startValue++; } } static HRESULT MethodBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, #ifndef Z7_ST bool oldLzmaBenchMode, UInt32 numThreads, const CAffinityMode *affinityMode, #endif const COneMethodInfo &method2, size_t uncompressedDataSize, const Byte *fileData, unsigned generateDictBits, IBenchPrintCallback *printCallback, IBenchCallback *callback, CBenchProps *benchProps) { COneMethodInfo method = method2; UInt64 methodId; UInt32 numStreams; bool isFilter; const int codecIndex = FindMethod_Index( EXTERNAL_CODECS_LOC_VARS method.MethodName, true, methodId, numStreams, isFilter); if (codecIndex < 0) return E_NOTIMPL; if (numStreams != 1) return E_INVALIDARG; UInt32 numEncoderThreads = 1; UInt32 numSubDecoderThreads = 1; #ifndef Z7_ST numEncoderThreads = numThreads; if (oldLzmaBenchMode) if (methodId == k_LZMA) { if (numThreads == 1 && method.Get_NumThreads() < 0) method.AddProp_NumThreads(1); const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(); if (numThreads > 1 && numLzmaThreads > 1) { numEncoderThreads = (numThreads + 1) / 2; // 20.03 numSubDecoderThreads = 2; } } const bool mtEncMode = (numEncoderThreads > 1) || affinityMode->NeedAffinity(); #endif CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : NULL; encoder.printCallback = printCallback; #ifndef Z7_ST encoder.EncoderIndex = i; encoder.NumEncoderInternalThreads = numSubDecoderThreads; encoder.AffinityMode = *affinityMode; /* if (numSubDecoderThreads > 1) if (encoder.AffinityMode.NeedAffinity() && encoder.AffinityMode.NumBundleThreads == 1) { // if old LZMA benchmark uses two threads in coder, we increase (NumBundleThreads) for old LZMA benchmark uses two threads instead of one if (encoder.AffinityMode.NumBundleThreads * 2 <= encoder.AffinityMode.NumCores) encoder.AffinityMode.NumBundleThreads *= 2; } */ #endif { CCreatedCoder cod; RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)codecIndex, true, encoder._encoderFilter, cod)) encoder._encoder = cod.Coder; if (!encoder._encoder && !encoder._encoderFilter) return E_NOTIMPL; } SetPseudoRand(encoder._iv, sizeof(encoder._iv), 17); SetPseudoRand(encoder._key, sizeof(encoder._key), 51); SetPseudoRand(encoder._psw, sizeof(encoder._psw), 123); for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CCreatedCoder cod; CMyComPtr &decoder = encoder._decoders[j]; RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod)) decoder = cod.Coder; if (!encoder._decoderFilter && !decoder) return E_NOTIMPL; } encoder.UseRealData_Enc = encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30; encoder.CheckCrcMode_Dec = k_CheckCrcMode_Always; if (benchProps->DecComplexCompr + benchProps->DecComplexUnc <= 30) encoder.CheckCrcMode_Dec = k_CheckCrcMode_FirstPass; // for filters // k_CheckCrcMode_Never; // for debug // k_CheckCrcMode_Always; // for debug if (fileData) { encoder.UseRealData_Enc = true; encoder.CheckCrcMode_Dec = k_CheckCrcMode_Always; } } UInt32 crc = 0; if (fileData) crc = CrcCalc(fileData, uncompressedDataSize); for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder._method = method; encoder.generateDictBits = generateDictBits; encoder._uncompressedDataSize = uncompressedDataSize; encoder.kBufferSize = uncompressedDataSize; encoder.fileData = fileData; encoder.crc = crc; } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; #ifndef Z7_ST CBenchThreadsFlusher encoderFlusher; if (mtEncMode) { WRes wres = encoderFlusher.Common.StartEvent.Create(); if (wres != 0) return HRESULT_FROM_WIN32(wres); encoderFlusher.NumThreads = numEncoderThreads; encoderFlusher.EncodersSpec = &encodersSpec; encoderFlusher.NeedClose = true; } #endif for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = GetNumIterations(benchProps->GetNumCommands_Enc(uncompressedDataSize), complexInCommands); // encoder.NumIterations = 3; { #if 0 #define kCrcPoly 0xEDB88320 UInt32 r = i; unsigned num = numEncoderThreads < 256 ? 8 : 16; do r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); while (--num); encoder.Salt = r; #else UInt32 salt0 = g_CrcTable[(Byte)i]; UInt32 salt1 = g_CrcTable[(Byte)(i >> 8)]; encoder.Salt = salt0 ^ (salt1 << 3); #endif } // (g_CrcTable[0] == 0), and (encoder.Salt == 0) for first thread // printf("\n encoder index = %d, Salt = %8x\n", i, encoder.Salt); encoder.KeySize = benchProps->KeySize; for (int j = 0; j < 2; j++) { CBenchProgressInfo *spec = new CBenchProgressInfo; encoder.progressInfoSpec[j] = spec; encoder.progressInfo[j] = spec; spec->Status = &status; } if (i == 0) { CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; bpi->Callback = callback; bpi->BenchInfo.NumIterations = numEncoderThreads; } #ifndef Z7_ST if (mtEncMode) { #ifdef USE_ALLOCA encoder.AllocaSize = BENCH_ALLOCA_VALUE(i); #endif encoder.Common = &encoderFlusher.Common; encoder.IsGlobalMtMode = numEncoderThreads > 1; RINOK(encoder.CreateEncoderThread()) } #endif } if (printCallback) { RINOK(printCallback->CheckBreak()) } #ifndef Z7_ST if (mtEncMode) { for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; const WRes wres = encoder.ReadyEvent.Lock(); if (wres != 0) return HRESULT_FROM_WIN32(wres); RINOK(encoder.Results[0]) } CBenchProgressInfo *bpi = encoders[0].progressInfoSpec[0]; bpi->SetStartTime(); const WRes wres = encoderFlusher.StartAndWait(); if (status.Res == 0 && wres != 0) return HRESULT_FROM_WIN32(wres); } else #endif { RINOK(encoders[0].Encode()) } RINOK(status.Res) CBenchInfo info; encoders[0].progressInfoSpec[0]->SetFinishTime(info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { const CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; // printf("\n%7d\n", encoder.compressedSize); } RINOK(callback->SetEncodeResult(info, true)) // ---------- Decode ---------- status.Res = S_OK; status.EncodeMode = false; const UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; #ifndef Z7_ST const bool mtDecoderMode = (numDecoderThreads > 1) || affinityMode->NeedAffinity(); #endif for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; /* #ifndef Z7_ST // encoder.affinityMode = *affinityMode; if (encoder.NumEncoderInternalThreads != 1) encoder.AffinityMode.DivideNum = encoder.NumEncoderInternalThreads; #endif */ if (i == 0) { encoder.NumIterations = GetNumIterations( benchProps->GetNumCommands_Dec( encoder.compressedSize, encoder.kBufferSize), complexInCommands); CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; bpi->Callback = callback; bpi->BenchInfo.NumIterations = numDecoderThreads; bpi->SetStartTime(); } else encoder.NumIterations = encoders[0].NumIterations; #ifndef Z7_ST { const int numSubThreads = method.Get_NumThreads(); encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : (unsigned)numSubThreads; } if (mtDecoderMode) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { const HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , BENCH_ALLOCA_VALUE(i * numSubDecoderThreads + j) #endif ); RINOK(res) } } else #endif { RINOK(encoder.Decode(0)) } } #ifndef Z7_ST if (mtDecoderMode) { WRes wres = 0; HRESULT res = S_OK; for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; const WRes wres2 = encoder.thread[j]. // Wait(); // later we can get thread times from thread in UNDER_CE Wait_Close(); if (wres == 0 && wres2 != 0) wres = wres2; const HRESULT res2 = encoder.Results[j]; if (res == 0 && res2 != 0) res = res2; } if (wres != 0) return HRESULT_FROM_WIN32(wres); RINOK(res) } #endif // Z7_ST RINOK(status.Res) encoders[0].progressInfoSpec[0]->SetFinishTime(info); /* #ifndef Z7_ST #ifdef UNDER_CE if (mtDecoderMode) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0) info.UserTime += GetTime64(userTime) + GetTime64(kernelTime); } #endif #endif */ info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { const CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } // RINOK(callback->SetDecodeResult(info, false)) // why we called before 21.03 ?? RINOK(callback->SetDecodeResult(info, true)) return S_OK; } static inline UInt64 GetDictSizeFromLog(unsigned dictSizeLog) { /* if (dictSizeLog < 32) return (UInt32)1 << dictSizeLog; else return (UInt32)(Int32)-1; */ return (UInt64)1 << dictSizeLog; } // it's limit of current LZMA implementation that can be changed later #define kLzmaMaxDictSize ((UInt32)15 << 28) static inline UInt64 GetLZMAUsage(bool multiThread, int btMode, UInt64 dict) { if (dict == 0) dict = 1; if (dict > kLzmaMaxDictSize) dict = kLzmaMaxDictSize; UInt32 hs = (UInt32)dict - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; hs += (1 << 16); const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16); UInt64 blockSize = (UInt64)dict + (1 << 16) + (multiThread ? (1 << 20) : 0); blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)); if (blockSize >= kBlockSizeMax) blockSize = kBlockSizeMax; UInt64 son = (UInt64)dict; if (btMode) son *= 2; const UInt64 v = (hs + son) * 4 + blockSize + (1 << 20) + (multiThread ? (6 << 20) : 0); // printf("\nGetLZMAUsage = %d\n", (UInt32)(v >> 20)); // printf("\nblockSize = %d\n", (UInt32)(blockSize >> 20)); return v; } UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench) { const size_t kBufferSize = (size_t)dictionary + kAdditionalSize; const UInt64 kCompressedBufferSize = GetBenchCompressedSize(kBufferSize); // / 2; if (level < 0) level = 5; const int algo = (level < 5 ? 0 : 1); const int btMode = (algo == 0 ? 0 : 1); UInt32 numBigThreads = numThreads; const bool lzmaMt = (totalBench || (numThreads > 1 && btMode)); if (btMode) { if (!totalBench && lzmaMt) numBigThreads /= 2; } return ((UInt64)kBufferSize + kCompressedBufferSize + GetLZMAUsage(lzmaMt, btMode, dictionary) + (2 << 20)) * numBigThreads; } static UInt64 GetBenchMemoryUsage_Hash(UInt32 numThreads, UInt64 dictionary) { // dictionary += (dictionary >> 9); // for page tables (virtual memory) return (UInt64)(dictionary + (1 << 15)) * numThreads + (2 << 20); } // ---------- CRC and HASH ---------- struct CCrcInfo_Base { CMidAlignedBuffer Buffer; const Byte *Data; size_t Size; bool CreateLocalBuf; UInt32 CheckSum_Res; CCrcInfo_Base(): CreateLocalBuf(true), CheckSum_Res(0) {} HRESULT Generate(const Byte *data, size_t size); HRESULT CrcProcess(UInt64 numIterations, const UInt32 *checkSum, IHasher *hf, IBenchPrintCallback *callback); }; // for debug: define it to test hash calling with unaligned data // #define Z7_BENCH_HASH_ALIGN_BUF_OFFSET 3 HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) { Size = size; Data = data; if (!data || CreateLocalBuf) { Byte *buf; const size_t size2 = (size + k_RandBuf_AlignMask) & ~(size_t)k_RandBuf_AlignMask; if (size2 < size) return E_OUTOFMEMORY; #ifdef Z7_BENCH_HASH_ALIGN_BUF_OFFSET ALLOC_WITH_HRESULT(&Buffer, size2 + Z7_BENCH_HASH_ALIGN_BUF_OFFSET) buf = Buffer + Z7_BENCH_HASH_ALIGN_BUF_OFFSET; #else ALLOC_WITH_HRESULT(&Buffer, size2) buf = Buffer; #endif Data = buf; if (!data) RandGen_BufAfterPad(buf, size); else if (size != 0) // (CreateLocalBuf == true) memcpy(buf, data, size); } return S_OK; } HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, const UInt32 *checkSum, IHasher *hf, IBenchPrintCallback *callback) { MY_ALIGN(16) UInt32 hash32[64 / 4]; memset(hash32, 0, sizeof(hash32)); CheckSum_Res = 0; const UInt32 hashSize = hf->GetDigestSize(); if (hashSize > sizeof(hash32)) return S_FALSE; const Byte *buf = Data; const size_t size = Size; UInt32 checkSum_Prev = 0; UInt64 prev = 0; UInt64 cur = 0; do { hf->Init(); size_t pos = 0; do { const size_t rem = size - pos; const UInt32 kStep = ((UInt32)1 << 31); const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; hf->Update(buf + pos, curSize); pos += curSize; } while (pos != size); hf->Final((Byte *)(void *)hash32); UInt32 sum = 0; for (UInt32 j = 0; j < hashSize; j += 4) { sum = rotlFixed(sum, 11); sum += GetUi32((const Byte *)(const void *)hash32 + j); } if (checkSum) { if (sum != *checkSum) return S_FALSE; } else { checkSum_Prev = sum; checkSum = &checkSum_Prev; } if (callback) { cur += size; if (cur - prev >= ((UInt32)1 << 30)) { prev = cur; RINOK(callback->CheckBreak()) } } } while (--numIterations); CheckSum_Res = checkSum_Prev; return S_OK; } extern UInt32 g_BenchCpuFreqTemp; // we need non-static variavble to disable compiler optimization UInt32 g_BenchCpuFreqTemp = 1; #define YY1 sum += val; sum ^= val; #define YY3 YY1 YY1 YY1 YY1 #define YY5 YY3 YY3 YY3 YY3 #define YY7 YY5 YY5 YY5 YY5 static const UInt32 kNumFreqCommands = 128; EXTERN_C_BEGIN static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val) { for (UInt32 i = 0; i < num; i++) { YY7 } return sum; } EXTERN_C_END #ifndef Z7_ST struct CBaseThreadInfo { NWindows::CThread Thread; IBenchPrintCallback *Callback; HRESULT CallbackRes; WRes Wait_If_Created() { if (!Thread.IsCreated()) return 0; return Thread.Wait_Close(); } }; struct CFreqInfo: public CBaseThreadInfo { UInt32 ValRes; UInt32 Size; UInt64 NumIterations; }; static THREAD_FUNC_DECL FreqThreadFunction(void *param) { CFreqInfo *p = (CFreqInfo *)param; UInt32 sum = g_BenchCpuFreqTemp; for (UInt64 k = p->NumIterations; k > 0; k--) { if (p->Callback) { p->CallbackRes = p->Callback->CheckBreak(); if (p->CallbackRes != S_OK) break; } sum = CountCpuFreq(sum, p->Size, g_BenchCpuFreqTemp); } p->ValRes = sum; return THREAD_FUNC_RET_ZERO; } struct CFreqThreads { CFreqInfo *Items; UInt32 NumThreads; CFreqThreads(): Items(NULL), NumThreads(0) {} WRes WaitAll() { WRes wres = 0; for (UInt32 i = 0; i < NumThreads; i++) { WRes wres2 = Items[i].Wait_If_Created(); if (wres == 0 && wres2 != 0) wres = wres2; } NumThreads = 0; return wres; } ~CFreqThreads() { WaitAll(); delete []Items; } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param); struct CCrcInfo: public CBaseThreadInfo { const Byte *Data; size_t Size; UInt64 NumIterations; bool CheckSumDefined; UInt32 CheckSum; CMyComPtr Hasher; HRESULT Res; UInt32 CheckSum_Res; #ifndef Z7_ST NSynchronization::CManualResetEvent ReadyEvent; UInt32 ThreadIndex; CBenchSyncCommon *Common; CAffinityMode AffinityMode; #endif // we want to call CCrcInfo_Base::Buffer.Free() in main thread. // so we uses non-local CCrcInfo_Base. CCrcInfo_Base crcib; HRESULT CreateThread() { WRes res = 0; if (!ReadyEvent.IsCreated()) res = ReadyEvent.Create(); if (res == 0) res = AffinityMode.CreateThread_WithAffinity(Thread, CrcThreadFunction, this, ThreadIndex); return HRESULT_FROM_WIN32(res); } #ifdef USE_ALLOCA size_t AllocaSize; #endif void Process(); CCrcInfo(): Res(E_FAIL) {} }; static const bool k_Crc_CreateLocalBuf_For_File = true; // for total BW test // static const bool k_Crc_CreateLocalBuf_For_File = false; // for shared memory read test void CCrcInfo::Process() { crcib.CreateLocalBuf = k_Crc_CreateLocalBuf_For_File; // we can use additional Generate() passes to reduce some time effects for new page allocation // for (unsigned y = 0; y < 10; y++) Res = crcib.Generate(Data, Size); // if (Common) { WRes wres = ReadyEvent.Set(); if (wres != 0) { if (Res == 0) Res = HRESULT_FROM_WIN32(wres); return; } if (Res != 0) return; wres = Common->StartEvent.Lock(); if (wres != 0) { Res = HRESULT_FROM_WIN32(wres); return; } if (Common->ExitMode) return; } Res = crcib.CrcProcess(NumIterations, CheckSumDefined ? &CheckSum : NULL, Hasher, Callback); CheckSum_Res = crcib.CheckSum_Res; /* We don't want to include the time of slow CCrcInfo_Base::Buffer.Free() to time of benchmark. So we don't free Buffer here */ // crcib.Buffer.Free(); } static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; #ifdef USE_ALLOCA alloca(p->AllocaSize); #endif p->Process(); return THREAD_FUNC_RET_ZERO; } struct CCrcThreads { CCrcInfo *Items; unsigned NumThreads; CBenchSyncCommon Common; bool NeedClose; CCrcThreads(): Items(NULL), NumThreads(0), NeedClose(false) {} WRes StartAndWait(bool exitMode = false); ~CCrcThreads() { StartAndWait(true); delete []Items; } }; WRes CCrcThreads::StartAndWait(bool exitMode) { if (!NeedClose) return 0; Common.ExitMode = exitMode; WRes wres = Common.StartEvent.Set(); for (unsigned i = 0; i < NumThreads; i++) { WRes wres2 = Items[i].Wait_If_Created(); if (wres == 0 && wres2 != 0) wres = wres2; } NumThreads = 0; NeedClose = false; return wres; } #endif /* static UInt32 CrcCalc1(const Byte *buf, size_t size) { UInt32 crc = CRC_INIT_VAL; for (size_t i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } */ /* static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } */ static bool CrcInternalTest() { CAlignedBuffer buffer; const size_t kBufSize = 1 << 11; const size_t kCheckSize = 1 << 6; buffer.Alloc(kBufSize); if (!buffer.IsAllocated()) return false; Byte *buf = (Byte *)buffer; RandGen_BufAfterPad(buf, kBufSize); UInt32 sum = 0; for (size_t i = 0; i < kBufSize - kCheckSize * 2; i += kCheckSize - 1) for (size_t j = 0; j < kCheckSize; j++) { sum = rotlFixed(sum, 11); sum += CrcCalc(buf + i + j, j); } return sum == 0x28462c7c; } struct CBenchMethod { unsigned Weight; unsigned DictBits; Int32 EncComplex; Int32 DecComplexCompr; Int32 DecComplexUnc; const char *Name; // unsigned KeySize; }; // #define USE_SW_CMPLX #ifdef USE_SW_CMPLX #define CMPLX(x) ((x) * 1000) #else #define CMPLX(x) (x) #endif static const CBenchMethod g_Bench[] = { // { 40, 17, 357, 145, 20, "LZMA:x1" }, // { 20, 18, 360, 145, 20, "LZMA2:x1:mt2" }, { 20, 18, 360, 145, 20, "LZMA:x1" }, { 20, 22, 600, 145, 20, "LZMA:x3" }, { 80, 24, 1220, 145, 20, "LZMA:x5:mt1" }, { 80, 24, 1220, 145, 20, "LZMA:x5:mt2" }, { 10, 16, 124, 40, 14, "Deflate:x1" }, { 20, 16, 376, 40, 14, "Deflate:x5" }, { 10, 16, 1082, 40, 14, "Deflate:x7" }, { 10, 17, 422, 40, 14, "Deflate64:x5" }, { 10, 15, 590, 69, 69, "BZip2:x1" }, { 20, 19, 815, 122, 122, "BZip2:x5" }, { 10, 19, 815, 122, 122, "BZip2:x5:mt2" }, { 10, 19, 2530, 122, 122, "BZip2:x7" }, // { 10, 18, 1010, 0, 1150, "PPMDZip:x1" }, { 10, 18, 1010, 0, 1150, "PPMD:x1" }, // { 10, 22, 1655, 0, 1830, "PPMDZip:x5" }, { 10, 22, 1655, 0, 1830, "PPMD:x5" }, // { 2, 0, -16, 0, -16, "Swap2" }, { 2, 0, -16, 0, -16, "Swap4" }, // { 2, 0, 3, 0, 4, "Delta:1" }, // { 2, 0, 3, 0, 4, "Delta:2" }, // { 2, 0, 3, 0, 4, "Delta:3" }, { 2, 0, 3, 0, 4, "Delta:4" }, // { 2, 0, 3, 0, 4, "Delta:8" }, // { 2, 0, 3, 0, 4, "Delta:32" }, { 2, 0, 2, 0, 2, "BCJ" }, { 2, 0, 1, 0, 1, "ARM64" }, { 2, 0, 1, 0, 1, "RISCV" }, // { 10, 0, 18, 0, 18, "AES128CBC:1" }, // { 10, 0, 21, 0, 21, "AES192CBC:1" }, { 10, 0, 24, 0, 24, "AES256CBC:1" }, // { 10, 0, 18, 0, 18, "AES128CTR:1" }, // { 10, 0, 21, 0, 21, "AES192CTR:1" }, // { 10, 0, 24, 0, 24, "AES256CTR:1" }, // { 2, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:2" }, // { 2, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:2" }, { 2, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:2" }, // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:2" }, // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:2" }, // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:2" }, // { 1, 0, CMPLX(6), 0, -2, "AES128CBC:3" }, // { 1, 0, CMPLX(7), 0, -2, "AES192CBC:3" }, { 1, 0, CMPLX(8), 0, -2, "AES256CBC:3" } // { 1, 0, CMPLX(1), 0, -2, "AES128CTR:3" }, // { 1, 0, CMPLX(1), 0, -2, "AES192CTR:3" }, // { 1, 0, CMPLX(1), 0, -2, "AES256CTR:3" }, }; struct CBenchHash { unsigned Weight; UInt32 Complex; UInt32 CheckSum; const char *Name; }; // #define ARM_CRC_MUL 100 #define ARM_CRC_MUL 1 #define k_Hash_Complex_Mult 256 static const CBenchHash g_Hash[] = { { 20, 256, 0x21e207bb, "CRC32:12" } , { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, { 10, 256, 0x41b901d1, "CRC64" }, { 10, 64, 0x43eac94f, "XXH64" }, { 10, 5100, 0x7913ba03, "SHA256:1" }, { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, { 10, 2340, 0xff769021, "SHA1:1" }, { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, { 2, 4096, 0x85189d02, "BLAKE2sp:1" }, { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast #if 0 , { 2, 2048, 0x85189d02, "BLAKE2sp:4" } // sse2-way1 , { 2, 1024, 0x85189d02, "BLAKE2sp:5" } // sse2-way2 , { 2, 1024, 0x85189d02, "BLAKE2sp:6" } // avx2-way2 , { 2, 1024, 0x85189d02, "BLAKE2sp:7" } // avx2-way4 #endif }; static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size) { char s[128]; unsigned startPos = (unsigned)sizeof(s) - 32; memset(s, ' ', startPos); ConvertUInt64ToString(value, s + startPos); // if (withSpace) { startPos--; size++; } unsigned len = (unsigned)strlen(s + startPos); if (size > len) { size -= len; if (startPos < size) startPos = 0; else startPos -= size; } f.Print(s + startPos); } static const unsigned kFieldSize_Name = 12; static const unsigned kFieldSize_SmallName = 4; static const unsigned kFieldSize_Speed = 9; static const unsigned kFieldSize_Usage = 5; static const unsigned kFieldSize_RU = 6; static const unsigned kFieldSize_Rating = 6; static const unsigned kFieldSize_EU = 5; static const unsigned kFieldSize_Effec = 5; static const unsigned kFieldSize_CrcSpeed = 8; static const unsigned kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating; static const unsigned kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec; static void PrintRating(IBenchPrintCallback &f, UInt64 rating, unsigned size) { PrintNumber(f, (rating + 500000) / 1000000, size); } static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, unsigned size) { UInt64 v = 0; if (divider != 0) v = (val * 100 + divider / 2) / divider; PrintNumber(f, v, size); } static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) { char s[256]; memset(s, (Byte)c, size); s[size] = 0; f.Print(s); } static void PrintSpaces(IBenchPrintCallback &f, unsigned size) { PrintChars(f, ' ', size); } static void PrintUsage(IBenchPrintCallback &f, UInt64 usage, unsigned size) { PrintNumber(f, Benchmark_GetUsage_Percents(usage), size); } static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq) { PrintUsage(f, usage, kFieldSize_Usage); PrintRating(f, rpu, kFieldSize_RU); PrintRating(f, rating, kFieldSize_Rating); if (showFreq) { if (cpuFreq == 0) PrintSpaces(f, kFieldSize_EUAndEffec); else { PrintPercents(f, rating, cpuFreq * usage / kBenchmarkUsageMult, kFieldSize_EU); PrintPercents(f, rating, cpuFreq, kFieldSize_Effec); } } } void CTotalBenchRes::Generate_From_BenchInfo(const CBenchInfo &info) { Speed = info.GetUnpackSizeSpeed(); Usage = info.GetUsage(); RPU = info.GetRatingPerUsage(Rating); } void CTotalBenchRes::Mult_For_Weight(unsigned weight) { NumIterations2 *= weight; RPU *= weight; Rating *= weight; Usage *= weight; Speed *= weight; } void CTotalBenchRes::Update_With_Res(const CTotalBenchRes &r) { Rating += r.Rating; Usage += r.Usage; RPU += r.RPU; Speed += r.Speed; // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1); NumIterations2 += r.NumIterations2; } static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, unsigned weight, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res) { CTotalBenchRes t; t.Rating = rating; t.NumIterations2 = 1; t.Generate_From_BenchInfo(info); if (f) { if (t.Speed != 0) PrintNumber(*f, t.Speed / 1024, kFieldSize_Speed); else PrintSpaces(*f, 1 + kFieldSize_Speed); } if (f) { PrintResults(*f, t.Usage, t.RPU, rating, showFreq, cpuFreq); } if (res) { // res->NumIterations1++; t.Mult_For_Weight(weight); res->Update_With_Res(t); } } static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, bool showSpeed, const CTotalBenchRes &res) { const UInt64 numIterations2 = res.NumIterations2 ? res.NumIterations2 : 1; const UInt64 speed = res.Speed / numIterations2; if (showSpeed && speed != 0) PrintNumber(f, speed / 1024, kFieldSize_Speed); else PrintSpaces(f, 1 + kFieldSize_Speed); // PrintSpaces(f, 1 + kFieldSize_Speed); // UInt64 numIterations1 = res.NumIterations1; if (numIterations1 == 0) numIterations1 = 1; PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq); } static void PrintHex(AString &s, UInt64 v) { char temp[32]; ConvertUInt64ToHex(v, temp); s += temp; } AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) { AString s; // s.Add_UInt32(ti.numProcessThreads); unsigned numSysThreads = ti.GetNumSystemThreads(); if (ti.GetNumProcessThreads() != numSysThreads) { // if (ti.numProcessThreads != ti.numSysThreads) { s += " / "; s.Add_UInt32(numSysThreads); } s += " : "; #ifdef _WIN32 PrintHex(s, ti.processAffinityMask); s += " / "; PrintHex(s, ti.systemAffinityMask); #else unsigned i = (numSysThreads + 3) & ~(unsigned)3; if (i == 0) i = 4; for (; i >= 4; ) { i -= 4; unsigned val = 0; for (unsigned k = 0; k < 4; k++) { const unsigned bit = (ti.IsCpuSet(i + k) ? 1 : 0); val += (bit << k); } PrintHex(s, val); } #endif } return s; } #ifdef Z7_LARGE_PAGES #ifdef _WIN32 extern bool g_LargePagesMode; extern "C" { extern SIZE_T g_LargePageSize; } #endif void Add_LargePages_String(AString &s) { #ifdef _WIN32 if (g_LargePagesMode || g_LargePageSize != 0) { s.Add_OptSpaced("(LP-"); PrintSize_KMGT_Or_Hex(s, g_LargePageSize); #ifdef MY_CPU_X86_OR_AMD64 if (CPU_IsSupported_PageGB()) s += "-1G"; #endif if (!g_LargePagesMode) s += "-NA"; s += ")"; } #else s += ""; #endif } #endif static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads) { f.Print("RAM "); f.Print(sizeString); if (size_Defined) PrintNumber(f, (size >> 20), 6); else f.Print(" ?"); f.Print(" MB"); #ifdef Z7_LARGE_PAGES { AString s; Add_LargePages_String(s); f.Print(s); } #endif f.Print(", # "); f.Print(threadsString); PrintNumber(f, numThreads, 3); } struct CBenchCallbackToPrint Z7_final: public IBenchCallback { bool NeedPrint; bool Use2Columns; bool ShowFreq; unsigned NameFieldSize; unsigned EncodeWeight; unsigned DecodeWeight; UInt64 CpuFreq; UInt64 DictSize; IBenchPrintCallback *_file; CBenchProps BenchProps; CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; CBenchInfo BenchInfo_Results[2]; CBenchCallbackToPrint(): NeedPrint(true), Use2Columns(false), ShowFreq(false), NameFieldSize(0), EncodeWeight(1), DecodeWeight(1), CpuFreq(0) {} void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Print(const char *s); void NewLine(); HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); HRESULT SetEncodeResult(const CBenchInfo &info, bool final) Z7_override; HRESULT SetDecodeResult(const CBenchInfo &info, bool final) Z7_override; }; HRESULT CBenchCallbackToPrint::SetFreq(bool showFreq, UInt64 cpuFreq) { ShowFreq = showFreq; CpuFreq = cpuFreq; return S_OK; } HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final) { RINOK(_file->CheckBreak()) if (final) BenchInfo_Results[0] = info; if (final) if (NeedPrint) { const UInt64 rating = BenchProps.GetRating_Enc(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations); PrintResults(_file, info, EncodeWeight, rating, ShowFreq, CpuFreq, &EncodeRes); if (!Use2Columns) _file->NewLine(); } return S_OK; } static const char * const kSep = " | "; HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final) { RINOK(_file->CheckBreak()) if (final) BenchInfo_Results[1] = info; if (final) if (NeedPrint) { const UInt64 rating = BenchProps.GetRating_Dec(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); if (Use2Columns) _file->Print(kSep); else PrintSpaces(*_file, NameFieldSize); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(_file, info2, DecodeWeight, rating, ShowFreq, CpuFreq, &DecodeRes); } return S_OK; } void CBenchCallbackToPrint::Print(const char *s) { _file->Print(s); } void CBenchCallbackToPrint::NewLine() { _file->NewLine(); } static void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size) { f.Print(s); int numSpaces = (int)size - (int)MyStringLen(s); if (numSpaces > 0) PrintSpaces(f, (unsigned)numSpaces); } static void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size) { int numSpaces = (int)size - (int)MyStringLen(s); if (numSpaces > 0) PrintSpaces(f, (unsigned)numSpaces); f.Print(s); } static bool DoesWildcardMatchName_NoCase(const AString &mask, const char *name) { UString wildc = GetUnicodeString(mask); UString bname = GetUnicodeString(name); wildc.MakeLower_Ascii(); bname.MakeLower_Ascii(); return DoesWildcardMatchName(wildc, bname); } static HRESULT TotalBench( DECL_EXTERNAL_CODECS_LOC_VARS const COneMethodInfo &methodMask, UInt64 complexInCommands, #ifndef Z7_ST UInt32 numThreads, const CAffinityMode *affinityMode, #endif bool forceUnpackSize, size_t unpackSize, const Byte *fileData, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Bench); i++) { const CBenchMethod &bench = g_Bench[i]; if (!DoesWildcardMatchName_NoCase(methodMask.MethodName, bench.Name)) continue; PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); { unsigned keySize = 32; if (IsString1PrefixedByString2(bench.Name, "AES128")) keySize = 16; else if (IsString1PrefixedByString2(bench.Name, "AES192")) keySize = 24; callback->BenchProps.KeySize = keySize; } callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; callback->BenchProps.EncComplex = bench.EncComplex; COneMethodInfo method; NCOM::CPropVariant propVariant; propVariant = bench.Name; RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)) size_t unpackSize2 = unpackSize; if (!forceUnpackSize && bench.DictBits == 0) unpackSize2 = kFilterUnpackSize; callback->EncodeWeight = bench.Weight; callback->DecodeWeight = bench.Weight; const HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, #ifndef Z7_ST false, numThreads, affinityMode, #endif method, unpackSize2, fileData, bench.DictBits, printCallback, callback, &callback->BenchProps); if (res == E_NOTIMPL) { // callback->Print(" ---"); // we need additional empty line as line for decompression results if (!callback->Use2Columns) callback->NewLine(); } else { RINOK(res) } callback->NewLine(); } return S_OK; } struct CFreqBench { // in: UInt64 complexInCommands; UInt32 numThreads; bool showFreq; UInt64 specifiedFreq; // out: UInt64 CpuFreqRes; UInt64 UsageRes; UInt32 res; CFreqBench() {} HRESULT FreqBench(IBenchPrintCallback *_file #ifndef Z7_ST , const CAffinityMode *affinityMode #endif ); }; HRESULT CFreqBench::FreqBench(IBenchPrintCallback *_file #ifndef Z7_ST , const CAffinityMode *affinityMode #endif ) { res = 0; CpuFreqRes = 0; UsageRes = 0; if (numThreads == 0) numThreads = 1; #ifdef Z7_ST numThreads = 1; #endif const UInt32 complexity = kNumFreqCommands; UInt64 numIterations = complexInCommands / complexity; UInt32 numIterations2 = 1 << 30; if (numIterations > numIterations2) numIterations /= numIterations2; else { numIterations2 = (UInt32)numIterations; numIterations = 1; } CBenchInfoCalc progressInfoSpec; #ifndef Z7_ST bool mtMode = (numThreads > 1) || affinityMode->NeedAffinity(); if (mtMode) { CFreqThreads threads; threads.Items = new CFreqInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CFreqInfo &info = threads.Items[i]; info.Callback = _file; info.CallbackRes = S_OK; info.NumIterations = numIterations; info.Size = numIterations2; } progressInfoSpec.SetStartTime(); for (i = 0; i < numThreads; i++) { // Sleep(10); CFreqInfo &info = threads.Items[i]; WRes wres = affinityMode->CreateThread_WithAffinity(info.Thread, FreqThreadFunction, &info, i); if (info.Thread.IsCreated()) threads.NumThreads++; if (wres != 0) return HRESULT_FROM_WIN32(wres); } WRes wres = threads.WaitAll(); if (wres != 0) return HRESULT_FROM_WIN32(wres); for (i = 0; i < numThreads; i++) { RINOK(threads.Items[i].CallbackRes) } } else #endif { progressInfoSpec.SetStartTime(); UInt32 sum = g_BenchCpuFreqTemp; UInt64 k = numIterations; do { sum = CountCpuFreq(sum, numIterations2, g_BenchCpuFreqTemp); if (_file) { RINOK(_file->CheckBreak()) } } while (--k); res += sum; } if (res == 0x12345678) if (_file) { RINOK(_file->CheckBreak()) } CBenchInfo info; progressInfoSpec.SetFinishTime(info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; const UInt64 numCommands = (UInt64)numIterations * numIterations2 * numThreads * complexity; const UInt64 rating = info.GetSpeed(numCommands); CpuFreqRes = rating / numThreads; UsageRes = info.GetUsage(); if (_file) { PrintResults(_file, info, 0, // weight rating, showFreq, showFreq ? (specifiedFreq != 0 ? specifiedFreq : CpuFreqRes) : 0, NULL); RINOK(_file->CheckBreak()) } return S_OK; } static HRESULT CrcBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, UInt32 numThreads, const size_t bufferSize, const Byte *fileData, UInt64 &speed, UInt64 &usage, UInt32 complexity, unsigned benchWeight, const UInt32 *checkSum, const COneMethodInfo &method, IBenchPrintCallback *_file, #ifndef Z7_ST const CAffinityMode *affinityMode, #endif bool showRating, CTotalBenchRes *encodeRes, bool showFreq, UInt64 cpuFreq) { if (numThreads == 0) numThreads = 1; #ifdef Z7_ST numThreads = 1; #endif const AString &methodName = method.MethodName; // methodName.RemoveChar(L'-'); CMethodId hashID; if (!FindHashMethod( EXTERNAL_CODECS_LOC_VARS methodName, hashID)) return E_NOTIMPL; /* // if will generate random data in each thread, instead of global data CMidAlignedBuffer buffer; if (!fileData) { ALLOC_WITH_HRESULT(&buffer, bufferSize) RandGen(buffer, bufferSize); fileData = buffer; } */ const size_t bsize = (bufferSize == 0 ? 1 : bufferSize); UInt64 numIterations = complexInCommands * k_Hash_Complex_Mult / complexity / bsize; if (numIterations == 0) numIterations = 1; CBenchInfoCalc progressInfoSpec; CBenchInfo info; #ifndef Z7_ST bool mtEncMode = (numThreads > 1) || affinityMode->NeedAffinity(); if (mtEncMode) { CCrcThreads threads; threads.Items = new CCrcInfo[numThreads]; { WRes wres = threads.Common.StartEvent.Create(); if (wres != 0) return HRESULT_FROM_WIN32(wres); threads.NeedClose = true; } UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &ci = threads.Items[i]; AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, ci.Hasher)) if (!ci.Hasher) return E_NOTIMPL; CMyComPtr scp; ci.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { RINOK(method.SetCoderProps(scp)) } ci.Callback = _file; ci.Data = fileData; ci.NumIterations = numIterations; ci.Size = bufferSize; ci.CheckSumDefined = false; if (checkSum) { ci.CheckSum = *checkSum; ci.CheckSumDefined = true; } #ifdef USE_ALLOCA ci.AllocaSize = BENCH_ALLOCA_VALUE(i); #endif } for (i = 0; i < numThreads; i++) { CCrcInfo &ci = threads.Items[i]; ci.ThreadIndex = i; ci.Common = &threads.Common; ci.AffinityMode = *affinityMode; HRESULT hres = ci.CreateThread(); if (ci.Thread.IsCreated()) threads.NumThreads++; if (hres != 0) return hres; } for (i = 0; i < numThreads; i++) { CCrcInfo &ci = threads.Items[i]; WRes wres = ci.ReadyEvent.Lock(); if (wres != 0) return HRESULT_FROM_WIN32(wres); RINOK(ci.Res) } progressInfoSpec.SetStartTime(); WRes wres = threads.StartAndWait(); if (wres != 0) return HRESULT_FROM_WIN32(wres); progressInfoSpec.SetFinishTime(info); for (i = 0; i < numThreads; i++) { RINOK(threads.Items[i].Res) if (i != 0) if (threads.Items[i].CheckSum_Res != threads.Items[i - 1].CheckSum_Res) return S_FALSE; } } else #endif { CMyComPtr hasher; AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)) if (!hasher) return E_NOTIMPL; CMyComPtr scp; hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) { RINOK(method.SetCoderProps(scp)) } CCrcInfo_Base crcib; crcib.CreateLocalBuf = false; RINOK(crcib.Generate(fileData, bufferSize)) progressInfoSpec.SetStartTime(); RINOK(crcib.CrcProcess(numIterations, checkSum, hasher, _file)) progressInfoSpec.SetFinishTime(info); } UInt64 unpSize = numIterations * bufferSize; UInt64 unpSizeThreads = unpSize * numThreads; info.UnpackSize = unpSizeThreads; info.PackSize = unpSizeThreads; info.NumIterations = 1; if (_file) { if (showRating) { UInt64 unpSizeThreads2 = unpSizeThreads; if (unpSizeThreads2 == 0) unpSizeThreads2 = numIterations * 1 * numThreads; const UInt64 numCommands = unpSizeThreads2 * complexity / 256; const UInt64 rating = info.GetSpeed(numCommands); PrintResults(_file, info, benchWeight, rating, showFreq, cpuFreq, encodeRes); } RINOK(_file->CheckBreak()) } speed = info.GetSpeed(unpSizeThreads); usage = info.GetUsage(); return S_OK; } static HRESULT TotalBench_Hash( DECL_EXTERNAL_CODECS_LOC_VARS const COneMethodInfo &methodMask, UInt64 complexInCommands, UInt32 numThreads, size_t bufSize, const Byte *fileData, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback, #ifndef Z7_ST const CAffinityMode *affinityMode, #endif CTotalBenchRes *encodeRes, bool showFreq, UInt64 cpuFreq) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Hash); i++) { const CBenchHash &bench = g_Hash[i]; if (!DoesWildcardMatchName_NoCase(methodMask.MethodName, bench.Name)) continue; PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); // callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; // callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; // callback->BenchProps.EncComplex = bench.EncComplex; COneMethodInfo method; NCOM::CPropVariant propVariant; propVariant = bench.Name; RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)) UInt64 speed, usage; const HRESULT res = CrcBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, bufSize, fileData, speed, usage, bench.Complex, bench.Weight, (!fileData && bufSize == (1 << kNumHashDictBits)) ? &bench.CheckSum : NULL, method, printCallback, #ifndef Z7_ST affinityMode, #endif true, // showRating encodeRes, showFreq, cpuFreq); if (res == E_NOTIMPL) { // callback->Print(" ---"); } else { RINOK(res) } callback->NewLine(); } return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(): Values(NULL) {} void Alloc(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *end; UInt64 result = ConvertStringToUInt64(s, &end); if (*end != 0 || s.IsEmpty()) prop = s; else if (result <= (UInt32)0xFFFFFFFF) prop = (UInt32)result; else prop = result; } static bool AreSameMethodNames(const char *fullName, const char *shortName) { return StringsAreEqualNoCase_Ascii(fullName, shortName); } static void Print_Usage_and_Threads(IBenchPrintCallback &f, UInt64 usage, UInt32 threads) { PrintRequirements(f, "usage:", true, usage, "Benchmark threads: ", threads); } static void Print_Delimiter(IBenchPrintCallback &f) { f.Print(" |"); } static void Print_Pow(IBenchPrintCallback &f, unsigned pow) { char s[16]; ConvertUInt32ToString(pow, s); unsigned pos = MyStringLen(s); s[pos++] = ':'; s[pos] = 0; PrintLeft(f, s, kFieldSize_SmallName); // 4 } static void Bench_BW_Print_Usage_Speed(IBenchPrintCallback &f, UInt64 usage, UInt64 speed) { PrintUsage(f, usage, kFieldSize_Usage); PrintNumber(f, speed / 1000000, kFieldSize_CrcSpeed); } HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, const CObjectVector &props, UInt32 numIterations, bool multiDict, IBenchFreqCallback *freqCallback) { // for (int y = 0; y < 10000; y++) if (!CrcInternalTest()) return E_FAIL; UInt32 numCPUs = 1; UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; NSystem::CProcessAffinity threadsInfo; threadsInfo.InitST(); #ifndef Z7_ST if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0) numCPUs = threadsInfo.GetNumProcessThreads(); else numCPUs = NSystem::GetNumberOfProcessors(); #endif // numCPUs = 24; /* { DWORD_PTR mask = (1 << 0); DWORD_PTR old = SetThreadAffinityMask(GetCurrentThread(), mask); old = old; DWORD_PTR old2 = SetThreadAffinityMask(GetCurrentThread(), mask); old2 = old2; return 0; } */ const bool ramSize_Defined = NSystem::GetRamSize(ramSize); UInt32 numThreadsSpecified = numCPUs; bool needSetComplexity = false; UInt32 testTimeMs = kComplexInMs; UInt32 startDicLog = 22; bool startDicLog_Defined = false; UInt64 specifiedFreq = 0; bool multiThreadTests = false; UInt64 complexInCommands = kComplexInCommands; UInt32 numThreads_Start = 1; #ifndef Z7_ST CAffinityMode affinityMode; #endif COneMethodInfo method; CMidAlignedBuffer fileDataBuffer; bool use_fileData = false; bool isFixedDict = false; { unsigned i; if (printCallback) { for (i = 0; i < props.Size(); i++) { const CProperty &property = props[i]; printCallback->Print(" "); printCallback->Print(GetAnsiString(property.Name)); if (!property.Value.IsEmpty()) { printCallback->Print("="); printCallback->Print(GetAnsiString(property.Value)); } } if (!props.IsEmpty()) printCallback->NewLine(); } for (i = 0; i < props.Size(); i++) { const CProperty &property = props[i]; UString name (property.Name); name.MakeLower_Ascii(); if (name.IsEqualTo("file")) { if (property.Value.IsEmpty()) return E_INVALIDARG; NFile::NIO::CInFile file; if (!file.Open(us2fs(property.Value))) return GetLastError_noZero_HRESULT(); size_t len; { UInt64 len64; if (!file.GetLength(len64)) return GetLastError_noZero_HRESULT(); if (printCallback) { printCallback->Print("file size ="); PrintNumber(*printCallback, len64, 0); printCallback->NewLine(); } len = (size_t)len64; if (len != len64) return E_INVALIDARG; } // (len == 0) is allowed. Also it's allowed if Alloc(0) returns NULL here ALLOC_WITH_HRESULT(&fileDataBuffer, len) use_fileData = true; { size_t processed; if (!file.ReadFull((Byte *)fileDataBuffer, len, processed)) return GetLastError_noZero_HRESULT(); if (processed != len) return E_FAIL; } continue; } NCOM::CPropVariant propVariant; if (!property.Value.IsEmpty()) ParseNumberString(property.Value, propVariant); if (name.IsEqualTo("time")) { RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)) needSetComplexity = true; testTimeMs *= 1000; continue; } if (name.IsEqualTo("timems")) { RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)) needSetComplexity = true; continue; } if (name.IsEqualTo("tic")) { UInt32 v; RINOK(ParsePropToUInt32(UString(), propVariant, v)) if (v >= 64) return E_INVALIDARG; complexInCommands = (UInt64)1 << v; continue; } const bool isCurrent_fixedDict = name.IsEqualTo("df"); if (isCurrent_fixedDict) isFixedDict = true; if (isCurrent_fixedDict || name.IsEqualTo("ds")) { RINOK(ParsePropToUInt32(UString(), propVariant, startDicLog)) if (startDicLog > 32) return E_INVALIDARG; startDicLog_Defined = true; continue; } if (name.IsEqualTo("mts")) { RINOK(ParsePropToUInt32(UString(), propVariant, numThreads_Start)) continue; } if (name.IsEqualTo("af")) { UInt32 bundle; RINOK(ParsePropToUInt32(UString(), propVariant, bundle)) if (bundle > 0 && bundle < numCPUs) { #ifndef Z7_ST affinityMode.SetLevels(numCPUs, 2); affinityMode.NumBundleThreads = bundle; #endif } continue; } if (name.IsEqualTo("freq")) { UInt32 freq32 = 0; RINOK(ParsePropToUInt32(UString(), propVariant, freq32)) if (freq32 == 0) return E_INVALIDARG; specifiedFreq = (UInt64)freq32 * 1000000; if (printCallback) { printCallback->Print("freq="); PrintNumber(*printCallback, freq32, 0); printCallback->NewLine(); } continue; } if (name.IsPrefixedBy_Ascii_NoCase("mt")) { const UString s = name.Ptr(2); if (s.IsEqualTo("*") || (s.IsEmpty() && propVariant.vt == VT_BSTR && StringsAreEqual_Ascii(propVariant.bstrVal, "*"))) { multiThreadTests = true; continue; } #ifndef Z7_ST RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified)) #endif continue; } RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)) } } if (printCallback) { AString s; #if 1 || !defined(Z7_MSC_VER_ORIGINAL) || (Z7_MSC_VER_ORIGINAL >= 1900) s += "Compiler: "; GetCompiler(s); printCallback->Print(s); printCallback->NewLine(); s.Empty(); #endif GetSystemInfoText(s); printCallback->Print(s); printCallback->NewLine(); } if (printCallback) { printCallback->Print("1T CPU Freq (MHz):"); } if (printCallback || freqCallback) { UInt64 numMilCommands = 1 << 6; if (specifiedFreq != 0) { while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000)) numMilCommands >>= 1; } for (int jj = 0;; jj++) { if (printCallback) RINOK(printCallback->CheckBreak()) UInt64 start = ::GetTimeCount(); UInt32 sum = (UInt32)start; sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp); if (sum == 0xF1541213) if (printCallback) printCallback->Print(""); const UInt64 realDelta = ::GetTimeCount() - start; start = realDelta; if (start == 0) start = 1; if (start > (UInt64)1 << 61) start = 1; const UInt64 freq = GetFreq(); // mips is constant in some compilers const UInt64 hzVal = MyMultDiv64(numMilCommands * 1000000, freq, start); const UInt64 mipsVal = numMilCommands * freq / start; if (printCallback) { if (realDelta == 0) { printCallback->Print(" -"); } else { // PrintNumber(*printCallback, start, 0); PrintNumber(*printCallback, mipsVal, 5); } } if (freqCallback) { RINOK(freqCallback->AddCpuFreq(1, hzVal, kBenchmarkUsageMult)) } if (jj >= 1) { bool needStop = (numMilCommands >= (1 << #ifdef _DEBUG 7 #else 11 #endif )); if (start >= freq * 16) { printCallback->Print(" (Cmplx)"); if (!freqCallback) // we don't want complexity change for old gui lzma benchmark { needSetComplexity = true; } needStop = true; } if (needSetComplexity) SetComplexCommandsMs(testTimeMs, false, mipsVal * 1000000, complexInCommands); if (needStop) break; numMilCommands <<= 1; } } if (freqCallback) { RINOK(freqCallback->FreqsFinished(1)) } } if (printCallback || freqCallback) for (unsigned test = 0; test < 3; test++) { if (numThreadsSpecified < 2) { // if (test == 1) break; } if (test == 2 && numThreadsSpecified <= numCPUs) break; if (printCallback) printCallback->NewLine(); /* it can show incorrect frequency for HT threads. */ UInt32 numThreads = numThreadsSpecified; if (test < 2) { if (numThreads >= numCPUs) numThreads = numCPUs; if (test == 0) numThreads /= 2; } if (numThreads < 1) numThreads = 1; if (printCallback) { char s[128]; ConvertUInt64ToString(numThreads, s); printCallback->Print(s); printCallback->Print("T CPU Freq (MHz):"); } UInt64 numMilCommands = 1 << #ifdef _DEBUG 7; #else 10; #endif if (specifiedFreq != 0) { while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000)) numMilCommands >>= 1; } // for (int jj = 0;; jj++) for (;;) { if (printCallback) RINOK(printCallback->CheckBreak()) { // PrintLeft(f, "CPU", kFieldSize_Name); // UInt32 resVal; CFreqBench fb; fb.complexInCommands = numMilCommands * 1000000; fb.numThreads = numThreads; // showFreq; // fb.showFreq = (freqTest == kNumCpuTests - 1 || specifiedFreq != 0); fb.showFreq = true; fb.specifiedFreq = 1; const HRESULT res = fb.FreqBench(NULL /* printCallback */ #ifndef Z7_ST , &affinityMode #endif ); RINOK(res) if (freqCallback) { RINOK(freqCallback->AddCpuFreq(numThreads, fb.CpuFreqRes, fb.UsageRes)) } if (printCallback) { /* if (realDelta == 0) { printCallback->Print(" -"); } else */ { // PrintNumber(*printCallback, start, 0); PrintUsage(*printCallback, fb.UsageRes, 3); printCallback->Print("%"); PrintNumber(*printCallback, fb.CpuFreqRes / 1000000, 0); printCallback->Print(" "); // PrintNumber(*printCallback, fb.UsageRes, 5); } } } // if (jj >= 1) { const bool needStop = (numMilCommands >= (1 << #ifdef _DEBUG 7 #else 11 #endif )); if (needStop) break; numMilCommands <<= 1; } } if (freqCallback) { RINOK(freqCallback->FreqsFinished(numThreads)) } } if (printCallback) { printCallback->NewLine(); printCallback->NewLine(); PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs); printCallback->Print(GetProcessThreadsInfo(threadsInfo)); printCallback->NewLine(); } if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax) return E_INVALIDARG; UInt64 dict = (UInt64)1 << startDicLog; const bool dictIsDefined = (isFixedDict || method.Get_DicSize(dict)); const unsigned level = method.GetLevel(); AString &methodName = method.MethodName; const AString original_MethodName = methodName; if (methodName.IsEmpty()) methodName = "LZMA"; if (benchCallback) { CBenchProps benchProps; benchProps.SetLzmaCompexity(); const UInt64 dictSize = method.Get_Lzma_DicSize(); size_t uncompressedDataSize; if (use_fileData) { uncompressedDataSize = fileDataBuffer.Size(); } else { uncompressedDataSize = kAdditionalSize + (size_t)dictSize; if (uncompressedDataSize < dictSize) return E_INVALIDARG; } return MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, #ifndef Z7_ST true, numThreadsSpecified, &affinityMode, #endif method, uncompressedDataSize, (const Byte *)fileDataBuffer, kOldLzmaDictBits, printCallback, benchCallback, &benchProps); } if (methodName.IsEqualTo_Ascii_NoCase("CRC")) methodName = "crc32"; CMethodId hashID; const bool isHashMethod = FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID); int codecIndex = -1; bool isFilter = false; if (!isHashMethod) { UInt32 numStreams; codecIndex = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS original_MethodName, true, // encode hashID, numStreams, isFilter); // we can allow non filter for BW tests if (!isFilter) codecIndex = -1; } CBenchCallbackToPrint callback; callback.Init(); callback._file = printCallback; if (isHashMethod || codecIndex != -1) { if (!printCallback) return S_FALSE; IBenchPrintCallback &f = *printCallback; UInt64 dict64 = dict; if (!dictIsDefined) dict64 = (1 << 27); if (use_fileData) { if (!dictIsDefined) dict64 = fileDataBuffer.Size(); else if (dict64 > fileDataBuffer.Size()) dict64 = fileDataBuffer.Size(); } for (;;) { const int index = method.FindProp(NCoderPropID::kDictionarySize); if (index < 0) break; method.Props.Delete((unsigned)index); } // methodName.RemoveChar(L'-'); Int32 complexity = 16 * k_Hash_Complex_Mult; // for unknown hash method const UInt32 *checkSum = NULL; int benchIndex = -1; if (isHashMethod) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Hash); i++) { const CBenchHash &h = g_Hash[i]; AString benchMethod (h.Name); AString benchProps; const int propPos = benchMethod.Find(':'); if (propPos >= 0) { benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); benchMethod.DeleteFrom((unsigned)propPos); } if (AreSameMethodNames(benchMethod, methodName)) { const bool sameProps = method.PropsString.IsEqualTo_Ascii_NoCase(benchProps); /* bool isMainMethod = method.PropsString.IsEmpty(); if (isMainMethod) isMainMethod = !checkSum || (benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps.IsEqualTo_Ascii_NoCase("8")); if (sameProps || isMainMethod) */ { complexity = (Int32)h.Complex; checkSum = &h.CheckSum; if (sameProps) break; /* if property. is not specified, we use the complexity for latest fastest method (crc32:64) */ } } } // if (!checkSum) return E_NOTIMPL; } else { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Bench); i++) { const CBenchMethod &bench = g_Bench[i]; AString benchMethod (bench.Name); AString benchProps; const int propPos = benchMethod.Find(':'); if (propPos >= 0) { benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); benchMethod.DeleteFrom((unsigned)propPos); } if (AreSameMethodNames(benchMethod, methodName)) { const bool sameProps = method.PropsString.IsEqualTo_Ascii_NoCase(benchProps); // bool isMainMethod = method.PropsString.IsEmpty(); // if (sameProps || isMainMethod) { benchIndex = (int)i; if (sameProps) break; } } } // if (benchIndex < 0) return E_NOTIMPL; } { /* we count usage only for crc and filter. non-filters are not supported */ UInt64 usage = (1 << 20); UInt64 bufSize = dict64; UInt32 numBlocks = isHashMethod ? 1 : 3; if (use_fileData) { usage += fileDataBuffer.Size(); if (bufSize > fileDataBuffer.Size()) bufSize = fileDataBuffer.Size(); if (isHashMethod) { numBlocks = 0; #ifndef Z7_ST if (numThreadsSpecified != 1) numBlocks = (k_Crc_CreateLocalBuf_For_File ? 1 : 0); #endif } } usage += numThreadsSpecified * bufSize * numBlocks; Print_Usage_and_Threads(f, usage, numThreadsSpecified); } CUIntVector numThreadsVector; { unsigned nt = numThreads_Start; for (;;) { if (nt > numThreadsSpecified) break; numThreadsVector.Add(nt); const unsigned next = nt * 2; const UInt32 ntHalf= numThreadsSpecified / 2; if (ntHalf > nt && ntHalf < next) numThreadsVector.Add(ntHalf); if (numThreadsSpecified > nt && numThreadsSpecified < next) numThreadsVector.Add(numThreadsSpecified); nt = next; } } unsigned numColumns = isHashMethod ? 1 : 2; CTempValues speedTotals; CTempValues usageTotals; { const unsigned numItems = numThreadsVector.Size() * numColumns; speedTotals.Alloc(numItems); usageTotals.Alloc(numItems); for (unsigned i = 0; i < numItems; i++) { speedTotals.Values[i] = 0; usageTotals.Values[i] = 0; } } f.NewLine(); for (unsigned line = 0; line < 3; line++) { f.NewLine(); f.Print(line == 0 ? "THRD" : line == 1 ? " " : "Size"); FOR_VECTOR (ti, numThreadsVector) { if (ti != 0) Print_Delimiter(f); if (line == 0) { PrintSpaces(f, (kFieldSize_CrcSpeed + kFieldSize_Usage + 2) * (numColumns - 1)); PrintNumber(f, numThreadsVector[ti], 1 + kFieldSize_Usage + kFieldSize_CrcSpeed); } else { for (unsigned c = 0; c < numColumns; c++) { PrintRight(f, line == 1 ? "Usage" : "%", kFieldSize_Usage + 1); PrintRight(f, line == 1 ? "BW" : "MB/s", kFieldSize_CrcSpeed + 1); } } } } f.NewLine(); UInt64 numSteps = 0; // for (UInt32 iter = 0; iter < numIterations; iter++) // { unsigned pow = 10; // kNumHashDictBits if (startDicLog_Defined) pow = startDicLog; // #define NUM_SUB_BITS 2 // pow <<= NUM_SUB_BITS; for (;; pow++) { const UInt64 bufSize = (UInt64)1 << pow; // UInt64 bufSize = (UInt64)1 << (pow >> NUM_SUB_BITS); // bufSize += ((UInt64)pow & ((1 << NUM_SUB_BITS) - 1)) << ((pow >> NUM_SUB_BITS) - NUM_SUB_BITS); size_t dataSize = fileDataBuffer.Size(); if (dataSize > bufSize || !use_fileData) dataSize = (size_t)bufSize; for (UInt32 iter = 0; iter < numIterations; iter++) { Print_Pow(f, pow); // PrintNumber(f, bufSize >> 10, 4); FOR_VECTOR (ti, numThreadsVector) { RINOK(f.CheckBreak()) const UInt32 numThreads = numThreadsVector[ti]; if (isHashMethod) { UInt64 speed = 0; UInt64 usage = 0; const HRESULT res = CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, dataSize, (const Byte *)fileDataBuffer, speed, usage, (UInt32)complexity, 1, // benchWeight, (pow == kNumHashDictBits && !use_fileData) ? checkSum : NULL, method, &f, #ifndef Z7_ST &affinityMode, #endif false, // showRating NULL, false, 0); RINOK(res) if (ti != 0) Print_Delimiter(f); Bench_BW_Print_Usage_Speed(f, usage, speed); speedTotals.Values[ti] += speed; usageTotals.Values[ti] += usage; } else { { unsigned keySize = 32; if (IsString1PrefixedByString2(methodName, "AES128")) keySize = 16; else if (IsString1PrefixedByString2(methodName, "AES192")) keySize = 24; callback.BenchProps.KeySize = keySize; } COneMethodInfo method2 = method; unsigned bench_DictBits; if (benchIndex >= 0) { const CBenchMethod &bench = g_Bench[benchIndex]; callback.BenchProps.EncComplex = bench.EncComplex; callback.BenchProps.DecComplexUnc = bench.DecComplexUnc; callback.BenchProps.DecComplexCompr = bench.DecComplexCompr; bench_DictBits = bench.DictBits; // bench_DictBits = kOldLzmaDictBits; = 32 default : for debug } else { bench_DictBits = kOldLzmaDictBits; // = 32 default if (isFilter) { const unsigned k_UnknownCoderComplexity = 4; callback.BenchProps.EncComplex = k_UnknownCoderComplexity; callback.BenchProps.DecComplexUnc = k_UnknownCoderComplexity; } else { callback.BenchProps.EncComplex = 1 << 10; callback.BenchProps.DecComplexUnc = 1 << 6; } callback.BenchProps.DecComplexCompr = 0; } callback.NeedPrint = false; if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA")) { const NCOM::CPropVariant propVariant = (UInt32)pow; RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant)) } const HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, #ifndef Z7_ST false, // oldLzmaBenchMode numThreadsVector[ti], &affinityMode, #endif method2, dataSize, (const Byte *)fileDataBuffer, bench_DictBits, printCallback, &callback, &callback.BenchProps); RINOK(res) if (ti != 0) Print_Delimiter(f); for (unsigned i = 0; i < 2; i++) { const CBenchInfo &bi = callback.BenchInfo_Results[i]; const UInt64 usage = bi.GetUsage(); const UInt64 speed = bi.GetUnpackSizeSpeed(); usageTotals.Values[ti * 2 + i] += usage; speedTotals.Values[ti * 2 + i] += speed; Bench_BW_Print_Usage_Speed(f, usage, speed); } } } f.NewLine(); numSteps++; } if (dataSize >= dict64) break; } if (numSteps != 0) { f.Print("Avg:"); for (unsigned ti = 0; ti < numThreadsVector.Size(); ti++) { if (ti != 0) Print_Delimiter(f); for (unsigned i = 0; i < numColumns; i++) Bench_BW_Print_Usage_Speed(f, usageTotals.Values[ti * numColumns + i] / numSteps, speedTotals.Values[ti * numColumns + i] / numSteps); } f.NewLine(); } return S_OK; } bool use2Columns = false; bool totalBenchMode = false; bool onlyHashBench = false; if (methodName.IsEqualTo_Ascii_NoCase("hash")) { onlyHashBench = true; methodName = "*"; totalBenchMode = true; } else if (methodName.Find('*') >= 0) totalBenchMode = true; // ---------- Threads loop ---------- for (unsigned threadsPassIndex = 0; threadsPassIndex < 3; threadsPassIndex++) { UInt32 numThreads = numThreadsSpecified; if (!multiThreadTests) { if (threadsPassIndex != 0) break; } else { numThreads = 1; if (threadsPassIndex != 0) { if (numCPUs < 2) break; numThreads = numCPUs; if (threadsPassIndex == 1) { if (numCPUs >= 4) numThreads = numCPUs / 2; } else if (numCPUs < 4) break; } } IBenchPrintCallback &f = *printCallback; if (threadsPassIndex > 0) { f.NewLine(); f.NewLine(); } if (!dictIsDefined && !onlyHashBench) { const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); unsigned dicSizeLog = dicSizeLog_Main; #ifdef UNDER_CE dicSizeLog = (UInt64)1 << 20; #endif if (ramSize_Defined) for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, (int)level, ((UInt64)1 << dicSizeLog), totalBenchMode) + (8 << 20) <= ramSize) break; dict = (UInt64)1 << dicSizeLog; if (totalBenchMode && dicSizeLog != dicSizeLog_Main) { f.Print("Dictionary reduced to: "); PrintNumber(f, dicSizeLog, 1); f.NewLine(); } } Print_Usage_and_Threads(f, onlyHashBench ? GetBenchMemoryUsage_Hash(numThreads, dict) : GetBenchMemoryUsage(numThreads, (int)level, dict, totalBenchMode), numThreads); f.NewLine(); f.NewLine(); if (totalBenchMode) { callback.NameFieldSize = kFieldSize_Name; use2Columns = false; } else { callback.NameFieldSize = kFieldSize_SmallName; use2Columns = true; } callback.Use2Columns = use2Columns; bool showFreq = false; UInt64 cpuFreq = 0; if (totalBenchMode) { showFreq = true; } unsigned fileldSize = kFieldSize_TotalSize; if (showFreq) fileldSize += kFieldSize_EUAndEffec; if (use2Columns) { PrintSpaces(f, callback.NameFieldSize); PrintRight(f, "Compressing", fileldSize); f.Print(kSep); PrintRight(f, "Decompressing", fileldSize); } f.NewLine(); PrintLeft(f, totalBenchMode ? "Method" : "Dict", callback.NameFieldSize); int j; for (j = 0; j < 2; j++) { PrintRight(f, "Speed", kFieldSize_Speed + 1); PrintRight(f, "Usage", kFieldSize_Usage + 1); PrintRight(f, "R/U", kFieldSize_RU + 1); PrintRight(f, "Rating", kFieldSize_Rating + 1); if (showFreq) { PrintRight(f, "E/U", kFieldSize_EU + 1); PrintRight(f, "Effec", kFieldSize_Effec + 1); } if (!use2Columns) break; if (j == 0) f.Print(kSep); } f.NewLine(); PrintSpaces(f, callback.NameFieldSize); for (j = 0; j < 2; j++) { PrintRight(f, "KiB/s", kFieldSize_Speed + 1); PrintRight(f, "%", kFieldSize_Usage + 1); PrintRight(f, "MIPS", kFieldSize_RU + 1); PrintRight(f, "MIPS", kFieldSize_Rating + 1); if (showFreq) { PrintRight(f, "%", kFieldSize_EU + 1); PrintRight(f, "%", kFieldSize_Effec + 1); } if (!use2Columns) break; if (j == 0) f.Print(kSep); } f.NewLine(); f.NewLine(); if (specifiedFreq != 0) cpuFreq = specifiedFreq; // bool showTotalSpeed = false; if (totalBenchMode) { for (UInt32 i = 0; i < numIterations; i++) { if (i != 0) printCallback->NewLine(); const unsigned kNumCpuTests = 3; for (unsigned freqTest = 0; freqTest < kNumCpuTests; freqTest++) { PrintLeft(f, "CPU", kFieldSize_Name); // UInt32 resVal; CFreqBench fb; fb.complexInCommands = complexInCommands; fb.numThreads = numThreads; // showFreq; fb.showFreq = (freqTest == kNumCpuTests - 1 || specifiedFreq != 0); fb.specifiedFreq = specifiedFreq; const HRESULT res = fb.FreqBench(printCallback #ifndef Z7_ST , &affinityMode #endif ); RINOK(res) cpuFreq = fb.CpuFreqRes; callback.NewLine(); if (specifiedFreq != 0) cpuFreq = specifiedFreq; if (testTimeMs >= 1000) if (freqTest == kNumCpuTests - 1) { // SetComplexCommandsMs(testTimeMs, specifiedFreq != 0, cpuFreq, complexInCommands); } } callback.NewLine(); // return S_OK; // change it callback.SetFreq(true, cpuFreq); if (!onlyHashBench) { size_t dataSize = (size_t)dict; if (use_fileData) { dataSize = fileDataBuffer.Size(); if (dictIsDefined && dataSize > dict) dataSize = (size_t)dict; } const HRESULT res = TotalBench(EXTERNAL_CODECS_LOC_VARS method, complexInCommands, #ifndef Z7_ST numThreads, &affinityMode, #endif dictIsDefined || use_fileData, // forceUnpackSize dataSize, (const Byte *)fileDataBuffer, printCallback, &callback); RINOK(res) } { size_t dataSize = (size_t)1 << kNumHashDictBits; if (dictIsDefined) { dataSize = (size_t)dict; if (dataSize != dict) return E_OUTOFMEMORY; } if (use_fileData) { dataSize = fileDataBuffer.Size(); if (dictIsDefined && dataSize > dict) dataSize = (size_t)dict; } const HRESULT res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS method, complexInCommands, numThreads, dataSize, (const Byte *)fileDataBuffer, printCallback, &callback, #ifndef Z7_ST &affinityMode, #endif &callback.EncodeRes, true, cpuFreq); RINOK(res) } callback.NewLine(); { PrintLeft(f, "CPU", kFieldSize_Name); CFreqBench fb; fb.complexInCommands = complexInCommands; fb.numThreads = numThreads; // showFreq; fb.showFreq = (specifiedFreq != 0); fb.specifiedFreq = specifiedFreq; const HRESULT res = fb.FreqBench(printCallback #ifndef Z7_ST , &affinityMode #endif ); RINOK(res) callback.NewLine(); } } } else { needSetComplexity = true; if (!methodName.IsEqualTo_Ascii_NoCase("LZMA")) { unsigned i; for (i = 0; i < Z7_ARRAY_SIZE(g_Bench); i++) { const CBenchMethod &h = g_Bench[i]; AString benchMethod (h.Name); AString benchProps; const int propPos = benchMethod.Find(':'); if (propPos >= 0) { benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); benchMethod.DeleteFrom((unsigned)propPos); } if (AreSameMethodNames(benchMethod, methodName)) { if (benchProps.IsEmpty() || (benchProps == "x5" && method.PropsString.IsEmpty()) || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) { callback.BenchProps.EncComplex = h.EncComplex; callback.BenchProps.DecComplexCompr = h.DecComplexCompr; callback.BenchProps.DecComplexUnc = h.DecComplexUnc; needSetComplexity = false; break; } } } /* if (i == Z7_ARRAY_SIZE(g_Bench)) return E_NOTIMPL; */ } if (needSetComplexity) callback.BenchProps.SetLzmaCompexity(); if (startDicLog < kBenchMinDicLogSize) startDicLog = kBenchMinDicLogSize; for (unsigned i = 0; i < numIterations; i++) { unsigned pow = (dict < GetDictSizeFromLog(startDicLog)) ? kBenchMinDicLogSize : (unsigned)startDicLog; if (!multiDict) pow = 32; while (GetDictSizeFromLog(pow) > dict && pow > 0) pow--; for (; GetDictSizeFromLog(pow) <= dict; pow++) { Print_Pow(f, pow); callback.DictSize = (UInt64)1 << pow; COneMethodInfo method2 = method; if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA")) { // We add dictionary size property. // method2 can have two different dictionary size properties. // And last property is main. NCOM::CPropVariant propVariant = (UInt32)pow; RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant)) } size_t uncompressedDataSize; if (use_fileData) { uncompressedDataSize = fileDataBuffer.Size(); } else { uncompressedDataSize = (size_t)callback.DictSize; if (uncompressedDataSize != callback.DictSize) return E_OUTOFMEMORY; if (uncompressedDataSize >= (1 << 18)) uncompressedDataSize += kAdditionalSize; } const HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, #ifndef Z7_ST true, numThreads, &affinityMode, #endif method2, uncompressedDataSize, (const Byte *)fileDataBuffer, kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); f.NewLine(); RINOK(res) if (!multiDict) break; } } } PrintChars(f, '-', callback.NameFieldSize + fileldSize); if (use2Columns) { f.Print(kSep); PrintChars(f, '-', fileldSize); } f.NewLine(); if (use2Columns) { PrintLeft(f, "Avr:", callback.NameFieldSize); PrintTotals(f, showFreq, cpuFreq, !totalBenchMode, callback.EncodeRes); f.Print(kSep); PrintTotals(f, showFreq, cpuFreq, !totalBenchMode, callback.DecodeRes); f.NewLine(); } PrintLeft(f, "Tot:", callback.NameFieldSize); CTotalBenchRes midRes; midRes = callback.EncodeRes; midRes.Update_With_Res(callback.DecodeRes); // midRes.SetSum(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, showFreq, cpuFreq, false, midRes); f.NewLine(); } return S_OK; } tmp41wklro_/CPP/7zip/UI/Common/Bench.h0000444000175000001440000000652014413476000020413 0ustar nabijaczleweliusers// Bench.h #ifndef ZIP7_INC_7ZIP_BENCH_H #define ZIP7_INC_7ZIP_BENCH_H #include "../../../Windows/System.h" #include "../../Common/CreateCoder.h" #include "../../UI/Common/Property.h" UInt64 Benchmark_GetUsage_Percents(UInt64 usage); struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumIterations; /* during Code(): we track benchInfo only from one thread (theads with index[0]) NumIterations means number of threads UnpackSize and PackSize are total sizes of all iterations of current thread after Code(): NumIterations means the number of Iterations UnpackSize and PackSize are total sizes of all threads */ CBenchInfo(): NumIterations(0) {} UInt64 GetUsage() const; UInt64 GetRatingPerUsage(UInt64 rating) const; UInt64 GetSpeed(UInt64 numUnits) const; UInt64 GetUnpackSizeSpeed() const { return GetSpeed(UnpackSize * NumIterations); } UInt64 Get_UnpackSize_Full() const { return UnpackSize * NumIterations; } UInt64 GetRating_LzmaEnc(UInt64 dictSize) const; UInt64 GetRating_LzmaDec() const; }; struct CTotalBenchRes { // UInt64 NumIterations1; // for Usage UInt64 NumIterations2; // for Rating / RPU UInt64 Rating; UInt64 Usage; UInt64 RPU; UInt64 Speed; void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; Speed = 0; } void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating); Usage = (r1.Usage + r2.Usage); RPU = (r1.RPU + r2.RPU); Speed = (r1.Speed + r2.Speed); // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1); NumIterations2 = (r1.NumIterations2 + r2.NumIterations2); } void Generate_From_BenchInfo(const CBenchInfo &info); void Mult_For_Weight(unsigned weight); void Update_With_Res(const CTotalBenchRes &r); }; const unsigned kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench); Z7_PURE_INTERFACES_BEGIN DECLARE_INTERFACE(IBenchCallback) { // virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0; virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; DECLARE_INTERFACE(IBenchPrintCallback) { virtual void Print(const char *s) = 0; virtual void NewLine() = 0; virtual HRESULT CheckBreak() = 0; }; DECLARE_INTERFACE(IBenchFreqCallback) { virtual HRESULT AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage) = 0; virtual HRESULT FreqsFinished(unsigned numThreads) = 0; }; Z7_PURE_INTERFACES_END HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, const CObjectVector &props, UInt32 numIterations, bool multiDict, IBenchFreqCallback *freqCallback = NULL); AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti); void GetSysInfo(AString &s1, AString &s2); void GetCpuName(AString &s); void AddCpuFeatures(AString &s); #ifdef Z7_LARGE_PAGES void Add_LargePages_String(AString &s); #else // #define Add_LargePages_String #endif #endif tmp41wklro_/CPP/7zip/UI/Common/DefaultName.cpp0000444000175000001440000000200114003333334022077 0ustar nabijaczleweliusers// DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { const unsigned extLen = extension.Len(); const unsigned fileNameLen = fileName.Len(); if (fileNameLen > extLen + 1) { const unsigned dotPos = fileNameLen - (extLen + 1); if (fileName[dotPos] == '.') if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1))) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind_Dot(); if (dotPos > 0) return fileName.Left((unsigned)dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L'~'; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } tmp41wklro_/CPP/7zip/UI/Common/DefaultName.h0000444000175000001440000000037514357314620021571 0ustar nabijaczleweliusers// DefaultName.h #ifndef ZIP7_INC_DEFAULT_NAME_H #define ZIP7_INC_DEFAULT_NAME_H #include "../../../Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif tmp41wklro_/CPP/7zip/UI/Common/DirItem.h0000444000175000001440000002253414561635420020743 0ustar nabijaczleweliusers// DirItem.h #ifndef ZIP7_INC_DIR_ITEM_H #define ZIP7_INC_DIR_ITEM_H #ifdef _WIN32 #include "../../../Common/MyLinux.h" #endif #include "../../../Common/MyString.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/TimeUtils.h" #include "../../Common/UniqBlocks.h" #include "../../Archive/IArchive.h" struct CDirItemsStat { UInt64 NumDirs; UInt64 NumFiles; UInt64 NumAltStreams; UInt64 FilesSize; UInt64 AltStreamsSize; UInt64 NumErrors; // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; } UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; } UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; } bool IsEmpty() const { return 0 == NumDirs && 0 == NumFiles && 0 == NumAltStreams && 0 == FilesSize && 0 == AltStreamsSize && 0 == NumErrors; } CDirItemsStat(): NumDirs(0), NumFiles(0), NumAltStreams(0), FilesSize(0), AltStreamsSize(0), NumErrors(0) {} }; struct CDirItemsStat2: public CDirItemsStat { UInt64 Anti_NumDirs; UInt64 Anti_NumFiles; UInt64 Anti_NumAltStreams; // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); } UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); } bool IsEmpty() const { return CDirItemsStat::IsEmpty() && 0 == Anti_NumDirs && 0 == Anti_NumFiles && 0 == Anti_NumAltStreams; } CDirItemsStat2(): Anti_NumDirs(0), Anti_NumFiles(0), Anti_NumAltStreams(0) {} }; Z7_PURE_INTERFACES_BEGIN #define Z7_IFACEN_IDirItemsCallback(x) \ virtual HRESULT ScanError(const FString &path, DWORD systemError) x \ virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x \ Z7_IFACE_DECL_PURE(IDirItemsCallback) Z7_PURE_INTERFACES_END struct CArcTime { FILETIME FT; UInt16 Prec; Byte Ns100; bool Def; CArcTime() { Clear(); } void Clear() { FT.dwHighDateTime = FT.dwLowDateTime = 0; Prec = 0; Ns100 = 0; Def = false; } bool IsZero() const { return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0; } int CompareWith(const CArcTime &a) const { const int res = CompareFileTime(&FT, &a.FT); if (res != 0) return res; if (Ns100 < a.Ns100) return -1; if (Ns100 > a.Ns100) return 1; return 0; } UInt64 Get_FILETIME_as_UInt64() const { return (((UInt64)FT.dwHighDateTime) << 32) + FT.dwLowDateTime; } UInt32 Get_DosTime() const { FILETIME ft2 = FT; if ((Prec == k_PropVar_TimePrec_Base + 8 || Prec == k_PropVar_TimePrec_Base + 9) && Ns100 != 0) { UInt64 u64 = Get_FILETIME_as_UInt64(); // we round up even small (ns < 100ns) as FileTimeToDosTime() if (u64 % 20000000 == 0) { u64++; ft2.dwHighDateTime = (DWORD)(u64 >> 32); ft2.dwHighDateTime = (DWORD)u64; } } // FileTimeToDosTime() is expected to round up in Windows UInt32 dosTime; // we use simplified code with utctime->dos. // do we need local time instead here? NWindows::NTime::FileTime_To_DosTime(ft2, dosTime); return dosTime; } int GetNumDigits() const { if (Prec == k_PropVar_TimePrec_Unix || Prec == k_PropVar_TimePrec_DOS) return 0; if (Prec == k_PropVar_TimePrec_HighPrec) return 9; if (Prec == k_PropVar_TimePrec_0) return 7; int digits = (int)Prec - (int)k_PropVar_TimePrec_Base; if (digits < 0) digits = 0; return digits; } void Write_To_FiTime(CFiTime &dest) const { #ifdef _WIN32 dest = FT; #else if (FILETIME_To_timespec(FT, dest)) if ((Prec == k_PropVar_TimePrec_Base + 8 || Prec == k_PropVar_TimePrec_Base + 9) && Ns100 != 0) { dest.tv_nsec += Ns100; } #endif } // (Def) is not set void Set_From_FILETIME(const FILETIME &ft) { FT = ft; // Prec = k_PropVar_TimePrec_CompatNTFS; Prec = k_PropVar_TimePrec_Base + 7; Ns100 = 0; } // (Def) is not set // it set full form precision: k_PropVar_TimePrec_Base + numDigits void Set_From_FiTime(const CFiTime &ts) { #ifdef _WIN32 FT = ts; Prec = k_PropVar_TimePrec_Base + 7; // Prec = k_PropVar_TimePrec_Base; // for debug // Prec = 0; // for debug Ns100 = 0; #else unsigned ns100; FiTime_To_FILETIME_ns100(ts, FT, ns100); Ns100 = (Byte)ns100; Prec = k_PropVar_TimePrec_Base + 9; #endif } void Set_From_Prop(const PROPVARIANT &prop) { FT = prop.filetime; unsigned prec = 0; unsigned ns100 = 0; const unsigned prec_Temp = prop.wReserved1; if (prec_Temp != 0 && prec_Temp <= k_PropVar_TimePrec_1ns && prop.wReserved3 == 0) { const unsigned ns100_Temp = prop.wReserved2; if (ns100_Temp < 100) { ns100 = ns100_Temp; prec = prec_Temp; } } Prec = (UInt16)prec; Ns100 = (Byte)ns100; Def = true; } }; struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase { UString Name; #ifndef UNDER_CE CByteBuffer ReparseData; #ifdef _WIN32 // UString ShortName; CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } #else bool AreReparseData() const { return ReparseData.Size() != 0; } #endif // _WIN32 #endif // !UNDER_CE void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi) { (NWindows::NFile::NFind::CFileInfoBase &)*this = fi; } int PhyParent; int LogParent; int SecureIndex; #ifdef _WIN32 #else int OwnerNameIndex; int OwnerGroupIndex; #endif // bool Attrib_IsDefined; CDirItem(): PhyParent(-1) , LogParent(-1) , SecureIndex(-1) #ifdef _WIN32 #else , OwnerNameIndex(-1) , OwnerGroupIndex(-1) #endif // , Attrib_IsDefined(true) { } CDirItem(const NWindows::NFile::NFind::CFileInfo &fi, int phyParent, int logParent, int secureIndex): CFileInfoBase(fi) , Name(fs2us(fi.Name)) #if defined(_WIN32) && !defined(UNDER_CE) // , ShortName(fs2us(fi.ShortName)) #endif , PhyParent(phyParent) , LogParent(logParent) , SecureIndex(secureIndex) #ifdef _WIN32 #else , OwnerNameIndex(-1) , OwnerGroupIndex(-1) #endif {} }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); public: CObjectVector Items; bool SymLinks; bool ScanAltStreams; bool ExcludeDirItems; bool ExcludeFileItems; bool ShareForWrite; /* it must be called after anotrher checks */ bool CanIncludeItem(bool isDir) const { return isDir ? !ExcludeDirItems : !ExcludeFileItems; } CDirItemsStat Stat; #if !defined(UNDER_CE) HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, const FString &phyPrefix); #endif #if defined(_WIN32) && !defined(UNDER_CE) CUniqBlocks SecureBlocks; CByteBuffer TempSecureBuf; bool _saclEnabled; bool ReadSecure; HRESULT AddSecurityItem(const FString &path, int &secureIndex); HRESULT FillFixedReparse(); #endif #ifndef _WIN32 C_UInt32_UString_Map OwnerNameMap; C_UInt32_UString_Map OwnerGroupMap; bool StoreOwnerName; HRESULT FillDeviceSizes(); #endif IDirItemsCallback *Callback; CDirItems(); void AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NWindows::NFile::NFind::CFileInfo &fi); HRESULT AddError(const FString &path, DWORD errorCode); HRESULT AddError(const FString &path); HRESULT ScanProgress(const FString &path); // unsigned GetNumFolders() const { return Prefixes.Size(); } FString GetPhyPath(unsigned index) const; UString GetLogPath(unsigned index) const; unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector &files); HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector &files); HRESULT EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector *requestedPaths); void ReserveDown(); }; struct CArcItem { UInt64 Size; UString Name; CArcTime MTime; // it can be mtime of archive file, if MTime is not defined for item in archive bool IsDir; bool IsAltStream; bool Size_Defined; bool Censored; UInt32 IndexInServer; CArcItem(): IsDir(false), IsAltStream(false), Size_Defined(false), Censored(false) {} }; #endif tmp41wklro_/CPP/7zip/UI/Common/EnumDirItems.cpp0000444000175000001440000012322514553761200022302 0ustar nabijaczleweliusers// EnumDirItems.cpp #include "StdAfx.h" #include // #include #ifndef _WIN32 #include #include #include "../../../Common/UTFConvert.h" #endif #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/FileName.h" #if defined(_WIN32) && !defined(UNDER_CE) #define Z7_USE_SECURITY_CODE #include "../../../Windows/SecurityUtils.h" #endif #include "EnumDirItems.h" #include "SortUtils.h" using namespace NWindows; using namespace NFile; using namespace NName; static bool FindFile_KeepDots(NFile::NFind::CFileInfo &fi, const FString &path, bool followLink) { const bool res = fi.Find(path, followLink); if (!res) return res; if (path.IsEmpty()) return res; // we keep name "." and "..", if it's without tail slash const FChar *p = path.RightPtr(1); if (*p != '.') return res; if (p != path.Ptr()) { FChar c = p[-1]; if (!IS_PATH_SEPAR(c)) { if (c != '.') return res; p--; if (p != path.Ptr()) { c = p[-1]; if (!IS_PATH_SEPAR(c)) return res; } } } fi.Name = p; return res; } void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NFind::CFileInfo &fi) { /* CDirItem di(fi); di.PhyParent = phyParent; di.LogParent = logParent; di.SecureIndex = secureIndex; Items.Add(di); */ VECTOR_ADD_NEW_OBJECT (Items, CDirItem(fi, phyParent, logParent, secureIndex)) if (fi.IsDir()) Stat.NumDirs++; #ifdef _WIN32 else if (fi.IsAltStream) { Stat.NumAltStreams++; Stat.AltStreamsSize += fi.Size; } #endif else { Stat.NumFiles++; Stat.FilesSize += fi.Size; } } // (DWORD)E_FAIL #define DI_DEFAULT_ERROR ERROR_INVALID_FUNCTION HRESULT CDirItems::AddError(const FString &path, DWORD errorCode) { if (errorCode == 0) errorCode = DI_DEFAULT_ERROR; Stat.NumErrors++; if (Callback) return Callback->ScanError(path, errorCode); return S_OK; } HRESULT CDirItems::AddError(const FString &path) { return AddError(path, ::GetLastError()); } static const unsigned kScanProgressStepMask = (1 << 12) - 1; HRESULT CDirItems::ScanProgress(const FString &dirPath) { if (Callback) return Callback->ScanProgress(Stat, dirPath, true); return S_OK; } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; unsigned len = name.Len(); int i; for (i = index; i >= 0; i = parents[(unsigned)i]) len += Prefixes[(unsigned)i].Len(); wchar_t *p = path.GetBuf_SetEnd(len) + len; p -= name.Len(); wmemcpy(p, (const wchar_t *)name, name.Len()); for (i = index; i >= 0; i = parents[(unsigned)i]) { const UString &s = Prefixes[(unsigned)i]; p -= s.Len(); wmemcpy(p, (const wchar_t *)s, s.Len()); } return path; } FString CDirItems::GetPhyPath(unsigned index) const { const CDirItem &di = Items[index]; return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name)); } UString CDirItems::GetLogPath(unsigned index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } bool InitLocalPrivileges(); CDirItems::CDirItems(): SymLinks(false), ScanAltStreams(false) , ExcludeDirItems(false) , ExcludeFileItems(false) , ShareForWrite(false) #ifdef Z7_USE_SECURITY_CODE , ReadSecure(false) #endif #ifndef _WIN32 , StoreOwnerName(false) #endif , Callback(NULL) { #ifdef Z7_USE_SECURITY_CODE _saclEnabled = InitLocalPrivileges(); #endif } #ifdef Z7_USE_SECURITY_CODE HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) { secureIndex = -1; SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; if (_saclEnabled) securInfo |= SACL_SECURITY_INFORMATION; DWORD errorCode = 0; DWORD secureSize; BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); if (res) { if (secureSize == 0) return S_OK; if (secureSize > TempSecureBuf.Size()) errorCode = ERROR_INVALID_FUNCTION; } else { errorCode = GetLastError(); if (errorCode == ERROR_INSUFFICIENT_BUFFER) { if (secureSize <= TempSecureBuf.Size()) errorCode = ERROR_INVALID_FUNCTION; else { TempSecureBuf.Alloc(secureSize); res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); if (res) { if (secureSize != TempSecureBuf.Size()) errorCode = ERROR_INVALID_FUNCTION; } else errorCode = GetLastError(); } } } if (res) { secureIndex = (int)SecureBlocks.AddUniq(TempSecureBuf, secureSize); return S_OK; } return AddError(path, errorCode); } #endif // Z7_USE_SECURITY_CODE HRESULT CDirItems::EnumerateOneDir(const FString &phyPrefix, CObjectVector &files) { NFind::CEnumerator enumerator; // printf("\n enumerator.SetDirPrefix(phyPrefix) \n"); enumerator.SetDirPrefix(phyPrefix); #ifdef _WIN32 NFind::CFileInfo fi; for (unsigned ttt = 0; ; ttt++) { bool found; if (!enumerator.Next(fi, found)) return AddError(phyPrefix); if (!found) return S_OK; files.Add(fi); if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(ScanProgress(phyPrefix)) } } #else // _WIN32 // enumerator.SolveLinks = !SymLinks; CObjectVector entries; for (;;) { bool found; NFind::CDirEntry de; if (!enumerator.Next(de, found)) return AddError(phyPrefix); if (!found) break; entries.Add(de); } FOR_VECTOR(i, entries) { const NFind::CDirEntry &de = entries[i]; NFind::CFileInfo fi; if (!enumerator.Fill_FileInfo(de, fi, !SymLinks)) // if (!fi.Find_AfterEnumerator(path)) { const FString path = phyPrefix + de.Name; { RINOK(AddError(path)) continue; } } files.Add(fi); if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(ScanProgress(phyPrefix)) } } return S_OK; #endif // _WIN32 } HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { RINOK(ScanProgress(phyPrefix)) CObjectVector files; RINOK(EnumerateOneDir(phyPrefix, files)) FOR_VECTOR (i, files) { #ifdef _WIN32 const NFind::CFileInfo &fi = files[i]; #else const NFind::CFileInfo &fi = files[i]; /* NFind::CFileInfo fi; { const NFind::CDirEntry &di = files[i]; const FString path = phyPrefix + di.Name; if (!fi.Find_AfterEnumerator(path)) { RINOK(AddError(path)); continue; } fi.Name = di.Name; } */ #endif if (CanIncludeItem(fi.IsDir())) { int secureIndex = -1; #ifdef Z7_USE_SECURITY_CODE if (ReadSecure) { RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex)) } #endif AddDirFileInfo(phyParent, logParent, secureIndex, fi); } if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(ScanProgress(phyPrefix)) } if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + name2)) } } return S_OK; } /* EnumerateItems2() const FStringVector &filePaths - are path without tail slashes. All dir prefixes of filePaths will be not stores in logical paths fix it: we can scan AltStream also. */ #ifdef _WIN32 // #define FOLLOW_LINK_PARAM // #define FOLLOW_LINK_PARAM2 #define FOLLOW_LINK_PARAM , (!SymLinks) #define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) #else #define FOLLOW_LINK_PARAM , (!SymLinks) #define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) #endif HRESULT CDirItems::EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector *requestedPaths) { const int phyParent = phyPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, fs2us(phyPrefix)); const int logParent = logPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, logPrefix); #ifdef _WIN32 const bool phyPrefix_isAltStreamPrefix = NFile::NName::IsAltStreamPrefixWithColon(fs2us(phyPrefix)); #endif FOR_VECTOR (i, filePaths) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; if (!FindFile_KeepDots(fi, phyPath FOLLOW_LINK_PARAM)) { RINOK(AddError(phyPath)) continue; } if (requestedPaths) requestedPaths->Add(phyPath); const int delimiter = filePath.ReverseFind_PathSepar(); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur.SetFrom(filePath, (unsigned)(delimiter + 1)); phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } if (CanIncludeItem(fi.IsDir())) { int secureIndex = -1; #ifdef Z7_USE_SECURITY_CODE if (ReadSecure) { RINOK(AddSecurityItem(phyPath, secureIndex)) } #endif #ifdef _WIN32 if (phyPrefix_isAltStreamPrefix && fi.IsAltStream) { const int pos = fi.Name.Find(FChar(':')); if (pos >= 0) fi.Name.DeleteFrontal((unsigned)pos + 1); } #endif AddDirFileInfo(phyParentCur, logParent, secureIndex, fi); } if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; const unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + phyPrefixCur + name2)) } } ReserveDown(); return S_OK; } static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const int phyParent, const int logParent, const FString &phyPrefix, const UStringVector &addParts, // additional parts from curNode CDirItems &dirItems, bool enterToSubFolders); /* EnumerateDirItems_Spec() adds new Dir item prefix, and enumerates dir items, then it can remove that Dir item prefix, if there are no items in that dir. */ /* EnumerateDirItems_Spec() it's similar to EnumerateDirItems, but phyPrefix doesn't include (curFolderName) */ static HRESULT EnumerateDirItems_Spec( const NWildcard::CCensorNode &curNode, const int phyParent, const int logParent, const FString &curFolderName, const FString &phyPrefix, // without (curFolderName) const UStringVector &addParts, // (curNode + addParts) includes (curFolderName) CDirItems &dirItems, bool enterToSubFolders) { const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; const unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); const unsigned numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems( curNode, (int)parent, (int)parent, phyPrefix + name2, addParts, dirItems, enterToSubFolders); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } #ifndef UNDER_CE #ifdef _WIN32 static HRESULT EnumerateAltStreams( const NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, const int phyParent, const int logParent, const FString &phyPath, // with (fi.Name), without tail slash for folders const UStringVector &addParts, // with (fi.Name), prefix parts from curNode bool addAllSubStreams, CDirItems &dirItems) { // we don't use (ExcludeFileItems) rules for AltStreams // if (dirItems.ExcludeFileItems) return S_OK; NFind::CStreamEnumerator enumerator(phyPath); for (;;) { NFind::CStreamInfo si; bool found; if (!enumerator.Next(si, found)) { return dirItems.AddError(phyPath + FTEXT(":*")); // , (DWORD)E_FAIL } if (!found) return S_OK; if (si.IsMainStream()) continue; UStringVector parts = addParts; const UString reducedName = si.GetReducedName(); parts.Back() += reducedName; if (curNode.CheckPathToRoot(false, parts, true)) continue; if (!addAllSubStreams) if (!curNode.CheckPathToRoot(true, parts, true)) continue; NFind::CFileInfo fi2 = fi; fi2.Name += us2fs(reducedName); fi2.Size = si.Size; fi2.Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); fi2.IsAltStream = true; dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2); } } #endif // _WIN32 /* We get Reparse data and parse it. If there is Reparse error, we free dirItem.Reparse data. Do we need to work with empty reparse data? */ HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, const FString &phyPrefix) { if (!SymLinks) return S_OK; #ifdef _WIN32 if (!fi.HasReparsePoint() || fi.IsAltStream) #else // _WIN32 if (!fi.IsPosixLink()) #endif // _WIN32 return S_OK; const FString path = phyPrefix + fi.Name; CByteBuffer &buf = dirItem.ReparseData; if (NIO::GetReparseData(path, buf)) { // if (dirItem.ReparseData.Size() != 0) Stat.FilesSize -= fi.Size; return S_OK; } DWORD res = ::GetLastError(); buf.Free(); return AddError(path, res); } #endif // UNDER_CE static HRESULT EnumerateForItem( const NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, const int phyParent, const int logParent, const FString &phyPrefix, const UStringVector &addParts, // additional parts from curNode, without (fi.Name) CDirItems &dirItems, bool enterToSubFolders) { const UString name = fs2us(fi.Name); UStringVector newParts = addParts; newParts.Add(name); // check the path in exclude rules if (curNode.CheckPathToRoot(false, newParts, !fi.IsDir())) return S_OK; #if !defined(UNDER_CE) int dirItemIndex = -1; #if defined(_WIN32) bool addAllSubStreams = false; bool needAltStreams = true; #endif // _WIN32 #endif // !defined(UNDER_CE) // check the path in inlcude rules if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir())) { #if !defined(UNDER_CE) // dirItemIndex = (int)dirItems.Items.Size(); #if defined(_WIN32) // we will not check include rules for substreams. addAllSubStreams = true; #endif // _WIN32 #endif // !defined(UNDER_CE) if (dirItems.CanIncludeItem(fi.IsDir())) { int secureIndex = -1; #ifdef Z7_USE_SECURITY_CODE if (dirItems.ReadSecure) { RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex)) } #endif #if !defined(UNDER_CE) dirItemIndex = (int)dirItems.Items.Size(); #endif // !defined(UNDER_CE) dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); } else { #if defined(_WIN32) && !defined(UNDER_CE) needAltStreams = false; #endif } if (fi.IsDir()) enterToSubFolders = true; } #if !defined(UNDER_CE) // we don't scan AltStreams for link files if (dirItemIndex >= 0) { CDirItem &dirItem = dirItems.Items[(unsigned)dirItemIndex]; RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)) if (dirItem.ReparseData.Size() != 0) return S_OK; } #if defined(_WIN32) if (needAltStreams && dirItems.ScanAltStreams) { RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix + fi.Name, // with (fi.Name) newParts, // with (fi.Name) addAllSubStreams, dirItems)) } #endif #endif // !defined(UNDER_CE) #ifndef _WIN32 if (!fi.IsPosixLink()) // posix link can follow to dir #endif if (!fi.IsDir()) return S_OK; const NWildcard::CCensorNode *nextNode = NULL; if (addParts.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) { nextNode = &curNode.SubNodes[(unsigned)index]; newParts.Clear(); } } if (!nextNode) { if (!enterToSubFolders) return S_OK; #ifndef _WIN32 if (fi.IsPosixLink()) { // here we can try to resolve posix link // if the link to dir, then can we follow it return S_OK; // we don't follow posix link } #else if (dirItems.SymLinks && fi.HasReparsePoint()) { /* 20.03: in SymLinks mode: we don't enter to directory that has reparse point and has no CCensorNode NOTE: (curNode and parent nodes) still can have wildcard rules to include some items of target directory (of reparse point), but we ignore these rules here. */ return S_OK; } #endif nextNode = &curNode; } return EnumerateDirItems_Spec( *nextNode, phyParent, logParent, fi.Name, phyPrefix, // without (fi.Name) newParts, // relative to (*nextNode). (*nextNode + newParts) includes (fi.Name) dirItems, enterToSubFolders); } static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) { FOR_VECTOR (i, curNode.IncludeItems) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) return false; const UString &name = item.PathParts.Front(); /* if (name.IsEmpty()) return false; */ /* Windows doesn't support file name with wildcard But if another system supports file name with wildcard, and wildcard mode is disabled, we can ignore wildcard in name */ /* #ifndef _WIN32 if (!item.WildcardParsing) continue; #endif */ if (DoesNameContainWildcard(name)) return false; } return true; } #if defined(_WIN32) && !defined(UNDER_CE) static bool IsVirtualFsFolder(const FString &prefix, const UString &name) { UString s = fs2us(prefix); s += name; s.Add_PathSepar(); // it returns (true) for non real FS folder path like - "\\SERVER\" return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0; } #endif static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const int phyParent, const int logParent, const FString &phyPrefix, const UStringVector &addParts, // prefix from curNode including CDirItems &dirItems, bool enterToSubFolders) { if (!enterToSubFolders) { /* if there are IncludeItems censor rules that affect items in subdirs, then we will enter to all subfolders */ if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; } RINOK(dirItems.ScanProgress(phyPrefix)) // try direct_names case at first if (addParts.IsEmpty() && !enterToSubFolders) { if (CanUseFsDirect(curNode)) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector needEnterVector; unsigned i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); FString fullPath = phyPrefix + us2fs(name); /* // not possible now if (!item.ForDir && !item.ForFile) { RINOK(dirItems.AddError(fullPath, ERROR_INVALID_PARAMETER)); continue; } */ #if defined(_WIN32) && !defined(UNDER_CE) bool needAltStreams = true; #endif #ifdef Z7_USE_SECURITY_CODE bool needSecurity = true; #endif if (phyPrefix.IsEmpty()) { if (!item.ForFile) { /* we don't like some names for alt streams inside archive: ":sname" for "\" "c:::sname" for "C:\" So we ignore alt streams for these cases */ if (name.IsEmpty()) { #if defined(_WIN32) && !defined(UNDER_CE) needAltStreams = false; #endif /* // do we need to ignore security info for "\\" folder ? #ifdef Z7_USE_SECURITY_CODE needSecurity = false; #endif */ fullPath = CHAR_PATH_SEPARATOR; } #if defined(_WIN32) && !defined(UNDER_CE) else if (item.IsDriveItem()) { needAltStreams = false; fullPath.Add_PathSepar(); } #endif } } NFind::CFileInfo fi; #if defined(_WIN32) && !defined(UNDER_CE) if (IsVirtualFsFolder(phyPrefix, name)) { fi.SetAsDir(); fi.Name = us2fs(name); } else #endif if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2)) { RINOK(dirItems.AddError(fullPath)) continue; } /* #ifdef _WIN32 #define MY_ERROR_IS_DIR ERROR_FILE_NOT_FOUND #define MY_ERROR_NOT_DIR DI_DEFAULT_ERROR #else #define MY_ERROR_IS_DIR EISDIR #define MY_ERROR_NOT_DIR ENOTDIR #endif */ const bool isDir = fi.IsDir(); if (isDir ? !item.ForDir : !item.ForFile) { // RINOK(dirItems.AddError(fullPath, isDir ? MY_ERROR_IS_DIR: MY_ERROR_NOT_DIR)); RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)) continue; } { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } if (dirItems.CanIncludeItem(fi.IsDir())) { int secureIndex = -1; #ifdef Z7_USE_SECURITY_CODE if (needSecurity && dirItems.ReadSecure) { RINOK(dirItems.AddSecurityItem(fullPath, secureIndex)) } #endif dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); // we don't scan AltStreams for link files #if !defined(UNDER_CE) { CDirItem &dirItem = dirItems.Items.Back(); RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)) if (dirItem.ReparseData.Size() != 0) continue; } #if defined(_WIN32) if (needAltStreams && dirItems.ScanAltStreams) { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, fullPath, // including (name) pathParts, // including (fi.Name) true, /* addAllSubStreams */ dirItems)) } #endif // defined(_WIN32) #endif // !defined(UNDER_CE) } #ifndef _WIN32 if (!fi.IsPosixLink()) // posix link can follow to dir #endif if (!isDir) continue; UStringVector newParts; const NWildcard::CCensorNode *nextNode = NULL; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = (int)needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[(unsigned)index] = false; nextNode = &curNode.SubNodes[(unsigned)index]; } else { #ifndef _WIN32 if (fi.IsPosixLink()) { // here we can try to resolve posix link // if the link to dir, then can we follow it continue; // we don't follow posix link } #else if (dirItems.SymLinks) { if (fi.HasReparsePoint()) { /* 20.03: in SymLinks mode: we don't enter to directory that has reparse point and has no CCensorNode */ continue; } } #endif nextNode = &curNode; newParts.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, newParts, dirItems, true)) } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; FString fullPath = phyPrefix + us2fs(nextNode.Name); NFind::CFileInfo fi; if (nextNode.Name.IsEmpty()) { if (phyPrefix.IsEmpty()) fullPath = CHAR_PATH_SEPARATOR; } #ifdef _WIN32 else if(phyPrefix.IsEmpty() || (phyPrefix.Len() == NName::kSuperPathPrefixSize && IsSuperPath(phyPrefix))) { if (NWildcard::IsDriveColonName(nextNode.Name)) fullPath.Add_PathSepar(); } #endif // we don't want to call fi.Find() for root folder or virtual folder if ((phyPrefix.IsEmpty() && nextNode.Name.IsEmpty()) #if defined(_WIN32) && !defined(UNDER_CE) || IsVirtualFsFolder(phyPrefix, nextNode.Name) #endif ) { fi.SetAsDir(); fi.Name = us2fs(nextNode.Name); } else { if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2)) { if (!nextNode.AreThereIncludeItems()) continue; RINOK(dirItems.AddError(fullPath)) continue; } if (!fi.IsDir()) { RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)) continue; } } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false)) } return S_OK; } } #ifdef _WIN32 #ifndef UNDER_CE // scan drives, if wildcard is "*:\" if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0) { unsigned i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.PathParts.Size() < 1) break; const UString &name = item.PathParts.Front(); if (name.Len() != 2 || name[1] != ':') break; if (item.PathParts.Size() == 1) if (item.ForFile || !item.ForDir) break; if (NWildcard::IsDriveColonName(name)) continue; if (name[0] != '*' && name[0] != '?') break; } if (i == curNode.IncludeItems.Size()) { FStringVector driveStrings; NFind::MyGetLogicalDriveStrings(driveStrings); for (i = 0; i < driveStrings.Size(); i++) { FString driveName = driveStrings[i]; if (driveName.Len() < 3 || driveName.Back() != '\\') return E_FAIL; driveName.DeleteBack(); NFind::CFileInfo fi; fi.SetAsDir(); fi.Name = driveName; RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, addParts, dirItems, enterToSubFolders)) } return S_OK; } } #endif #endif CObjectVector files; // for (int y = 0; y < 1; y++) { // files.Clear(); RINOK(dirItems.EnumerateOneDir(phyPrefix, files)) /* FOR_VECTOR (i, files) { #ifdef _WIN32 // const NFind::CFileInfo &fi = files[i]; #else NFind::CFileInfo &fi = files[i]; { const NFind::CFileInfo &di = files[i]; const FString path = phyPrefix + di.Name; if (!fi.Find_AfterEnumerator(path)) { RINOK(dirItems.AddError(path)); continue; } fi.Name = di.Name; } #endif } */ } FOR_VECTOR (i, files) { #ifdef _WIN32 const NFind::CFileInfo &fi = files[i]; #else const NFind::CFileInfo &fi = files[i]; /* NFind::CFileInfo fi; { const NFind::CDirEntry &di = files[i]; const FString path = phyPrefix + di.Name; if (!fi.Find_AfterEnumerator(path)) { RINOK(dirItems.AddError(path)); continue; } fi.Name = di.Name; } */ #endif RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, addParts, dirItems, enterToSubFolders)) if (dirItems.Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(dirItems.ScanProgress(phyPrefix)) } } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, const NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, // prefix that will be added to Logical Path CDirItems &dirItems) { FOR_VECTOR (i, censor.Pairs) { const NWildcard::CPair &pair = censor.Pairs[i]; const int phyParent = pair.Prefix.IsEmpty() ? -1 : (int)dirItems.AddPrefix(-1, -1, pair.Prefix); int logParent = -1; if (pathMode == NWildcard::k_AbsPath) logParent = phyParent; else { if (!addPathPrefix.IsEmpty()) logParent = (int)dirItems.AddPrefix(-1, -1, addPathPrefix); } RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), dirItems, false // enterToSubFolders )) } dirItems.ReserveDown(); #if defined(_WIN32) && !defined(UNDER_CE) RINOK(dirItems.FillFixedReparse()) #endif #ifndef _WIN32 RINOK(dirItems.FillDeviceSizes()) #endif return S_OK; } #if defined(_WIN32) && !defined(UNDER_CE) HRESULT CDirItems::FillFixedReparse() { FOR_VECTOR(i, Items) { CDirItem &item = Items[i]; if (!SymLinks) { // continue; // for debug if (!item.Has_Attrib_ReparsePoint()) continue; // if (item.IsDir()) continue; const FString phyPath = GetPhyPath(i); NFind::CFileInfo fi; if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() { item.Size = fi.Size; item.CTime = fi.CTime; item.ATime = fi.ATime; item.MTime = fi.MTime; item.Attrib = fi.Attrib; continue; } /* // we request properties of target file instead of properies of symbolic link // here we also can manually parse unsupported links (like WSL links) NIO::CInFile inFile; if (inFile.Open(phyPath)) { BY_HANDLE_FILE_INFORMATION info; if (inFile.GetFileInformation(&info)) { // Stat.FilesSize doesn't contain item.Size already // Stat.FilesSize -= item.Size; item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; Stat.FilesSize += item.Size; item.CTime = info.ftCreationTime; item.ATime = info.ftLastAccessTime; item.MTime = info.ftLastWriteTime; item.Attrib = info.dwFileAttributes; continue; } } */ RINOK(AddError(phyPath)) continue; } // (SymLinks == true) here if (item.ReparseData.Size() == 0) continue; // if (item.Size == 0) { // 20.03: we use Reparse Data instead of real data item.Size = item.ReparseData.Size(); } CReparseAttr attr; if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) { const FString phyPath = GetPhyPath(i); AddError(phyPath, attr.ErrorCode); continue; } /* imagex/WIM reduces absolute paths in links (raparse data), if we archive non root folder. We do same thing here */ bool isWSL = false; if (attr.IsSymLink_WSL()) { // isWSL = true; // we don't change WSL symlinks continue; } else { if (attr.IsRelative_Win()) continue; } const UString &link = attr.GetPath(); if (!IsDrivePath(link)) continue; // maybe we need to support networks paths also ? FString fullPathF; if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF)) continue; const UString fullPath = fs2us(fullPathF); const UString logPath = GetLogPath(i); if (logPath.Len() >= fullPath.Len()) continue; if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0) continue; const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len()); if (!IsPathSepar(prefix.Back())) continue; const unsigned rootPrefixSize = GetRootPrefixSize(prefix); if (rootPrefixSize == 0) continue; if (rootPrefixSize == prefix.Len()) continue; // simple case: paths are from root if (link.Len() <= prefix.Len()) continue; if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) continue; UString newLink = prefix.Left(rootPrefixSize); newLink += link.Ptr(prefix.Len()); CByteBuffer data; bool isSymLink = !attr.IsMountPoint(); if (!FillLinkData(data, newLink, isSymLink, isWSL)) continue; item.ReparseData2 = data; } return S_OK; } #endif #ifndef _WIN32 HRESULT CDirItems::FillDeviceSizes() { { FOR_VECTOR (i, Items) { CDirItem &item = Items[i]; if (S_ISBLK(item.mode) && item.Size == 0) { const FString phyPath = GetPhyPath(i); NIO::CInFile inFile; inFile.PreserveATime = true; if (inFile.OpenShared(phyPath, ShareForWrite)) // fixme: OpenShared ?? { UInt64 size = 0; if (inFile.GetLength(size)) item.Size = size; } } if (StoreOwnerName) { OwnerNameMap.Add_UInt32(item.uid); OwnerGroupMap.Add_UInt32(item.gid); } } } if (StoreOwnerName) { UString u; AString a; { FOR_VECTOR (i, OwnerNameMap.Numbers) { // 200K/sec speed u.Empty(); const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]); // printf("\ngetpwuid=%s\n", pw->pw_name); if (pw) { a = pw->pw_name; ConvertUTF8ToUnicode(a, u); } OwnerNameMap.Strings.Add(u); } } { FOR_VECTOR (i, OwnerGroupMap.Numbers) { u.Empty(); const group *gr = getgrgid(OwnerGroupMap.Numbers[i]); if (gr) { // printf("\ngetgrgid %d %s\n", OwnerGroupMap.Numbers[i], gr->gr_name); a = gr->gr_name; ConvertUTF8ToUnicode(a, u); } OwnerGroupMap.Strings.Add(u); } } FOR_VECTOR (i, Items) { CDirItem &item = Items[i]; { const int index = OwnerNameMap.Find(item.uid); if (index < 0) throw 1; item.OwnerNameIndex = index; } { const int index = OwnerGroupMap.Find(item.gid); if (index < 0) throw 1; item.OwnerGroupIndex = index; } } } // if (NeedOwnerNames) { /* { for (unsigned i = 0 ; i < 10000; i++) { const passwd *pw = getpwuid(i); if (pw) { UString u; ConvertUTF8ToUnicode(AString(pw->pw_name), u); OwnerNameMap.Add(i, u); OwnerNameMap.Add(i, u); OwnerNameMap.Add(i, u); } const group *gr = getgrgid(i); if (gr) { // we can use utf-8 here. UString u; ConvertUTF8ToUnicode(AString(gr->gr_name), u); OwnerGroupMap.Add(i, u); } } } */ /* { FOR_VECTOR (i, OwnerNameMap.Strings) { AString s; ConvertUnicodeToUTF8(OwnerNameMap.Strings[i], s); printf("\n%5d %s", (unsigned)OwnerNameMap.Numbers[i], s.Ptr()); } } { printf("\n\n=========Groups\n"); FOR_VECTOR (i, OwnerGroupMap.Strings) { AString s; ConvertUnicodeToUTF8(OwnerGroupMap.Strings[i], s); printf("\n%5d %s", (unsigned)OwnerGroupMap.Numbers[i], s.Ptr()); } } */ } /* for (unsigned i = 0 ; i < 100000000; i++) { // const passwd *pw = getpwuid(1000); // pw = pw; int pos = OwnerNameMap.Find(1000); if (pos < 0 - (int)i) throw 1; } */ return S_OK; } #endif static const char * const kCannotFindArchive = "Cannot find archive"; HRESULT EnumerateDirItemsAndSort( NWildcard::CCensor &censor, NWildcard::ECensorPathMode censorPathMode, const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths, CDirItemsStat &st, IDirItemsCallback *callback) { FStringVector paths; { CDirItems dirItems; dirItems.Callback = callback; { HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems); st = dirItems.Stat; RINOK(res) } FOR_VECTOR (i, dirItems.Items) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) paths.Add(dirItems.GetPhyPath(i)); } } if (paths.Size() == 0) { // return S_OK; throw CMessagePathException(kCannotFindArchive); } UStringVector fullPaths; unsigned i; for (i = 0; i < paths.Size(); i++) { FString fullPath; NFile::NDir::MyGetFullPathName(paths[i], fullPath); fullPaths.Add(fs2us(fullPath)); } CUIntVector indices; SortFileNames(fullPaths, indices); sortedPaths.ClearAndReserve(indices.Size()); sortedFullPaths.ClearAndReserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { unsigned index = indices[i]; sortedPaths.AddInReserved(fs2us(paths[index])); sortedFullPaths.AddInReserved(fullPaths[index]); if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) throw CMessagePathException("Duplicate archive path:", sortedFullPaths[i]); } return S_OK; } #ifdef _WIN32 static bool IsDotsName(const wchar_t *s) { return s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)); } // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildcard(name) || IsDotsName(name)) return; NFind::CFileInfo fi; const FString path (us2fs(prefix + name)); #ifndef UNDER_CE if (NFile::NName::IsDevicePath(path)) return; #endif if (fi.Find(path)) name = fs2us(fi.Name); } static void ConvertToLongNames(const UString &prefix, CObjectVector &items) { FOR_VECTOR (i, items) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; if (prefix.IsEmpty() && item.IsDriveItem()) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); unsigned i; for (i = 0; i < node.SubNodes.Size(); i++) { UString &name = node.SubNodes[i].Name; if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name)) continue; ConvertToLongName(prefix, name); } // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (unsigned j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name)) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode); } } void ConvertToLongNames(NWildcard::CCensor &censor) { FOR_VECTOR (i, censor.Pairs) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif CMessagePathException::CMessagePathException(const char *a, const wchar_t *u) { (*this) += a; if (u) { Add_LF(); (*this) += u; } } CMessagePathException::CMessagePathException(const wchar_t *a, const wchar_t *u) { (*this) += a; if (u) { Add_LF(); (*this) += u; } } tmp41wklro_/CPP/7zip/UI/Common/EnumDirItems.h0000444000175000001440000000156714357314620021755 0ustar nabijaczleweliusers// EnumDirItems.h #ifndef ZIP7_INC_ENUM_DIR_ITEMS_H #define ZIP7_INC_ENUM_DIR_ITEMS_H #include "../../../Common/Wildcard.h" #include "DirItem.h" HRESULT EnumerateItems( const NWildcard::CCensor &censor, NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, CDirItems &dirItems); struct CMessagePathException: public UString { CMessagePathException(const char *a, const wchar_t *u = NULL); CMessagePathException(const wchar_t *a, const wchar_t *u = NULL); }; HRESULT EnumerateDirItemsAndSort( NWildcard::CCensor &censor, NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, UStringVector &sortedPaths, UStringVector &sortedFullPaths, CDirItemsStat &st, IDirItemsCallback *callback); #ifdef _WIN32 void ConvertToLongNames(NWildcard::CCensor &censor); #endif #endif tmp41wklro_/CPP/7zip/UI/Common/ExitCode.h0000444000175000001440000000141714357314620021106 0ustar nabijaczleweliusers// ExitCode.h #ifndef ZIP7_INC_EXIT_CODE_H #define ZIP7_INC_EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif tmp41wklro_/CPP/7zip/UI/Common/Extract.cpp0000444000175000001440000003622114561635420021351 0ustar nabijaczleweliusers// Extract.cpp #include "StdAfx.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" #include "../Common/ExtractingFilePath.h" #include "../Common/HashCalc.h" #include "Extract.h" #include "SetProperties.h" using namespace NWindows; using namespace NFile; using namespace NDir; static void SetErrorMessage(const char *message, const FString &path, HRESULT errorCode, UString &s) { s = message; s += " : "; s += NError::MyFormatMessage(errorCode); s += " : "; s += fs2us(path); } static HRESULT DecompressArchive( CCodecs *codecs, const CArchiveLink &arcLink, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, bool calcCrc, IExtractCallbackUI *callback, IFolderArchiveExtractCallback *callbackFAE, CArchiveExtractCallback *ecs, UString &errorMessage, UInt64 &stdInProcessed) { const CArc &arc = arcLink.Arcs.Back(); stdInProcessed = 0; IInArchive *archive = arc.Archive; CRecordVector realIndices; UStringVector removePathParts; FString outDir = options.OutputDir; UString replaceName = arc.DefaultName; if (arcLink.Arcs.Size() > 1) { // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1". // So it extracts different archives to one folder. // We will use top level archive name const CArc &arc0 = arcLink.Arcs[0]; if (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, "pe")) replaceName = arc0.DefaultName; } outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName))); bool elimIsPossible = false; UString elimPrefix; // only pure name without dir delimiter FString outDirReduced = outDir; if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths) { UString dirPrefix; SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix); if (!elimPrefix.IsEmpty()) { if (IsPathSepar(elimPrefix.Back())) elimPrefix.DeleteBack(); if (!elimPrefix.IsEmpty()) { outDirReduced = us2fs(dirPrefix); elimIsPossible = true; } } } const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); if (!options.StdInMode) { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) CReadArcItem item; for (UInt32 i = 0; i < numItems; i++) { if (elimIsPossible || !allFilesAreAllowed || options.ExcludeDirItems || options.ExcludeFileItems) { RINOK(arc.GetItem(i, item)) if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems) continue; } else { #ifdef SUPPORT_ALT_STREAMS item.IsAltStream = false; if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream) { RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream)) } #endif } #ifdef SUPPORT_ALT_STREAMS if (!options.NtOptions.AltStreams.Val && item.IsAltStream) continue; #endif if (elimIsPossible) { const UString &s = #ifdef SUPPORT_ALT_STREAMS item.MainPath; #else item.Path; #endif if (!IsPath1PrefixedByPath2(s, elimPrefix)) elimIsPossible = false; else { wchar_t c = s[elimPrefix.Len()]; if (c == 0) { if (!item.MainIsDir) elimIsPossible = false; } else if (!IsPathSepar(c)) elimIsPossible = false; } } if (!allFilesAreAllowed) { if (!CensorNode_CheckPath(wildcardCensor, item)) continue; } realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return callback->ExtractResult(S_OK); } } if (elimIsPossible) { removePathParts.Add(elimPrefix); // outDir = outDirReduced; } #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". // outDir.TrimRight(); // outDir = GetCorrectFullFsPath(outDir); #endif if (outDir.IsEmpty()) outDir = "." STRING_PATH_SEPARATOR; /* #ifdef _WIN32 else if (NName::IsAltPathPrefix(outDir)) {} #endif */ else if (!CreateComplexDir(outDir)) { const HRESULT res = GetLastError_noZero_HRESULT(); SetErrorMessage("Cannot create output directory", outDir, res, errorMessage); return res; } ecs->Init( options.NtOptions, options.StdInMode ? &wildcardCensor : NULL, &arc, callbackFAE, options.StdOutMode, options.TestMode, outDir, removePathParts, false, packSize); ecs->Is_elimPrefix_Mode = elimIsPossible; #ifdef SUPPORT_LINKS if (!options.StdInMode && !options.TestMode && options.NtOptions.HardLinks.Val) { RINOK(ecs->PrepareHardLinks(&realIndices)) } #endif HRESULT result; const Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0; CArchiveExtractCallback_Closer ecsCloser(ecs); if (options.StdInMode) { result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs); NCOM::CPropVariant prop; if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) ConvertPropVariantToUInt64(prop, stdInProcessed); } else { // v23.02: we reset completed value that could be set by Open() operation IArchiveExtractCallback *aec = ecs; const UInt64 val = 0; RINOK(aec->SetCompleted(&val)) result = archive->Extract(realIndices.ConstData(), realIndices.Size(), testMode, aec); } const HRESULT res2 = ecsCloser.Close(); if (result == S_OK) result = res2; return callback->ExtractResult(result); } /* v9.31: BUG was fixed: Sorted list for file paths was sorted with case insensitive compare function. But FindInSorted function did binary search via case sensitive compare function */ int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name); int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name) { unsigned left = 0, right = fileNames.Size(); while (left != right) { const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const UString &midVal = fileNames[mid]; const int comp = CompareFileNames(name, midVal); if (comp == 0) return (int)mid; if (comp < 0) right = mid; else left = mid + 1; } return -1; } HRESULT Extract( // DECL_EXTERNAL_CODECS_LOC_VARS CCodecs *codecs, const CObjectVector &types, const CIntVector &excludedFormats, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, IFolderArchiveExtractCallback *faeCallback, #ifndef Z7_SFX IHashCalc *hash, #endif UString &errorMessage, CDecompressStat &st) { st.Clear(); UInt64 totalPackSize = 0; CRecordVector arcSizes; unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size(); unsigned i; for (i = 0; i < numArcs; i++) { NFind::CFileInfo fi; fi.Size = 0; if (!options.StdInMode) { const FString arcPath = us2fs(arcPaths[i]); if (!fi.Find_FollowLink(arcPath)) { const HRESULT errorCode = GetLastError_noZero_HRESULT(); SetErrorMessage("Cannot find archive file", arcPath, errorCode, errorMessage); return errorCode; } if (fi.IsDir()) { HRESULT errorCode = E_FAIL; SetErrorMessage("The item is a directory", arcPath, errorCode, errorMessage); return errorCode; } } arcSizes.Add(fi.Size); totalPackSize += fi.Size; } CBoolArr skipArcs(numArcs); for (i = 0; i < numArcs; i++) skipArcs[i] = false; CArchiveExtractCallback *ecs = new CArchiveExtractCallback; CMyComPtr ec(ecs); const bool multi = (numArcs > 1); ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode, options.ZoneMode, false // keepEmptyDirParts ); #ifndef Z7_SFX ecs->SetHashMethods(hash); #endif if (multi) { RINOK(faeCallback->SetTotal(totalPackSize)) } UInt64 totalPackProcessed = 0; bool thereAreNotOpenArcs = false; for (i = 0; i < numArcs; i++) { if (skipArcs[i]) continue; ecs->InitBeforeNewArchive(); const UString &arcPath = arcPaths[i]; NFind::CFileInfo fi; if (options.StdInMode) { // do we need ctime and mtime? // fi.ClearBase(); // fi.Size = 0; // (UInt64)(Int64)-1; if (!fi.SetAs_StdInFile()) return GetLastError_noZero_HRESULT(); } else { if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir()) { const HRESULT errorCode = GetLastError_noZero_HRESULT(); SetErrorMessage("Cannot find archive file", us2fs(arcPath), errorCode, errorMessage); return errorCode; } } /* #ifndef Z7_NO_CRYPTO openCallback->Open_Clear_PasswordWasAsked_Flag(); #endif */ RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode)) CArchiveLink arcLink; CObjectVector types2 = types; /* #ifndef Z7_SFX if (types.IsEmpty()) { int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { UString s = arcPath.Ptr(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = arcPath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1)); if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0 { types2.Add(index2); types2.Add(index); } } } } } #endif */ COpenOptions op; #ifndef Z7_SFX op.props = &options.Properties; #endif op.codecs = codecs; op.types = &types2; op.excludedFormats = &excludedFormats; op.stdInMode = options.StdInMode; op.stream = NULL; op.filePath = arcPath; HRESULT result = arcLink.Open_Strict(op, openCallback); if (result == E_ABORT) return result; // arcLink.Set_ErrorsText(); RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result)) if (result != S_OK) { thereAreNotOpenArcs = true; if (!options.StdInMode) totalPackProcessed += fi.Size; continue; } #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) if (options.ZoneMode != NExtract::NZoneIdMode::kNone && !options.StdInMode) { ReadZoneFile_Of_BaseFile(us2fs(arcPath), ecs->ZoneBuf); } #endif if (arcLink.Arcs.Size() != 0) { if (arcLink.GetArc()->IsHashHandler(op)) { if (!options.TestMode) { /* real Extracting to files is possible. But user can think that hash archive contains real files. So we block extracting here. */ // v23.00 : we don't break process. RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, E_NOTIMPL)) thereAreNotOpenArcs = true; if (!options.StdInMode) totalPackProcessed += fi.Size; continue; // return E_NOTIMPL; // before v23 } FString dirPrefix = us2fs(options.HashDir); if (dirPrefix.IsEmpty()) { if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix)) { // return GetLastError_noZero_HRESULT(); } } if (!dirPrefix.IsEmpty()) NName::NormalizeDirPathPrefix(dirPrefix); ecs->DirPathPrefix_for_HashFiles = dirPrefix; } } if (!options.StdInMode) { // numVolumes += arcLink.VolumePaths.Size(); // arcLink.VolumesSize; // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes); // numArcs = arcPaths.Size(); if (arcLink.VolumePaths.Size() != 0) { Int64 correctionSize = (Int64)arcLink.VolumesSize; FOR_VECTOR (v, arcLink.VolumePaths) { int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); if (index >= 0) { if ((unsigned)index > i) { skipArcs[(unsigned)index] = true; correctionSize -= arcSizes[(unsigned)index]; } } } if (correctionSize != 0) { Int64 newPackSize = (Int64)totalPackSize + correctionSize; if (newPackSize < 0) newPackSize = 0; totalPackSize = (UInt64)newPackSize; RINOK(faeCallback->SetTotal(totalPackSize)) } } } /* // Now openCallback and extractCallback use same object. So we don't need to send password. #ifndef Z7_NO_CRYPTO bool passwordIsDefined; UString password; RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password)) if (passwordIsDefined) { RINOK(extractCallback->SetPassword(password)) } #endif */ CArc &arc = arcLink.Arcs.Back(); arc.MTime.Def = !options.StdInMode #ifdef _WIN32 && !fi.IsDevice #endif ; if (arc.MTime.Def) arc.MTime.Set_From_FiTime(fi.MTime); UInt64 packProcessed; const bool calcCrc = #ifndef Z7_SFX (hash != NULL); #else false; #endif RINOK(DecompressArchive( codecs, arcLink, fi.Size + arcLink.VolumesSize, wildcardCensor, options, calcCrc, extractCallback, faeCallback, ecs, errorMessage, packProcessed)) if (!options.StdInMode) packProcessed = fi.Size + arcLink.VolumesSize; totalPackProcessed += packProcessed; ecs->LocalProgressSpec->InSize += packProcessed; ecs->LocalProgressSpec->OutSize = ecs->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } if (multi || thereAreNotOpenArcs) { RINOK(faeCallback->SetTotal(totalPackSize)) RINOK(faeCallback->SetCompleted(&totalPackProcessed)) } st.NumFolders = ecs->NumFolders; st.NumFiles = ecs->NumFiles; st.NumAltStreams = ecs->NumAltStreams; st.UnpackSize = ecs->UnpackSize; st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; st.NumArchives = arcPaths.Size(); st.PackSize = ecs->LocalProgressSpec->InSize; return S_OK; } tmp41wklro_/CPP/7zip/UI/Common/Extract.h0000444000175000001440000000453414572400240021010 0ustar nabijaczleweliusers// Extract.h #ifndef ZIP7_INC_EXTRACT_H #define ZIP7_INC_EXTRACT_H #include "../../../Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" struct CExtractOptionsBase { CBoolPair ElimDup; bool ExcludeDirItems; bool ExcludeFileItems; bool PathMode_Force; bool OverwriteMode_Force; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; NExtract::NZoneIdMode::EEnum ZoneMode; CExtractNtOptions NtOptions; FString OutputDir; UString HashDir; CExtractOptionsBase(): ExcludeDirItems(false), ExcludeFileItems(false), PathMode_Force(false), OverwriteMode_Force(false), PathMode(NExtract::NPathMode::kFullPaths), OverwriteMode(NExtract::NOverwriteMode::kAsk), ZoneMode(NExtract::NZoneIdMode::kNone) {} }; struct CExtractOptions: public CExtractOptionsBase { bool StdInMode; bool StdOutMode; bool YesToAll; bool TestMode; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifndef Z7_SFX CObjectVector Properties; #endif /* #ifdef Z7_EXTERNAL_CODECS CCodecs *Codecs; #endif */ CExtractOptions(): StdInMode(false), StdOutMode(false), YesToAll(false), TestMode(false) {} }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 AltStreams_UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; UInt64 NumAltStreams; void Clear() { NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0; } }; HRESULT Extract( // DECL_EXTERNAL_CODECS_LOC_VARS CCodecs *codecs, const CObjectVector &types, const CIntVector &excludedFormats, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, IFolderArchiveExtractCallback *faeCallback, #ifndef Z7_SFX IHashCalc *hash, #endif UString &errorMessage, CDecompressStat &st); #endif tmp41wklro_/CPP/7zip/UI/Common/ExtractingFilePath.cpp0000444000175000001440000001414014401407000023440 0ustar nabijaczleweliusers// ExtractingFilePath.cpp #include "StdAfx.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileName.h" #include "ExtractingFilePath.h" extern bool g_PathTrailReplaceMode; bool g_PathTrailReplaceMode = #ifdef _WIN32 true #else false #endif ; #ifdef _WIN32 static void ReplaceIncorrectChars(UString &s) { { for (unsigned i = 0; i < s.Len(); i++) { wchar_t c = s[i]; if ( #ifdef _WIN32 c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"' || c == '/' // || c == 0x202E // RLO || #endif c == WCHAR_PATH_SEPARATOR) { #if WCHAR_PATH_SEPARATOR != L'/' // 22.00 : WSL replacement for backslash if (c == WCHAR_PATH_SEPARATOR) c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; else #endif c = '_'; s.ReplaceOneCharAtPos(i, c // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters ); } } } if (g_PathTrailReplaceMode) { /* // if (g_PathTrailReplaceMode == 1) { if (!s.IsEmpty()) { wchar_t c = s.Back(); if (c == '.' || c == ' ') { // s += (wchar_t)(0x9c); // STRING TERMINATOR s += (wchar_t)'_'; } } } else */ { unsigned i; for (i = s.Len(); i != 0;) { wchar_t c = s[i - 1]; if (c != '.' && c != ' ') break; i--; s.ReplaceOneCharAtPos(i, '_'); // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7)); } /* if (g_PathTrailReplaceMode > 1 && i != s.Len()) { s.DeleteFrom(i); } */ } } } #endif /* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream. But colon in postfix ":$DATA" is allowed. WIN32 functions don't allow empty alt stream name "name:" */ void Correct_AltStream_Name(UString &s) { unsigned len = s.Len(); const unsigned kPostfixSize = 6; if (s.Len() >= kPostfixSize && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) len -= kPostfixSize; for (unsigned i = 0; i < len; i++) { wchar_t c = s[i]; if (c == ':' || c == '\\' || c == '/' || c == 0x202E // RLO ) s.ReplaceOneCharAtPos(i, '_'); } if (s.IsEmpty()) s = '_'; } #ifdef _WIN32 static const unsigned g_ReservedWithNum_Index = 4; static const char * const g_ReservedNames[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; static bool IsSupportedName(const UString &name) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ReservedNames); i++) { const char *reservedName = g_ReservedNames[i]; unsigned len = MyStringLen(reservedName); if (name.Len() < len) continue; if (!name.IsPrefixedBy_Ascii_NoCase(reservedName)) continue; if (i >= g_ReservedWithNum_Index) { wchar_t c = name[len]; if (c < L'0' || c > L'9') continue; len++; } for (;;) { wchar_t c = name[len++]; if (c == 0 || c == '.') return false; if (c != ' ') break; } } return true; } static void CorrectUnsupportedName(UString &name) { if (!IsSupportedName(name)) name.InsertAtFront(L'_'); } #endif static void Correct_PathPart(UString &s) { // "." and ".." if (s.IsEmpty()) return; if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) s.Empty(); #ifdef _WIN32 else ReplaceIncorrectChars(s); #endif } // static const char * const k_EmptyReplaceName = "[]"; static const char k_EmptyReplaceName = '_'; UString Get_Correct_FsFile_Name(const UString &name) { UString res = name; Correct_PathPart(res); #ifdef _WIN32 CorrectUnsupportedName(res); #endif if (res.IsEmpty()) res = k_EmptyReplaceName; return res; } void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir) { unsigned i = 0; if (absIsAllowed) { #if defined(_WIN32) && !defined(UNDER_CE) bool isDrive = false; #endif if (parts[0].IsEmpty()) { i = 1; #if defined(_WIN32) && !defined(UNDER_CE) if (parts.Size() > 1 && parts[1].IsEmpty()) { i = 2; if (parts.Size() > 2 && parts[2] == L"?") { i = 3; if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) { isDrive = true; i = 4; } } } #endif } #if defined(_WIN32) && !defined(UNDER_CE) else if (NWindows::NFile::NName::IsDrivePath2(parts[0])) { isDrive = true; i = 1; } if (isDrive) { // we convert "c:name" to "c:\name", if absIsAllowed path. UString &ds = parts[i - 1]; if (ds.Len() > 2) { parts.Insert(i, ds.Ptr(2)); ds.DeleteFrom(2); } } #endif } if (i != 0) keepAndReplaceEmptyPrefixes = false; for (; i < parts.Size();) { UString &s = parts[i]; Correct_PathPart(s); if (s.IsEmpty()) { if (!keepAndReplaceEmptyPrefixes) if (isDir || i != parts.Size() - 1) { parts.Delete(i); continue; } s = k_EmptyReplaceName; } else { keepAndReplaceEmptyPrefixes = false; #ifdef _WIN32 CorrectUnsupportedName(s); #endif } i++; } if (!isDir) { if (parts.IsEmpty()) parts.Add((UString)k_EmptyReplaceName); else { UString &s = parts.Back(); if (s.IsEmpty()) s = k_EmptyReplaceName; } } } UString MakePathFromParts(const UStringVector &parts) { UString s; FOR_VECTOR (i, parts) { if (i != 0) s.Add_PathSepar(); s += parts[i]; } return s; } tmp41wklro_/CPP/7zip/UI/Common/ExtractingFilePath.h0000444000175000001440000000207414357314620023127 0ustar nabijaczleweliusers// ExtractingFilePath.h #ifndef ZIP7_INC_EXTRACTING_FILE_PATH_H #define ZIP7_INC_EXTRACTING_FILE_PATH_H #include "../../../Common/MyString.h" // #ifdef _WIN32 void Correct_AltStream_Name(UString &s); // #endif // replaces unsuported characters, and replaces "." , ".." and "" to "[]" UString Get_Correct_FsFile_Name(const UString &name); /* Correct_FsPath() corrects path parts to prepare it for File System operations. It also corrects empty path parts like "\\\\": - frontal empty path parts : it removes them or changes them to "_" - another empty path parts : it removes them if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker else { if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_" } */ void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir); UString MakePathFromParts(const UStringVector &parts); #endif tmp41wklro_/CPP/7zip/UI/Common/ExtractMode.h0000444000175000001440000000104314357314620021614 0ustar nabijaczleweliusers// ExtractMode.h #ifndef ZIP7_INC_EXTRACT_MODE_H #define ZIP7_INC_EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPaths, kCurPaths, kNoPaths, kAbsPaths, kNoPathsAlt // alt streams must be extracted without name of base file }; } namespace NOverwriteMode { enum EEnum { kAsk, kOverwrite, kSkip, kRename, kRenameExisting }; } namespace NZoneIdMode { enum EEnum { kNone, kAll, kOffice }; } } #endif tmp41wklro_/CPP/7zip/UI/Common/HashCalc.cpp0000444000175000001440000014027614567042400021407 0ustar nabijaczleweliusers// HashCalc.cpp #include "StdAfx.h" #include "../../../../C/Alloc.h" #include "../../../../C/CpuArch.h" #include "../../../Common/DynLimBuf.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "../../Archive/Common/ItemNameUtils.h" #include "../../Archive/IArchive.h" #include "EnumDirItems.h" #include "HashCalc.h" using namespace NWindows; #ifdef Z7_EXTERNAL_CODECS extern const CExternalCodecs *g_ExternalCodecs_Ptr; #endif class CHashMidBuf { void *_data; public: CHashMidBuf(): _data(NULL) {} operator void *() { return _data; } bool Alloc(size_t size) { if (_data) return false; _data = ::MidAlloc(size); return _data != NULL; } ~CHashMidBuf() { ::MidFree(_data); } }; static const char * const k_DefaultHashMethod = "CRC32"; HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) { UStringVector names = hashMethods; if (names.IsEmpty()) names.Add(UString(k_DefaultHashMethod)); CRecordVector ids; CObjectVector methods; unsigned i; for (i = 0; i < names.Size(); i++) { COneMethodInfo m; RINOK(m.ParseMethodFromString(names[i])) if (m.MethodName.IsEmpty()) m.MethodName = k_DefaultHashMethod; if (m.MethodName == "*") { CRecordVector tempMethods; GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); methods.Clear(); ids.Clear(); FOR_VECTOR (t, tempMethods) { unsigned index = ids.AddToUniqueSorted(tempMethods[t]); if (ids.Size() != methods.Size()) methods.Insert(index, m); } break; } else { // m.MethodName.RemoveChar(L'-'); CMethodId id; if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) return E_NOTIMPL; unsigned index = ids.AddToUniqueSorted(id); if (ids.Size() != methods.Size()) methods.Insert(index, m); } } for (i = 0; i < ids.Size(); i++) { CMyComPtr hasher; AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)) if (!hasher) throw "Can't create hasher"; const COneMethodInfo &m = methods[i]; { CMyComPtr scp; hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) RINOK(m.SetCoderProps(scp, NULL)) } const UInt32 digestSize = hasher->GetDigestSize(); if (digestSize > k_HashCalc_DigestSize_Max) return E_NOTIMPL; CHasherState &h = Hashers.AddNew(); h.DigestSize = digestSize; h.Hasher = hasher; h.Name = name; for (unsigned k = 0; k < k_HashCalc_NumGroups; k++) h.InitDigestGroup(k); } return S_OK; } void CHashBundle::InitForNewFile() { CurSize = 0; FOR_VECTOR (i, Hashers) { CHasherState &h = Hashers[i]; h.Hasher->Init(); h.InitDigestGroup(k_HashCalc_Index_Current); } } void CHashBundle::Update(const void *data, UInt32 size) { CurSize += size; FOR_VECTOR (i, Hashers) Hashers[i].Hasher->Update(data, size); } void CHashBundle::SetSize(UInt64 size) { CurSize = size; } static void AddDigests(Byte *dest, const Byte *src, UInt32 size) { unsigned next = 0; /* // we could use big-endian addition for sha-1 and sha-256 // but another hashers are little-endian if (size > 8) { for (unsigned i = size; i != 0;) { i--; next += (unsigned)dest[i] + (unsigned)src[i]; dest[i] = (Byte)next; next >>= 8; } } else */ { for (unsigned i = 0; i < size; i++) { next += (unsigned)dest[i] + (unsigned)src[i]; dest[i] = (Byte)next; next >>= 8; } } // we use little-endian to store extra bytes dest += k_HashCalc_DigestSize_Max; for (unsigned i = 0; i < k_HashCalc_ExtraSize; i++) { next += (unsigned)dest[i]; dest[i] = (Byte)next; next >>= 8; } } void CHasherState::AddDigest(unsigned groupIndex, const Byte *data) { NumSums[groupIndex]++; AddDigests(Digests[groupIndex], data, DigestSize); } void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) { if (isDir) NumDirs++; else if (isAltStream) { NumAltStreams++; AltStreamsSize += CurSize; } else { NumFiles++; FilesSize += CurSize; } Byte pre[16]; memset(pre, 0, sizeof(pre)); if (isDir) pre[0] = 1; FOR_VECTOR (i, Hashers) { CHasherState &h = Hashers[i]; if (!isDir) { h.Hasher->Final(h.Digests[0]); // k_HashCalc_Index_Current if (!isAltStream) h.AddDigest(k_HashCalc_Index_DataSum, h.Digests[0]); } h.Hasher->Init(); h.Hasher->Update(pre, sizeof(pre)); h.Hasher->Update(h.Digests[0], h.DigestSize); for (unsigned k = 0; k < path.Len(); k++) { wchar_t c = path[k]; // 21.04: we want same hash for linux and windows paths #if CHAR_PATH_SEPARATOR != '/' if (c == CHAR_PATH_SEPARATOR) c = '/'; // if (c == (wchar_t)('\\' + 0xf000)) c = '\\'; // to debug WSL // if (c > 0xf000 && c < 0xf080) c -= 0xf000; // to debug WSL #endif Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; h.Hasher->Update(temp, 2); } Byte tempDigest[k_HashCalc_DigestSize_Max]; h.Hasher->Final(tempDigest); if (!isAltStream) h.AddDigest(k_HashCalc_Index_NamesSum, tempDigest); h.AddDigest(k_HashCalc_Index_StreamsSum, tempDigest); } } static void CSum_Name_OriginalToEscape(const AString &src, AString &dest) { dest.Empty(); for (unsigned i = 0; i < src.Len();) { char c = src[i++]; if (c == '\n') { dest.Add_Char('\\'); c = 'n'; } else if (c == '\\') dest.Add_Char('\\'); dest.Add_Char(c); } } static bool CSum_Name_EscapeToOriginal(const char *s, AString &dest) { bool isOK = true; dest.Empty(); for (;;) { char c = *s++; if (c == 0) break; if (c == '\\') { const char c1 = *s; if (c1 == 'n') { c = '\n'; s++; } else if (c1 == '\\') { c = c1; s++; } else { // original md5sum returns NULL for such bad strings isOK = false; } } dest.Add_Char(c); } return isOK; } static void SetSpacesAndNul(char *s, unsigned num) { for (unsigned i = 0; i < num; i++) s[i] = ' '; s[num] = 0; } static const unsigned kHashColumnWidth_Min = 4 * 2; static unsigned GetColumnWidth(unsigned digestSize) { const unsigned width = digestSize * 2; return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width; } static void AddHashResultLine( AString &_s, // bool showHash, // UInt64 fileSize, bool showSize, const CObjectVector &hashers // unsigned digestIndex, = k_HashCalc_Index_Current ) { FOR_VECTOR (i, hashers) { const CHasherState &h = hashers[i]; char s[k_HashCalc_DigestSize_Max * 2 + 64]; s[0] = 0; // if (showHash) HashHexToString(s, h.Digests[k_HashCalc_Index_Current], h.DigestSize); const unsigned pos = (unsigned)strlen(s); const int numSpaces = (int)GetColumnWidth(h.DigestSize) - (int)pos; if (numSpaces > 0) SetSpacesAndNul(s + pos, (unsigned)numSpaces); if (i != 0) _s.Add_Space(); _s += s; } /* if (showSize) { _s.Add_Space(); static const unsigned kSizeField_Len = 13; // same as in HashCon.cpp char s[kSizeField_Len + 32]; char *p = s; SetSpacesAndNul(s, kSizeField_Len); p = s + kSizeField_Len; ConvertUInt64ToString(fileSize, p); int numSpaces = (int)kSizeField_Len - (int)strlen(p); if (numSpaces > 0) p -= (unsigned)numSpaces; _s += p; } */ } static void Add_LF(CDynLimBuf &hashFileString, const CHashOptionsLocal &options) { hashFileString += (char)(options.HashMode_Zero.Val ? 0 : '\n'); } static void WriteLine(CDynLimBuf &hashFileString, const CHashOptionsLocal &options, const UString &path2, bool isDir, const AString &methodName, const AString &hashesString) { if (options.HashMode_OnlyHash.Val) { hashFileString += hashesString; Add_LF(hashFileString, options); return; } UString path = path2; bool isBin = false; const bool zeroMode = options.HashMode_Zero.Val; const bool tagMode = options.HashMode_Tag.Val; #if CHAR_PATH_SEPARATOR != '/' path.Replace(WCHAR_PATH_SEPARATOR, L'/'); // path.Replace((wchar_t)('\\' + 0xf000), L'\\'); // to debug WSL #endif AString utf8; ConvertUnicodeToUTF8(path, utf8); AString esc; CSum_Name_OriginalToEscape(utf8, esc); if (!zeroMode) { if (esc != utf8) { /* Original md5sum writes escape in that case. We do same for compatibility with original md5sum. */ hashFileString += '\\'; } } if (isDir && !esc.IsEmpty() && esc.Back() != '/') esc.Add_Slash(); if (tagMode) { if (!methodName.IsEmpty()) { hashFileString += methodName; hashFileString += ' '; } hashFileString += '('; hashFileString += esc; hashFileString += ')'; hashFileString += " = "; } hashFileString += hashesString; if (!tagMode) { hashFileString += ' '; hashFileString += (char)(isBin ? '*' : ' '); hashFileString += esc; } Add_LF(hashFileString, options); } static void WriteLine(CDynLimBuf &hashFileString, const CHashOptionsLocal &options, const UString &path, bool isDir, const CHashBundle &hb) { AString methodName; if (!hb.Hashers.IsEmpty()) methodName = hb.Hashers[0].Name; AString hashesString; AddHashResultLine(hashesString, hb.Hashers); WriteLine(hashFileString, options, path, isDir, methodName, hashesString); } HRESULT HashCalc( DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor &censor, const CHashOptions &options, AString &errorInfo, IHashCallbackUI *callback) { CDirItems dirItems; dirItems.Callback = callback; if (options.StdInMode) { CDirItem di; if (!di.SetAs_StdInFile()) return GetLastError_noZero_HRESULT(); dirItems.Items.Add(di); } else { RINOK(callback->StartScanning()) dirItems.SymLinks = options.SymLinks.Val; dirItems.ScanAltStreams = options.AltStreamsMode; dirItems.ExcludeDirItems = censor.ExcludeDirItems; dirItems.ExcludeFileItems = censor.ExcludeFileItems; dirItems.ShareForWrite = options.OpenShareForWrite; HRESULT res = EnumerateItems(censor, options.PathMode, UString(), dirItems); if (res != S_OK) { if (res != E_ABORT) errorInfo = "Scanning error"; return res; } RINOK(callback->FinishScanning(dirItems.Stat)) } unsigned i; CHashBundle hb; RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)) // hb.Init(); hb.NumErrors = dirItems.Stat.NumErrors; UInt64 totalSize = 0; if (options.StdInMode) { RINOK(callback->SetNumFiles(1)) } else { totalSize = dirItems.Stat.GetTotalBytes(); RINOK(callback->SetTotal(totalSize)) } const UInt32 kBufSize = 1 << 15; CHashMidBuf buf; if (!buf.Alloc(kBufSize)) return E_OUTOFMEMORY; UInt64 completeValue = 0; RINOK(callback->BeforeFirstFile(hb)) /* CDynLimBuf hashFileString((size_t)1 << 31); const bool needGenerate = !options.HashFilePath.IsEmpty(); */ for (i = 0; i < dirItems.Items.Size(); i++) { CMyComPtr inStream; UString path; bool isDir = false; bool isAltStream = false; if (options.StdInMode) { #if 1 inStream = new CStdInFileStream; #else if (!CreateStdInStream(inStream)) { const DWORD lastError = ::GetLastError(); const HRESULT res = callback->OpenFileError(FString("stdin"), lastError); hb.NumErrors++; if (res != S_FALSE && res != S_OK) return res; continue; } #endif } else { path = dirItems.GetLogPath(i); const CDirItem &di = dirItems.Items[i]; #ifdef _WIN32 isAltStream = di.IsAltStream; #endif #ifndef UNDER_CE // if (di.AreReparseData()) if (di.ReparseData.Size() != 0) { CBufInStream *inStreamSpec = new CBufInStream(); inStream = inStreamSpec; inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); } else #endif { CInFileStream *inStreamSpec = new CInFileStream; inStreamSpec->Set_PreserveATime(options.PreserveATime); inStream = inStreamSpec; isDir = di.IsDir(); if (!isDir) { const FString phyPath = dirItems.GetPhyPath(i); if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) { const HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); hb.NumErrors++; if (res != S_FALSE) return res; continue; } if (!options.StdInMode) { UInt64 curSize = 0; if (inStreamSpec->GetSize(&curSize) == S_OK) { if (curSize > di.Size) { totalSize += curSize - di.Size; RINOK(callback->SetTotal(totalSize)) // printf("\ntotal = %d MiB\n", (unsigned)(totalSize >> 20)); } } } // inStreamSpec->ReloadProps(); } } } RINOK(callback->GetStream(path, isDir)) UInt64 fileSize = 0; hb.InitForNewFile(); if (!isDir) { for (UInt32 step = 0;; step++) { if ((step & 0xFF) == 0) { // printf("\ncompl = %d\n", (unsigned)(completeValue >> 20)); RINOK(callback->SetCompleted(&completeValue)) } UInt32 size; RINOK(inStream->Read(buf, kBufSize, &size)) if (size == 0) break; hb.Update(buf, size); fileSize += size; completeValue += size; } } hb.Final(isDir, isAltStream, path); /* if (needGenerate && (options.HashMode_Dirs.Val || !isDir)) { WriteLine(hashFileString, options, path, // change it isDir, hb); if (hashFileString.IsError()) return E_OUTOFMEMORY; } */ RINOK(callback->SetOperationResult(fileSize, hb, !isDir)) RINOK(callback->SetCompleted(&completeValue)) } /* if (needGenerate) { NFile::NIO::COutFile file; if (!file.Create(us2fs(options.HashFilePath), true)) // createAlways return GetLastError_noZero_HRESULT(); if (!file.WriteFull(hashFileString, hashFileString.Len())) return GetLastError_noZero_HRESULT(); } */ return callback->AfterLastFile(hb); } void HashHexToString(char *dest, const Byte *data, size_t size) { if (!data) { for (size_t i = 0; i < size; i++) { dest[0] = ' '; dest[1] = ' '; dest += 2; } *dest = 0; return; } if (size > 8) ConvertDataToHex_Lower(dest, data, size); else if (size == 0) { *dest = 0; return; } else { const char *dest_start = dest; dest += size * 2; *dest = 0; do { const size_t b = *data++; dest -= 2; dest[0] = GET_HEX_CHAR_UPPER(b >> 4); dest[1] = GET_HEX_CHAR_UPPER(b & 15); } while (dest != dest_start); } } void CHasherState::WriteToString(unsigned digestIndex, char *s) const { HashHexToString(s, Digests[digestIndex], DigestSize); if (digestIndex != 0 && NumSums[digestIndex] != 1) { unsigned numExtraBytes = GetNumExtraBytes_for_Group(digestIndex); if (numExtraBytes > 4) numExtraBytes = 8; else // if (numExtraBytes >= 0) numExtraBytes = 4; // if (numExtraBytes != 0) { s += strlen(s); *s++ = '-'; // *s = 0; HashHexToString(s, GetExtraData_for_Group(digestIndex), numExtraBytes); } } } // ---------- Hash Handler ---------- namespace NHash { #define IsWhite(c) ((c) == ' ' || (c) == '\t') bool CHashPair::IsDir() const { if (Name.IsEmpty() || Name.Back() != '/') return false; // here we expect that Dir items contain only zeros or no Hash for (size_t i = 0; i < Hash.Size(); i++) if (Hash.ConstData()[i] != 0) return false; return true; } bool CHashPair::ParseCksum(const char *s) { const char *end; const UInt32 crc = ConvertStringToUInt32(s, &end); if (*end != ' ') return false; end++; const UInt64 size = ConvertStringToUInt64(end, &end); if (*end != ' ') return false; end++; Name = end; Hash.Alloc(4); SetBe32(Hash, crc) Size_from_Arc = size; Size_from_Arc_Defined = true; return true; } static const char *SkipWhite(const char *s) { while (IsWhite(*s)) s++; return s; } static const char * const k_CsumMethodNames[] = { "sha256" , "sha224" // , "sha512/224" // , "sha512/256" , "sha512" , "sha384" , "sha1" , "md5" , "blake2b" , "crc64" , "crc32" , "cksum" }; static UString GetMethod_from_FileName(const UString &name) { AString s; ConvertUnicodeToUTF8(name, s); const int dotPos = s.ReverseFind_Dot(); const char *src = s.Ptr(); bool isExtension = false; if (dotPos >= 0) { isExtension = true; src = s.Ptr(dotPos + 1); } const char *m = ""; unsigned i; for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) { m = k_CsumMethodNames[i]; if (isExtension) { if (StringsAreEqual_Ascii(src, m)) break; } else if (IsString1PrefixedByString2_NoCase_Ascii(src, m)) if (StringsAreEqual_Ascii(src + strlen(m), "sums")) break; } UString res; if (i != Z7_ARRAY_SIZE(k_CsumMethodNames)) res = m; return res; } bool CHashPair::Parse(const char *s) { // here we keep compatibility with original md5sum / shasum bool escape = false; s = SkipWhite(s); if (*s == '\\') { s++; escape = true; } Escape = escape; // const char *kMethod = GetMethod_from_FileName(s); // if (kMethod) if ((size_t)(FindNonHexChar(s) - s) < 4) { // BSD-style checksum line { const char *s2 = s; for (; *s2 != 0; s2++) { const char c = *s2; if (c == 0) return false; if (c == ' ' || c == '(') break; } Method.SetFrom(s, (unsigned)(s2 - s)); s = s2; } IsBSD = true; if (*s == ' ') s++; if (*s != '(') return false; s++; { const char *s2 = s; for (; *s2 != 0; s2++) {} for (;;) { s2--; if (s2 < s) return false; if (*s2 == ')') break; } Name.SetFrom(s, (unsigned)(s2 - s)); s = s2 + 1; } s = SkipWhite(s); if (*s != '=') return false; s++; s = SkipWhite(s); } { const size_t numChars = (size_t)(FindNonHexChar(s) - s) & ~(size_t)1; Hash.Alloc(numChars / 2); if ((size_t)(ParseHexString(s, Hash) - Hash) != numChars / 2) throw 101; HashString.SetFrom(s, (unsigned)numChars); s += numChars; } if (IsBSD) { if (*s != 0) return false; if (escape) { const AString temp (Name); return CSum_Name_EscapeToOriginal(temp, Name); } return true; } if (*s == 0) return true; if (*s != ' ') return false; s++; const char c = *s; if (c != ' ' && c != '*' && c != 'U' // shasum Universal && c != '^' // shasum 0/1 ) return false; Mode = c; s++; if (escape) return CSum_Name_EscapeToOriginal(s, Name); Name = s; return true; } static bool GetLine(CByteBuffer &buf, bool zeroMode, bool cr_lf_Mode, size_t &posCur, AString &s) { s.Empty(); size_t pos = posCur; const Byte *p = buf; unsigned numDigits = 0; for (; pos < buf.Size(); pos++) { const Byte b = p[pos]; if (b == 0) { numDigits = 1; break; } if (zeroMode) continue; if (b == 0x0a) { numDigits = 1; break; } if (!cr_lf_Mode) continue; if (b == 0x0d) { if (pos + 1 >= buf.Size()) { numDigits = 1; break; // return false; } if (p[pos + 1] == 0x0a) { numDigits = 2; break; } } } s.SetFrom((const char *)(p + posCur), (unsigned)(pos - posCur)); posCur = pos + numDigits; return true; } static bool Is_CR_LF_Data(const Byte *buf, size_t size) { bool isCrLf = false; for (size_t i = 0; i < size;) { const Byte b = buf[i]; if (b == 0x0a) return false; if (b == 0x0d) { if (i == size - 1) return false; if (buf[i + 1] != 0x0a) return false; isCrLf = true; i += 2; } else i++; } return isCrLf; } static const Byte kArcProps[] = { // kpidComment, kpidCharacts }; static const Byte kProps[] = { kpidPath, kpidSize, kpidPackSize, kpidMethod }; static const Byte kRawProps[] = { kpidChecksum }; Z7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */ , UInt32 *parent, UInt32 *parentType)) { *parentType = NParentType::kDir; *parent = (UInt32)(Int32)-1; return S_OK; } Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)) { *numProps = Z7_ARRAY_SIZE(kRawProps); return S_OK; } Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)) { *propID = kRawProps[index]; *name = NULL; return S_OK; } Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) { *data = NULL; *dataSize = 0; *propType = 0; if (propID == kpidChecksum) { const CHashPair &hp = HashPairs[index]; if (hp.Hash.Size() > 0) { *data = hp.Hash; *dataSize = (UInt32)hp.Hash.Size(); *propType = NPropDataType::kRaw; } return S_OK; } return S_OK; } IMP_IInArchive_Props IMP_IInArchive_ArcProps Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = HashPairs.Size(); return S_OK; } static void Add_OptSpace_String(UString &dest, const char *src) { dest.Add_Space_if_NotEmpty(); dest += src; } Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidPhySize: if (_phySize != 0) prop = _phySize; break; /* case kpidErrorFlags: { UInt32 v = 0; if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; // if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; if (v != 0) prop = v; break; } */ case kpidCharacts: { UString s; if (_hashSize_Defined) { s.Add_Space_if_NotEmpty(); s.Add_UInt32(_hashSize * 8); s += "-bit"; } if (!_nameExtenstion.IsEmpty()) { s.Add_Space_if_NotEmpty(); s += _nameExtenstion; } if (_is_PgpMethod) { Add_OptSpace_String(s, "PGP"); if (!_pgpMethod.IsEmpty()) { s.Add_Colon(); s += _pgpMethod; } } if (_is_ZeroMode) Add_OptSpace_String(s, "ZERO"); if (_are_there_Tags) Add_OptSpace_String(s, "TAG"); if (_are_there_Dirs) Add_OptSpace_String(s, "DIRS"); prop = s; break; } case kpidReadOnly: { if (_isArc) if (!CanUpdate()) prop = true; break; } default: break; } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { // COM_TRY_BEGIN NCOM::CPropVariant prop; const CHashPair &hp = HashPairs[index]; switch (propID) { case kpidIsDir: { prop = hp.IsDir(); break; } case kpidPath: { UString path; hp.Get_UString_Path(path); bool useBackslashReplacement = true; if (_supportWindowsBackslash && !hp.Escape && path.Find(L"\\\\") < 0) { #if WCHAR_PATH_SEPARATOR == L'/' path.Replace(L'\\', L'/'); #else useBackslashReplacement = false; #endif } NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash( path, useBackslashReplacement); prop = path; break; } case kpidSize: { // client needs processed size of last file if (hp.Size_from_Disk_Defined) prop = (UInt64)hp.Size_from_Disk; else if (hp.Size_from_Arc_Defined) prop = (UInt64)hp.Size_from_Arc; break; } case kpidPackSize: { prop = (UInt64)hp.Hash.Size(); break; } case kpidMethod: { if (!hp.Method.IsEmpty()) prop = hp.Method; break; } default: break; } prop.Detach(value); return S_OK; // COM_TRY_END } static HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOpenCallback *openCallback) { buf.Free(); UInt64 len; RINOK(InStream_AtBegin_GetSize(stream, len)) if (len == 0 || len >= ((UInt64)1 << 31)) return S_FALSE; buf.Alloc((size_t)len); UInt64 pos = 0; // return ReadStream_FALSE(stream, buf, (size_t)len); for (;;) { const UInt32 kBlockSize = ((UInt32)1 << 24); const UInt32 curSize = (len < kBlockSize) ? (UInt32)len : kBlockSize; UInt32 processedSizeLoc; RINOK(stream->Read((Byte *)buf + pos, curSize, &processedSizeLoc)) if (processedSizeLoc == 0) return E_FAIL; len -= processedSizeLoc; pos += processedSizeLoc; if (len == 0) return S_OK; if (openCallback) { const UInt64 files = 0; RINOK(openCallback->SetCompleted(&files, &pos)) } } } Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) { COM_TRY_BEGIN { Close(); CByteBuffer buf; RINOK(ReadStream_to_Buf(stream, buf, openCallback)) CObjectVector &pairs = HashPairs; bool zeroMode = false; bool cr_lf_Mode = false; { for (size_t i = 0; i < buf.Size(); i++) if (buf.ConstData()[i] == 0) { zeroMode = true; break; } } _is_ZeroMode = zeroMode; if (!zeroMode) cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); if (openCallback) { Z7_DECL_CMyComPtr_QI_FROM( IArchiveOpenVolumeCallback, openVolumeCallback, openCallback) if (openVolumeCallback) { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) if (prop.vt == VT_BSTR) _nameExtenstion = GetMethod_from_FileName(prop.bstrVal); } } bool cksumMode = false; if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum")) cksumMode = true; _is_CksumMode = cksumMode; size_t pos = 0; AString s; bool minusMode = false; unsigned numLines = 0; while (pos < buf.Size()) { if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s)) return S_FALSE; numLines++; if (s.IsEmpty()) continue; if (s.IsPrefixedBy_Ascii_NoCase("; ")) { if (numLines != 1) return S_FALSE; // comment line of FileVerifier++ continue; } if (s.IsPrefixedBy_Ascii_NoCase("-----")) { if (minusMode) break; // end of pgp mode minusMode = true; if (s.IsPrefixedBy_Ascii_NoCase("-----BEGIN PGP SIGNED MESSAGE")) { if (_is_PgpMethod) return S_FALSE; if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s)) return S_FALSE; const char *kStart = "Hash: "; if (!s.IsPrefixedBy_Ascii_NoCase(kStart)) return S_FALSE; _pgpMethod = s.Ptr((unsigned)strlen(kStart)); _is_PgpMethod = true; } continue; } CHashPair pair; pair.FullLine = s; if (cksumMode) { if (!pair.ParseCksum(s)) return S_FALSE; } else if (!pair.Parse(s)) return S_FALSE; pairs.Add(pair); } { unsigned hashSize = 0; bool hashSize_Dismatch = false; for (unsigned i = 0; i < HashPairs.Size(); i++) { const CHashPair &hp = HashPairs[i]; if (i == 0) hashSize = (unsigned)hp.Hash.Size(); else if (hashSize != hp.Hash.Size()) hashSize_Dismatch = true; if (hp.IsBSD) _are_there_Tags = true; if (!_are_there_Dirs && hp.IsDir()) _are_there_Dirs = true; } if (!hashSize_Dismatch && hashSize != 0) { _hashSize = hashSize; _hashSize_Defined = true; } } _phySize = buf.Size(); _isArc = true; return S_OK; } COM_TRY_END } void CHandler::ClearVars() { _phySize = 0; _isArc = false; _is_CksumMode = false; _is_PgpMethod = false; _is_ZeroMode = false; _are_there_Tags = false; _are_there_Dirs = false; _hashSize_Defined = false; _hashSize = 0; } Z7_COM7F_IMF(CHandler::Close()) { ClearVars(); _nameExtenstion.Empty(); _pgpMethod.Empty(); HashPairs.Clear(); return S_OK; } static bool CheckDigests(const Byte *a, const Byte *b, size_t size) { if (size <= 8) { /* we use reversed order for one digest, when text representation uses big-order for crc-32 and crc-64 */ for (size_t i = 0; i < size; i++) if (a[i] != b[size - 1 - i]) return false; return true; } { for (size_t i = 0; i < size; i++) if (a[i] != b[i]) return false; return true; } } static void AddDefaultMethod(UStringVector &methods, unsigned size) { const char *m = NULL; if (size == 32) m = "sha256"; else if (size == 20) m = "sha1"; else if (size == 16) m = "md5"; else if (size == 8) m = "crc64"; else if (size == 4) m = "crc32"; else return; #ifdef Z7_EXTERNAL_CODECS const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; #endif CMethodId id; if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS AString(m), id)) methods.Add(UString(m)); } Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) { COM_TRY_BEGIN /* if (testMode == 0) return E_NOTIMPL; */ const bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = HashPairs.Size(); if (numItems == 0) return S_OK; #ifdef Z7_EXTERNAL_CODECS const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; #endif CHashBundle hb_Glob; // UStringVector methods = options.Methods; UStringVector methods; if (methods.IsEmpty() && !_nameExtenstion.IsEmpty()) { AString utf; ConvertUnicodeToUTF8(_nameExtenstion, utf); CMethodId id; if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id)) methods.Add(_nameExtenstion); } if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) { CMethodId id; if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS _pgpMethod, id)) methods.Add(UString(_pgpMethod)); } if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) AddDefaultMethod(methods, _hashSize); RINOK(hb_Glob.SetMethods( EXTERNAL_CODECS_LOC_VARS methods)) Z7_DECL_CMyComPtr_QI_FROM( IArchiveUpdateCallbackFile, updateCallbackFile, extractCallback) if (!updateCallbackFile) return E_NOTIMPL; { Z7_DECL_CMyComPtr_QI_FROM( IArchiveGetDiskProperty, GetDiskProperty, extractCallback) if (GetDiskProperty) { UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) { const UInt32 index = allFilesMode ? i : indices[i]; const CHashPair &hp = HashPairs[index]; if (hp.IsDir()) continue; { NCOM::CPropVariant prop; RINOK(GetDiskProperty->GetDiskProperty(index, kpidSize, &prop)) if (prop.vt != VT_UI8) continue; totalSize += prop.uhVal.QuadPart; } } RINOK(extractCallback->SetTotal(totalSize)) // RINOK(Hash_SetTotalUnpacked->Hash_SetTotalUnpacked(indices, numItems)); } } const UInt32 kBufSize = 1 << 15; CHashMidBuf buf; if (!buf.Alloc(kBufSize)) return E_OUTOFMEMORY; CMyComPtr2_Create lps; lps->Init(extractCallback, false); for (UInt32 i = 0;; i++) { RINOK(lps->SetCur()) if (i >= numItems) break; const UInt32 index = allFilesMode ? i : indices[i]; CHashPair &hp = HashPairs[index]; UString path; hp.Get_UString_Path(path); CMyComPtr inStream; const bool isDir = hp.IsDir(); if (!isDir) { RINOK(updateCallbackFile->GetStream2(index, &inStream, NUpdateNotifyOp::kHashRead)) if (!inStream) { continue; // we have shown error in GetStream2() } // askMode = NArchive::NExtract::NAskMode::kSkip; } Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; CMyComPtr realOutStream; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) /* PrepareOperation() can expect kExtract to set Attrib and security of output file */ askMode = NArchive::NExtract::NAskMode::kReadExternal; RINOK(extractCallback->PrepareOperation(askMode)) const bool isAltStream = false; UInt64 fileSize = 0; CHashBundle hb_Loc; CHashBundle *hb_Use = &hb_Glob; HRESULT res_SetMethods = S_OK; UStringVector methods_loc; if (!hp.Method.IsEmpty()) { hb_Use = &hb_Loc; CMethodId id; if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id)) { methods_loc.Add(UString(hp.Method)); RINOK(hb_Loc.SetMethods( EXTERNAL_CODECS_LOC_VARS methods_loc)) } else res_SetMethods = E_NOTIMPL; } else if (methods.IsEmpty()) { AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size()); if (!methods_loc.IsEmpty()) { hb_Use = &hb_Loc; RINOK(hb_Loc.SetMethods( EXTERNAL_CODECS_LOC_VARS methods_loc)) } } const bool isSupportedMode = hp.IsSupportedMode(); hb_Use->InitForNewFile(); if (inStream) { for (UInt32 step = 0;; step++) { if ((step & 0xFF) == 0) { RINOK(lps.Interface()->SetRatioInfo(NULL, &fileSize)) } UInt32 size; RINOK(inStream->Read(buf, kBufSize, &size)) if (size == 0) break; hb_Use->Update(buf, size); if (realOutStream) { RINOK(WriteStream(realOutStream, buf, size)) } fileSize += size; } hp.Size_from_Disk = fileSize; hp.Size_from_Disk_Defined = true; } realOutStream.Release(); inStream.Release(); lps->InSize += hp.Hash.Size(); lps->OutSize += fileSize; hb_Use->Final(isDir, isAltStream, path); Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; if (isSupportedMode && res_SetMethods != E_NOTIMPL && hb_Use->Hashers.Size() > 0 ) { const CHasherState &hs = hb_Use->Hashers[0]; if (hs.DigestSize == hp.Hash.Size()) { opRes = NArchive::NExtract::NOperationResult::kCRCError; if (CheckDigests(hp.Hash, hs.Digests[0], hs.DigestSize)) if (!hp.Size_from_Arc_Defined || hp.Size_from_Arc == fileSize) opRes = NArchive::NExtract::NOperationResult::kOK; } } RINOK(extractCallback->SetOperationResult(opRes)) } return S_OK; COM_TRY_END } // ---------- UPDATE ---------- struct CUpdateItem { int IndexInArc; unsigned IndexInClient; UInt64 Size; bool NewData; bool NewProps; bool IsDir; UString Path; CUpdateItem(): Size(0), IsDir(false) {} }; static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, UString &res, bool convertSlash) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(index, propId, &prop)) if (prop.vt == VT_BSTR) { res = prop.bstrVal; if (convertSlash) NArchive::NItemName::ReplaceSlashes_OsToUnix(res); } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type)) { *type = NFileTimeType::kUnix; return S_OK; } Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback)) { COM_TRY_BEGIN if (_isArc && !CanUpdate()) return E_NOTIMPL; /* Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, callback) */ CObjectVector updateItems; UInt64 complexity = 0; UInt32 i; for (i = 0; i < numItems; i++) { CUpdateItem ui; Int32 newData; Int32 newProps; UInt32 indexInArc; if (!callback) return E_FAIL; RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc)) ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); ui.IndexInArc = (int)indexInArc; ui.IndexInClient = i; if (IntToBool(newProps)) { { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidIsDir, &prop)) if (prop.vt == VT_EMPTY) ui.IsDir = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsDir = (prop.boolVal != VARIANT_FALSE); } RINOK(GetPropString(callback, i, kpidPath, ui.Path, true)) // convertSlash /* if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') ui.Name += '/'; */ } if (IntToBool(newData)) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidSize, &prop)) if (prop.vt == VT_UI8) { ui.Size = prop.uhVal.QuadPart; complexity += ui.Size; } else if (prop.vt == VT_EMPTY) ui.Size = (UInt64)(Int64)-1; else return E_INVALIDARG; } updateItems.Add(ui); } if (complexity != 0) { RINOK(callback->SetTotal(complexity)) } #ifdef Z7_EXTERNAL_CODECS const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; #endif CHashBundle hb; UStringVector methods; if (!_methods.IsEmpty()) { FOR_VECTOR(k, _methods) { methods.Add(_methods[k]); } } else if (_crcSize_WasSet) { AddDefaultMethod(methods, _crcSize); } else { Z7_DECL_CMyComPtr_QI_FROM( IArchiveGetRootProps, getRootProps, callback) if (getRootProps) { NCOM::CPropVariant prop; RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) if (prop.vt == VT_BSTR) { const UString method = GetMethod_from_FileName(prop.bstrVal); if (!method.IsEmpty()) methods.Add(method); } } } RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) CMyComPtr2_Create lps; lps->Init(callback, true); const UInt32 kBufSize = 1 << 15; CHashMidBuf buf; if (!buf.Alloc(kBufSize)) return E_OUTOFMEMORY; CDynLimBuf hashFileString((size_t)1 << 31); CHashOptionsLocal options = _options; if (_isArc) { if (!options.HashMode_Zero.Def && _is_ZeroMode) options.HashMode_Zero.Val = true; if (!options.HashMode_Tag.Def && _are_there_Tags) options.HashMode_Tag.Val = true; if (!options.HashMode_Dirs.Def && _are_there_Dirs) options.HashMode_Dirs.Val = true; } if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1) options.HashMode_OnlyHash.Val = false; complexity = 0; for (i = 0; i < updateItems.Size(); i++) { lps->InSize = complexity; RINOK(lps->SetCur()) const CUpdateItem &ui = updateItems[i]; /* CHashPair item; if (!ui.NewProps) item = HashPairs[(unsigned)ui.IndexInArc]; */ if (ui.NewData) { UInt64 currentComplexity = ui.Size; UInt64 fileSize = 0; CMyComPtr fileInStream; bool needWrite = true; { HRESULT res = callback->GetStream(ui.IndexInClient, &fileInStream); if (res == S_FALSE) needWrite = false; else { RINOK(res) if (fileInStream) { Z7_DECL_CMyComPtr_QI_FROM( IStreamGetSize, streamGetSize, fileInStream) if (streamGetSize) { UInt64 size; if (streamGetSize->GetSize(&size) == S_OK) currentComplexity = size; } /* Z7_DECL_CMyComPtr_QI_FROM( IStreamGetProps, getProps, fileInStream) if (getProps) { FILETIME mTime; UInt64 size2; if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) { currentComplexity = size2; // item.MTime = NTime::FileTimeToUnixTime64(mTime);; } } */ } else { currentComplexity = 0; } } } hb.InitForNewFile(); const bool isDir = ui.IsDir; if (needWrite && fileInStream && !isDir) { for (UInt32 step = 0;; step++) { if ((step & 0xFF) == 0) { RINOK(lps.Interface()->SetRatioInfo(&fileSize, NULL)) // RINOK(callback->SetCompleted(&completeValue)); } UInt32 size; RINOK(fileInStream->Read(buf, kBufSize, &size)) if (size == 0) break; hb.Update(buf, size); fileSize += size; } currentComplexity = fileSize; } fileInStream.Release(); const bool isAltStream = false; hb.Final(isDir, isAltStream, ui.Path); if (options.HashMode_Dirs.Val || !isDir) { if (!hb.Hashers.IsEmpty()) lps->OutSize += hb.Hashers[0].DigestSize; WriteLine(hashFileString, options, ui.Path, isDir, hb); if (hashFileString.IsError()) return E_OUTOFMEMORY; } complexity += currentComplexity; /* if (reportArcProp) { PROPVARIANT prop; prop.vt = VT_EMPTY; prop.wReserved1 = 0; NCOM::PropVarEm_Set_UInt64(&prop, fileSize); RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidSize, &prop)); for (unsigned k = 0; k < hb.Hashers.Size(); k++) { const CHasherState &hs = hb.Hashers[k]; if (hs.DigestSize == 4 && hs.Name.IsEqualTo_Ascii_NoCase("crc32")) { NCOM::PropVarEm_Set_UInt32(&prop, GetUi32(hs.Digests[k_HashCalc_Index_Current])); RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidCRC, &prop)); } else { RINOK(reportArcProp->ReportRawProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidChecksum, hs.Digests[k_HashCalc_Index_Current], hs.DigestSize, NPropDataType::kRaw)); } RINOK(reportArcProp->ReportFinished(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, NArchive::NUpdate::NOperationResult::kOK)); } } */ RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)) } else { // old data const CHashPair &existItem = HashPairs[(unsigned)ui.IndexInArc]; if (ui.NewProps) { WriteLine(hashFileString, options, ui.Path, ui.IsDir, existItem.Method, existItem.HashString ); } else { hashFileString += existItem.FullLine; Add_LF(hashFileString, options); } } if (hashFileString.IsError()) return E_OUTOFMEMORY; } RINOK(WriteStream(outStream, hashFileString, hashFileString.Len())) return S_OK; COM_TRY_END } HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeLower_Ascii(); if (name.IsEmpty()) return E_INVALIDARG; if (name.IsEqualTo("m")) // "hm" hash method { // COneMethodInfo omi; // RINOK(omi.ParseMethodFromPROPVARIANT(L"", value)); // _methods.Add(omi.MethodName); // change it. use omi.PropsString if (value.vt != VT_BSTR) return E_INVALIDARG; UString s (value.bstrVal); _methods.Add(s); return S_OK; } if (name.IsEqualTo("flags")) { if (value.vt != VT_BSTR) return E_INVALIDARG; if (!_options.ParseString(value.bstrVal)) return E_INVALIDARG; return S_OK; } if (name.IsEqualTo("backslash")) return PROPVARIANT_to_bool(value, _supportWindowsBackslash); if (name.IsPrefixedBy_Ascii_NoCase("crc")) { name.Delete(0, 3); _crcSize = 4; _crcSize_WasSet = true; return ParsePropToUInt32(name, value, _crcSize); } // common properties if (name.IsPrefixedBy_Ascii_NoCase("mt") || name.IsPrefixedBy_Ascii_NoCase("memuse")) return S_OK; return E_INVALIDARG; } Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) { COM_TRY_BEGIN InitProps(); for (UInt32 i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])) } return S_OK; COM_TRY_END } CHandler::CHandler() { ClearVars(); InitProps(); } } static IInArchive *CreateHashHandler_In() { return new NHash::CHandler; } static IOutArchive *CreateHashHandler_Out() { return new NHash::CHandler; } void Codecs_AddHashArcHandler(CCodecs *codecs) { { CArcInfoEx item; item.Name = "Hash"; item.CreateInArchive = CreateHashHandler_In; item.CreateOutArchive = CreateHashHandler_Out; item.IsArcFunc = NULL; item.Flags = NArcInfoFlags::kKeepName | NArcInfoFlags::kStartOpen | NArcInfoFlags::kByExtOnlyOpen // | NArcInfoFlags::kPureStartOpen | NArcInfoFlags::kHashHandler ; // ubuntu uses "SHA256SUMS" file item.AddExts(UString ( "sha256 sha512 sha224 sha384 sha1 sha md5" // "b2sum" " crc32 crc64" " asc" " cksum" ), UString()); item.UpdateEnabled = (item.CreateOutArchive != NULL); item.SignatureOffset = 0; // item.Version = MY_VER_MIX; item.NewInterface = true; item.Signatures.AddNew().CopyFrom(NULL, 0); codecs->Formats.Add(item); } } tmp41wklro_/CPP/7zip/UI/Common/HashCalc.h0000444000175000001440000001674114561464040021055 0ustar nabijaczleweliusers// HashCalc.h #ifndef ZIP7_INC_HASH_CALC_H #define ZIP7_INC_HASH_CALC_H #include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" #include "../../Common/CreateCoder.h" #include "../../Common/MethodProps.h" #include "DirItem.h" #include "IFileExtractCallback.h" const unsigned k_HashCalc_DigestSize_Max = 64; const unsigned k_HashCalc_ExtraSize = 8; const unsigned k_HashCalc_NumGroups = 4; /* if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number if (size > 8) : lower case : original byte order (as big-endian byte sequence) */ void HashHexToString(char *dest, const Byte *data, size_t size); enum { k_HashCalc_Index_Current, k_HashCalc_Index_DataSum, k_HashCalc_Index_NamesSum, k_HashCalc_Index_StreamsSum }; struct CHasherState { CMyComPtr Hasher; AString Name; UInt32 DigestSize; UInt64 NumSums[k_HashCalc_NumGroups]; Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize]; void InitDigestGroup(unsigned groupIndex) { NumSums[groupIndex] = 0; memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex])); } const Byte *GetExtraData_for_Group(unsigned groupIndex) const { return Digests[groupIndex] + k_HashCalc_DigestSize_Max; } unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const { const Byte *p = GetExtraData_for_Group(groupIndex); // we use little-endian to read extra bytes for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--) if (p[i - 1] != 0) return i; return 0; } void AddDigest(unsigned groupIndex, const Byte *data); void WriteToString(unsigned digestIndex, char *s) const; }; Z7_PURE_INTERFACES_BEGIN DECLARE_INTERFACE(IHashCalc) { virtual void InitForNewFile() = 0; virtual void Update(const void *data, UInt32 size) = 0; virtual void SetSize(UInt64 size) = 0; virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0; }; Z7_PURE_INTERFACES_END struct CHashBundle Z7_final: public IHashCalc { CObjectVector Hashers; UInt64 NumDirs; UInt64 NumFiles; UInt64 NumAltStreams; UInt64 FilesSize; UInt64 AltStreamsSize; UInt64 NumErrors; UInt64 CurSize; UString MainName; UString FirstFileName; HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods); // void Init() {} CHashBundle() { NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; } void InitForNewFile() Z7_override; void Update(const void *data, UInt32 size) Z7_override; void SetSize(UInt64 size) Z7_override; void Final(bool isDir, bool isAltStream, const UString &path) Z7_override; }; Z7_PURE_INTERFACES_BEGIN // INTERFACE_IDirItemsCallback(x) #define Z7_IFACEN_IHashCallbackUI(x) \ virtual HRESULT StartScanning() x \ virtual HRESULT FinishScanning(const CDirItemsStat &st) x \ virtual HRESULT SetNumFiles(UInt64 numFiles) x \ virtual HRESULT SetTotal(UInt64 size) x \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x \ virtual HRESULT CheckBreak() x \ virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x \ virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x \ virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \ virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x \ virtual HRESULT AfterLastFile(CHashBundle &hb) x \ Z7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback) Z7_PURE_INTERFACES_END struct CHashOptionsLocal { CBoolPair HashMode_Zero; CBoolPair HashMode_Tag; CBoolPair HashMode_Dirs; CBoolPair HashMode_OnlyHash; void Init_HashOptionsLocal() { HashMode_Zero.Init(); HashMode_Tag.Init(); HashMode_Dirs.Init(); HashMode_OnlyHash.Init(); // HashMode_Dirs = true; // for debug } CHashOptionsLocal() { Init_HashOptionsLocal(); } bool ParseFlagCharOption(wchar_t c, bool val) { c = MyCharLower_Ascii(c); if (c == 'z') HashMode_Zero.SetVal_as_Defined(val); else if (c == 't') HashMode_Tag.SetVal_as_Defined(val); else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val); else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val); else return false; return true; } bool ParseString(const UString &s) { for (unsigned i = 0; i < s.Len();) { const wchar_t c = s[i++]; bool val = true; if (i < s.Len()) { const wchar_t next = s[i]; if (next == '-') { val = false; i++; } } if (!ParseFlagCharOption(c, val)) return false; } return true; } }; struct CHashOptions // : public CHashOptionsLocal { UStringVector Methods; // UString HashFilePath; bool PreserveATime; bool OpenShareForWrite; bool StdInMode; bool AltStreamsMode; CBoolPair SymLinks; NWildcard::ECensorPathMode PathMode; CHashOptions(): PreserveATime(false), OpenShareForWrite(false), StdInMode(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {} }; HRESULT HashCalc( DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor &censor, const CHashOptions &options, AString &errorInfo, IHashCallbackUI *callback); #ifndef Z7_SFX namespace NHash { struct CHashPair { CByteBuffer Hash; char Mode; bool IsBSD; bool Escape; bool Size_from_Arc_Defined; bool Size_from_Disk_Defined; AString Method; AString Name; AString FullLine; AString HashString; // unsigned HashLengthInBits; // AString MethodName; UInt64 Size_from_Arc; UInt64 Size_from_Disk; bool IsDir() const; void Get_UString_Path(UString &path) const { path.Empty(); if (!ConvertUTF8ToUnicode(Name, path)) return; } bool ParseCksum(const char *s); bool Parse(const char *s); bool IsSupportedMode() const { return Mode != 'U' && Mode != '^'; } CHashPair(): Mode(0) , IsBSD(false) , Escape(false) , Size_from_Arc_Defined(false) , Size_from_Disk_Defined(false) // , HashLengthInBits(0) , Size_from_Arc(0) , Size_from_Disk(0) {} }; Z7_CLASS_IMP_CHandler_IInArchive_3( IArchiveGetRawProps, /* public IGetArchiveHashHandler, */ IOutArchive, ISetProperties ) bool _isArc; bool _supportWindowsBackslash; bool _crcSize_WasSet; UInt64 _phySize; CObjectVector HashPairs; UString _nameExtenstion; // UString _method_fromName; AString _pgpMethod; bool _is_CksumMode; bool _is_PgpMethod; bool _is_ZeroMode; bool _are_there_Tags; bool _are_there_Dirs; bool _hashSize_Defined; unsigned _hashSize; UInt32 _crcSize; UStringVector _methods; CHashOptionsLocal _options; void ClearVars(); void InitProps() { _supportWindowsBackslash = true; _crcSize_WasSet = false; _crcSize = 4; _methods.Clear(); _options.Init_HashOptionsLocal(); } bool CanUpdate() const { if (!_isArc || _is_PgpMethod || _is_CksumMode) return false; return true; } HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value); public: CHandler(); }; } void Codecs_AddHashArcHandler(CCodecs *codecs); #endif #endif tmp41wklro_/CPP/7zip/UI/Common/IFileExtractCallback.h0000444000175000001440000000714714413351500023337 0ustar nabijaczleweliusers// IFileExtractCallback.h #ifndef ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H #define ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H #include "../../../Common/MyString.h" #include "../../IDecl.h" #include "LoadCodecs.h" #include "OpenArchive.h" Z7_PURE_INTERFACES_BEGIN #define Z7_IFACE_CONSTR_FOLDERARC_SUB(i, base, n) \ Z7_DECL_IFACE_7ZIP_SUB(i, base, 1, n) \ { Z7_IFACE_COM7_PURE(i) }; #define Z7_IFACE_CONSTR_FOLDERARC(i, n) \ Z7_IFACE_CONSTR_FOLDERARC_SUB(i, IUnknown, n) namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } /* ---------- IFolderArchiveExtractCallback ---------- is implemented by Console/ExtractCallbackConsole.h CExtractCallbackConsole FileManager/ExtractCallback.h CExtractCallbackImp FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported) IID_IFolderArchiveExtractCallback is requested by: - Agent/ArchiveFolder.cpp CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback) is sent to IArchiveFolder::Extract() - FileManager/PanelCopy.cpp CPanel::CopyTo(), if (options->testMode) is sent to IArchiveFolder::Extract() IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp */ #define Z7_IFACEM_IFolderArchiveExtractCallback(x) \ x(AskOverwrite( \ const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \ const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \ Int32 *answer)) \ x(PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)) \ x(MessageError(const wchar_t *message)) \ x(SetOperationResult(Int32 opRes, Int32 encrypted)) \ Z7_IFACE_CONSTR_FOLDERARC_SUB(IFolderArchiveExtractCallback, IProgress, 0x07) #define Z7_IFACEM_IFolderArchiveExtractCallback2(x) \ x(ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)) \ Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveExtractCallback2, 0x08) /* ---------- IExtractCallbackUI ---------- is implemented by Console/ExtractCallbackConsole.h CExtractCallbackConsole FileManager/ExtractCallback.h CExtractCallbackImp */ #ifdef Z7_NO_CRYPTO #define Z7_IFACEM_IExtractCallbackUI_Crypto(px) #else #define Z7_IFACEM_IExtractCallbackUI_Crypto(px) \ virtual HRESULT SetPassword(const UString &password) px #endif #define Z7_IFACEN_IExtractCallbackUI(px) \ virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) px \ virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) px \ virtual HRESULT ThereAreNoFiles() px \ virtual HRESULT ExtractResult(HRESULT result) px \ Z7_IFACEM_IExtractCallbackUI_Crypto(px) // IExtractCallbackUI - is non-COM interface // IFolderArchiveExtractCallback - is COM interface // Z7_IFACE_DECL_PURE_(IExtractCallbackUI, IFolderArchiveExtractCallback) Z7_IFACE_DECL_PURE(IExtractCallbackUI) #define Z7_IFACEM_IGetProp(x) \ x(GetProp(PROPID propID, PROPVARIANT *value)) \ Z7_IFACE_CONSTR_FOLDERARC(IGetProp, 0x20) #define Z7_IFACEM_IFolderExtractToStreamCallback(x) \ x(UseExtractToStream(Int32 *res)) \ x(GetStream7(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp)) \ x(PrepareOperation7(Int32 askExtractMode)) \ x(SetOperationResult8(Int32 resultEOperationResult, Int32 encrypted, UInt64 size)) \ Z7_IFACE_CONSTR_FOLDERARC(IFolderExtractToStreamCallback, 0x31) Z7_PURE_INTERFACES_END #endif tmp41wklro_/CPP/7zip/UI/Common/LoadCodecs.cpp0000444000175000001440000010202014533141040021713 0ustar nabijaczleweliusers// LoadCodecs.cpp /* Z7_EXTERNAL_CODECS --------------- CCodecs::Load() tries to detect the directory with plugins. It stops the checking, if it can find any of the following items: - 7z.dll file - "Formats" subdir - "Codecs" subdir The order of check: 1) directory of client executable 2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**] The order for HKEY_* : Path** : - HKEY_CURRENT_USER : PathXX - HKEY_LOCAL_MACHINE : PathXX - HKEY_CURRENT_USER : Path - HKEY_LOCAL_MACHINE : Path PathXX is Path32 in 32-bit code PathXX is Path64 in 64-bit code EXPORT_CODECS ------------- if (Z7_EXTERNAL_CODECS) is defined, then the code exports internal codecs of client from CCodecs object to external plugins. 7-Zip doesn't use that feature. 7-Zip uses the scheme: - client application without internal plugins. - 7z.dll module contains all (or almost all) plugins. 7z.dll can use codecs from another plugins, if required. */ #include "StdAfx.h" #include "../../../Common/MyCom.h" #include "../../../Common/StringToInt.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/PropVariant.h" #include "LoadCodecs.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #include "../../Common/RegisterCodec.h" #ifdef Z7_EXTERNAL_CODECS // #define EXPORT_CODECS #endif #ifdef Z7_EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef _WIN32 #include "../../../Windows/FileName.h" #include "../../../Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #define kCodecsFolderName FTEXT("Codecs") #define kFormatsFolderName FTEXT("Formats") static CFSTR const kMainDll = #ifdef _WIN32 FTEXT("7z.dll"); #else FTEXT("7z.so"); #endif #ifdef _WIN32 static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCWSTR const kProgramPathValue = L"Path"; static LPCWSTR const kProgramPath2Value = L"Path" #ifdef _WIN64 L"64"; #else L"32"; #endif static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) { NRegistry::CKey key; if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) { UString pathU; if (key.QueryValue(value, pathU) == ERROR_SUCCESS) { path = us2fs(pathU); NName::NormalizeDirPathPrefix(path); return NFind::DoesFileExist_Raw(path + kMainDll); } } return false; } #endif // _WIN32 #endif // Z7_EXTERNAL_CODECS static const unsigned kNumArcsMax = 72; static unsigned g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) throw() { if (g_NumArcs < kNumArcsMax) { g_Arcs[g_NumArcs] = arcInfo; g_NumArcs++; } // else throw 1; } /* static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; unsigned len = srcString.Len(); if (len == 0) return; for (unsigned i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } */ int CArcInfoEx::FindExtension(const UString &ext) const { FOR_VECTOR (i, Exts) if (ext.IsEqualTo_NoCase(Exts[i].Ext)) return (int)i; return -1; } void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) { UStringVector exts, addExts; SplitString(ext, exts); SplitString(addExt, addExts); FOR_VECTOR (i, exts) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifndef Z7_SFX static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector &signatures) { signatures.Clear(); while (size != 0) { const unsigned len = *data++; size--; if (len > size) return false; signatures.AddNew().CopyFrom(data, len); data += len; size -= len; } return true; } #endif // Z7_SFX // #include #ifdef Z7_EXTERNAL_CODECS static FString GetBaseFolderPrefixFromRegistry() { FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); #ifdef _WIN32 if ( !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll) && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName) && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName)) { FString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; } #endif // printf("\nmoduleFolderPrefix = %s\n", (const char *)GetAnsiString(moduleFolderPrefix)); return moduleFolderPrefix; } static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)) if (prop.vt == VT_BSTR) { if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) return E_FAIL; isAssigned = true; clsId = *(const GUID *)(const void *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index, PROPID propId, bool &resVal, bool &isAssigned) { NCOM::CPropVariant prop; resVal = false; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)) if (prop.vt == VT_BOOL) { isAssigned = true; resVal = VARIANT_BOOLToBool(prop.boolVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #if defined(__clang__) #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" #endif #ifdef _WIN32 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION #endif #define MY_GET_FUNC(dest, type, lib, func) \ dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func); // #define MY_GET_FUNC(dest, type, func) dest = (type)(func); #define MY_GET_FUNC_LOC(dest, type, lib, func) \ type dest; MY_GET_FUNC(dest, type, lib, func) HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); MY_GET_FUNC (lib.CreateDecoder, Func_CreateDecoder, lib.Lib, "CreateDecoder") MY_GET_FUNC (lib.CreateEncoder, Func_CreateEncoder, lib.Lib, "CreateEncoder") MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib, "GetMethodProperty") if (lib.GetMethodProperty) { UInt32 numMethods = 1; MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib, "GetNumberOfMethods") if (getNumberOfMethods) { RINOK(getNumberOfMethods(&numMethods)) } for (UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)) RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)) RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned)) Codecs.Add(info); } } MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib, "GetHashers") if (getHashers) { RINOK(getHashers(&lib.ComHashers)) if (lib.ComHashers) { UInt32 numMethods = lib.ComHashers->GetNumHashers(); for (UInt32 i = 0; i < numMethods; i++) { CDllHasherInfo info; info.LibIndex = Libs.Size() - 1; info.HasherIndex = i; Hashers.Add(info); } } } return S_OK; } static HRESULT GetProp( Func_GetHandlerProperty getProp, Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop); return getProp(propID, &prop); } static HRESULT GetProp_Bool( Func_GetHandlerProperty getProp, Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, bool &res) { res = false; NCOM::CPropVariant prop; RINOK(GetProp(getProp, getProp2, index, propID, prop)) if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT GetProp_UInt32( Func_GetHandlerProperty getProp, Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, UInt32 &res, bool &defined) { res = 0; defined = false; NCOM::CPropVariant prop; RINOK(GetProp(getProp, getProp2, index, propID, prop)) if (prop.vt == VT_UI4) { res = prop.ulVal; defined = true; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT GetProp_String( Func_GetHandlerProperty getProp, Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, UString &res) { res.Empty(); NCOM::CPropVariant prop; RINOK(GetProp(getProp, getProp2, index, propID, prop)) if (prop.vt == VT_BSTR) res.SetFromBstr(prop.bstrVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT GetProp_RawData( Func_GetHandlerProperty getProp, Func_GetHandlerProperty2 getProp2, UInt32 index, PROPID propID, CByteBuffer &bb) { bb.Free(); NCOM::CPropVariant prop; RINOK(GetProp(getProp, getProp2, index, propID, prop)) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); bb.CopyFrom((const Byte *)prop.bstrVal, len); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static const UInt32 kArcFlagsPars[] = { NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure }; HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; Func_GetHandlerProperty getProp = NULL; MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib, "GetHandlerProperty2") MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib, "GetIsArc") UInt32 numFormats = 1; if (getProp2) { MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib, "GetNumberOfFormats") if (getNumberOfFormats) { RINOK(getNumberOfFormats(&numFormats)) } } else { MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib, "GetHandlerProperty") if (!getProp) return S_OK; } for (UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = (int)(Libs.Size() - 1); item.FormatIndex = i; RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)) { NCOM::CPropVariant prop; if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) return E_FAIL; item.ClassID = *(const GUID *)(const void *)prop.bstrVal; prop.Clear(); } UString ext, addExt; RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)) RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)) item.AddExts(ext, addExt); GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); bool flags_Defined = false; RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)) item.NewInterface = flags_Defined; if (!flags_Defined) // && item.UpdateEnabled { // support for DLL version before 9.31: for (unsigned j = 0; j < Z7_ARRAY_SIZE(kArcFlagsPars); j += 2) { bool val = false; GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); if (val) item.Flags |= kArcFlagsPars[j + 1]; } } { bool defined = false; RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined)) } CByteBuffer sig; RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)) if (sig.Size() != 0) item.Signatures.Add(sig); else { RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)) ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); } bool signatureOffset_Defined; RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)) // bool version_Defined; // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); if (getIsArc) getIsArc(i, &item.IsArcFunc); Formats.Add(item); } return S_OK; } #ifdef Z7_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif void CCodecs::AddLastError(const FString &path) { const HRESULT res = GetLastError_noZero_HRESULT(); CCodecError &error = Errors.AddNew(); error.Path = path; error.ErrorCode = res; } static bool IsSupportedDll(CCodecLib &lib) { MY_GET_FUNC_LOC ( f_GetModuleProp, Func_GetModuleProp, lib.Lib, "GetModuleProp") /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown, if _WIN32 is not defined */ UInt32 flags = #ifdef _WIN32 NModuleInterfaceType::k_IUnknown_VirtDestructor_No; #else NModuleInterfaceType::k_IUnknown_VirtDestructor_Yes; #endif if (f_GetModuleProp) { { NCOM::CPropVariant prop; if (f_GetModuleProp(NModulePropID::kInterfaceType, &prop) == S_OK) { if (prop.vt == VT_UI4) flags = prop.ulVal; else if (prop.vt != VT_EMPTY) return false; } } { NCOM::CPropVariant prop; if (f_GetModuleProp(NModulePropID::kVersion, &prop) == S_OK) { if (prop.vt == VT_UI4) lib.Version = prop.ulVal; } } } if ( flags // (flags & NModuleFlags::kMask) != NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule) return false; return true; } HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK) { if (loadedOK) *loadedOK = false; // needCheckDll = 1; #ifdef _WIN32 if (needCheckDll) { NDLL::CLibrary lib; if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) { /* if is not win32 // %1 is not a valid Win32 application. // #define ERROR_BAD_EXE_FORMAT 193L */ // return GetLastError_noZero_HRESULT(); const DWORD lastError = GetLastError(); if (lastError != ERROR_BAD_EXE_FORMAT) { CCodecError &error = Errors.AddNew(); error.Path = dllPath; error.Message = "cannot load file as datafile library"; error.ErrorCode = HRESULT_FROM_WIN32(lastError); } return S_OK; } } #else UNUSED_VAR(needCheckDll) #endif Libs.AddNew(); CCodecLib &lib = Libs.Back(); lib.Path = dllPath; bool used = false; // HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { if (!IsSupportedDll(lib)) { CCodecError &error = Errors.AddNew(); error.Path = dllPath; error.Message = "the module is not compatible with program"; } else { if (loadedOK) *loadedOK = true; /* #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif */ /* { MY_GET_FUNC_LOC (_libStartup, Func_libStartup, lib.Lib, "LibStartup") if (_libStartup) { HRESULT res = _libStartup(); if (res != 0) { CCodecError &error = Errors.AddNew(); error.Path = dllPath; error.ErrorCode = res; } } } */ #ifdef Z7_LARGE_PAGES if (g_LargePageSize != 0) { MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib, "SetLargePageMode") if (setLargePageMode) setLargePageMode(); } #endif if (CaseSensitive_Change) { MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib, "SetCaseSensitive") if (setCaseSensitive) setCaseSensitive(CaseSensitive ? 1 : 0); } /* { MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib, "SetClientVersion") if (setClientVersion) { // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR; setClientVersion(g_ClientVersion); } } */ MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib, "CreateObject") { unsigned startSize = Codecs.Size() + Hashers.Size(); HRESULT res = LoadCodecs(); if (startSize != Codecs.Size() + Hashers.Size()) used = true; if (res == S_OK && lib.CreateObject) { startSize = Formats.Size(); res = LoadFormats(); if (startSize != Formats.Size()) used = true; } if (res != S_OK) { CCodecError &error = Errors.AddNew(); error.Path = dllPath; error.ErrorCode = res; } } // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs /* if (!used) { CCodecError &error = Errors.AddNew(); error.Path = dllPath; error.Message = "no 7-Zip code"; } */ } } else { AddLastError(dllPath); } if (!used) Libs.DeleteBack(); return S_OK; } HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath) { if (!NFile::NFind::DoesDirExist_FollowLink(folderPath)) // if (!NFile::NFind::DoesDirExist(folderPath)) { // AddLastError(folderPath); return S_OK; } FString folderPrefix = folderPath; folderPrefix.Add_PathSepar(); NFile::NFind::CEnumerator enumerator; enumerator.SetDirPrefix(folderPrefix); NFile::NFind::CDirEntry fi; for (;;) { bool found; if (!enumerator.Next(fi, found)) { // it can be wrong Symbolic link to folder here AddLastError(folderPath); break; // return GetLastError_noZero_HRESULT(); } if (!found) break; #ifdef _WIN32 if (fi.IsDir()) continue; #else if (enumerator.DirEntry_IsDir(fi, true)) // followLink continue; #endif RINOK(LoadDll(folderPrefix + fi.Name, true)) } return S_OK; } void CCodecs::CloseLibs() { // OutputDebugStringA("~CloseLibs start"); /* WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected, if it's called from another FreeLibrary() call. So we need to call FreeLibrary() before global destructors. Also we free global links from DLLs to object of this module before CLibrary::Free() call. */ FOR_VECTOR(i, Libs) { const CCodecLib &lib = Libs[i]; if (lib.SetCodecs) lib.SetCodecs(NULL); } // OutputDebugStringA("~CloseLibs after SetCodecs"); Libs.Clear(); // OutputDebugStringA("~CloseLibs end"); } #endif // Z7_EXTERNAL_CODECS HRESULT CCodecs::Load() { /* #ifdef NEW_FOLDER_INTERFACE InternalIcons.LoadIcons(g_hInstance); #endif */ Formats.Clear(); #ifdef Z7_EXTERNAL_CODECS Errors.Clear(); MainDll_ErrorPath.Empty(); Codecs.Clear(); Hashers.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.IsArcFunc = arc.IsArc; item.Flags = arc.Flags; { UString e, ae; if (arc.Ext) e = arc.Ext; if (arc.AddExt) ae = arc.AddExt; item.AddExts(e, ae); } #ifndef Z7_SFX item.CreateOutArchive = arc.CreateOutArchive; item.UpdateEnabled = (arc.CreateOutArchive != NULL); item.SignatureOffset = arc.SignatureOffset; // item.Version = MY_VER_MIX; item.NewInterface = true; if (arc.IsMultiSignature()) ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); else { if (arc.SignatureSize != 0) // 21.04 item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); } #endif Formats.Add(item); } // printf("\nLoad codecs \n"); #ifdef Z7_EXTERNAL_CODECS const FString baseFolder = GetBaseFolderPrefixFromRegistry(); { bool loadedOK; RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK)) if (!loadedOK) MainDll_ErrorPath = kMainDll; } RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName)) RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName)) NeedSetLibCodecs = true; if (Libs.Size() == 0) NeedSetLibCodecs = false; else if (Libs.Size() == 1) { // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module. #ifndef EXPORT_CODECS if (g_NumArcs == 0) NeedSetLibCodecs = false; #endif } if (NeedSetLibCodecs) { /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c) old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */ FOR_VECTOR(i, Libs) { CCodecLib &lib = Libs[i]; MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib, "SetCodecs") if (lib.SetCodecs) { RINOK(lib.SetCodecs(this)) } } } #endif // we sort Formats to get fixed order of Formats after compilation. Formats.Sort(); return S_OK; } #ifndef Z7_SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int dotPos = arcPath.ReverseFind_Dot(); if (dotPos <= arcPath.ReverseFind_PathSepar()) return -1; const UString ext = arcPath.Ptr((unsigned)(dotPos + 1)); if (ext.IsEmpty()) return -1; if (ext.IsEqualTo_Ascii_NoCase("exe")) return -1; FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; /* if (!arc.UpdateEnabled) continue; */ if (arc.FindExtension(ext) >= 0) return (int)i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; FOR_VECTOR (i, Formats) if (Formats[i].FindExtension(ext) >= 0) return (int)i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { FOR_VECTOR (i, Formats) if (Formats[i].Name.IsEqualTo_NoCase(arcType)) return (int)i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (unsigned pos = 0; pos < arcType.Len();) { int pos2 = arcType.Find(L'.', pos); if (pos2 < 0) pos2 = (int)arcType.Len(); const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); if (name.IsEmpty()) return false; int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = (unsigned)pos2 + 1; } return true; } #endif // Z7_SFX #ifdef Z7_EXTERNAL_CODECS // #define EXPORT_CODECS #ifdef EXPORT_CODECS extern unsigned g_NumCodecs; STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); #define NUM_EXPORT_CODECS g_NumCodecs extern unsigned g_NumHashers; STDAPI CreateHasher(UInt32 index, IHasher **hasher); STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); #define NUM_EXPORT_HASHERS g_NumHashers #else // EXPORT_CODECS #define NUM_EXPORT_CODECS 0 #define NUM_EXPORT_HASHERS 0 #endif // EXPORT_CODECS Z7_COM7F_IMF(CCodecs::GetNumMethods(UInt32 *numMethods)) { *numMethods = NUM_EXPORT_CODECS #ifdef Z7_EXTERNAL_CODECS + Codecs.Size() #endif ; return S_OK; } Z7_COM7F_IMF(CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif #ifdef Z7_EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (propID == NMethodPropID::kDecoderIsAssigned || propID == NMethodPropID::kEncoderIsAssigned) { NCOM::CPropVariant prop; prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ? ci.DecoderIsAssigned : ci.EncoderIsAssigned); prop.Detach(value); return S_OK; } if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned) { NCOM::CPropVariant prop; prop = (bool)ci.IsFilter; prop.Detach(value); return S_OK; } const CCodecLib &lib = Libs[ci.LibIndex]; return lib.GetMethodProperty(ci.CodecIndex, propID, value); #else return E_FAIL; #endif } Z7_COM7F_IMF(CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateDecoder(index, iid, coder); #endif #ifdef Z7_EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.DecoderIsAssigned) { const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateDecoder) return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder); if (lib.CreateObject) return lib.CreateObject(&ci.Decoder, iid, (void **)coder); } return S_OK; #else return E_FAIL; #endif } Z7_COM7F_IMF(CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateEncoder(index, iid, coder); #endif #ifdef Z7_EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.EncoderIsAssigned) { const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateEncoder) return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); if (lib.CreateObject) return lib.CreateObject(&ci.Encoder, iid, (void **)coder); } return S_OK; #else return E_FAIL; #endif } Z7_COM7F_IMF2(UInt32, CCodecs::GetNumHashers()) { return NUM_EXPORT_HASHERS #ifdef Z7_EXTERNAL_CODECS + Hashers.Size() #endif ; } Z7_COM7F_IMF(CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) { #ifdef EXPORT_CODECS if (index < g_NumHashers) return ::GetHasherProp(index, propID, value); #endif #ifdef Z7_EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value); #else return E_FAIL; #endif } Z7_COM7F_IMF(CCodecs::CreateHasher(UInt32 index, IHasher **hasher)) { #ifdef EXPORT_CODECS if (index < g_NumHashers) return CreateHasher(index, hasher); #endif #ifdef Z7_EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher); #else return E_FAIL; #endif } int CCodecs::GetCodec_LibIndex(UInt32 index) const { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef Z7_EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; return (int)ci.LibIndex; #else return -1; #endif } int CCodecs::GetHasherLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumHashers) return -1; #endif #ifdef Z7_EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return (int)ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK) { if (prop.vt == VT_BOOL) return VARIANT_BOOLToBool(prop.boolVal); } return false; } #endif #ifdef Z7_EXTERNAL_CODECS return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned; #else return false; #endif } bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK) { if (prop.vt == VT_BOOL) return VARIANT_BOOLToBool(prop.boolVal); } return false; } #endif #ifdef Z7_EXTERNAL_CODECS return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned; #else return false; #endif } bool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const { isAssigned = false; #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK) { if (prop.vt == VT_BOOL) { isAssigned = true; return VARIANT_BOOLToBool(prop.boolVal); } } return false; } #endif #ifdef Z7_EXTERNAL_CODECS { const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS]; isAssigned = c.IsFilter_Assigned; return c.IsFilter; } #else return false; #endif } UInt32 CCodecs::GetCodec_NumStreams(UInt32 index) { NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK) return 0; if (prop.vt == VT_UI4) return (UInt32)prop.ulVal; if (prop.vt == VT_EMPTY) return 1; return 0; } HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id) { NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)) if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } AString CCodecs::GetCodec_Name(UInt32 index) { AString s; NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s.SetFromWStr_if_Ascii(prop.bstrVal); return s; } UInt64 CCodecs::GetHasherId(UInt32 index) { NCOM::CPropVariant prop; if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK) return 0; if (prop.vt != VT_UI8) return 0; return prop.uhVal.QuadPart; } AString CCodecs::GetHasherName(UInt32 index) { AString s; NCOM::CPropVariant prop; if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s.SetFromWStr_if_Ascii(prop.bstrVal); return s; } UInt32 CCodecs::GetHasherDigestSize(UInt32 index) { NCOM::CPropVariant prop; if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK) return 0; if (prop.vt != VT_UI4) return 0; return prop.ulVal; } void CCodecs::GetCodecsErrorMessage(UString &s) { s.Empty(); FOR_VECTOR (i, Errors) { const CCodecError &ce = Errors[i]; s += "Codec Load Error: "; s += fs2us(ce.Path); if (ce.ErrorCode != 0) { s += " : "; s += NWindows::NError::MyFormatMessage(ce.ErrorCode); } if (!ce.Message.IsEmpty()) { s += " : "; s += ce.Message; } s.Add_LF(); } } #endif // Z7_EXTERNAL_CODECS #ifndef Z7_SFX extern unsigned g_NumCodecs; extern const CCodecInfo *g_Codecs[]; void CCodecs::Get_CodecsInfoUser_Vector(CObjectVector &v) { v.Clear(); { for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &cod = *g_Codecs[i]; CCodecInfoUser &u = v.AddNew(); u.EncoderIsAssigned = (cod.CreateEncoder != NULL); u.DecoderIsAssigned = (cod.CreateDecoder != NULL); u.IsFilter_Assigned = true; u.IsFilter = cod.IsFilter; u.NumStreams = cod.NumStreams; u.Name = cod.Name; } } #ifdef Z7_EXTERNAL_CODECS { UInt32 numMethods; if (GetNumMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { CCodecInfoUser &u = v.AddNew(); u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j); u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j); u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned); u.NumStreams = GetCodec_NumStreams(j); u.Name = GetCodec_Name(j); } } #endif } #endif tmp41wklro_/CPP/7zip/UI/Common/LoadCodecs.h0000444000175000001440000003172014413505020021367 0ustar nabijaczleweliusers// LoadCodecs.h #ifndef ZIP7_INC_LOAD_CODECS_H #define ZIP7_INC_LOAD_CODECS_H /* Client application uses LoadCodecs.* to load plugins to CCodecs object, that contains 3 lists of plugins: 1) Formats - internal and external archive handlers 2) Codecs - external codecs 3) Hashers - external hashers Z7_EXTERNAL_CODECS --------------- if Z7_EXTERNAL_CODECS is defined, then the code tries to load external plugins from DLL files (shared libraries). There are two types of executables in 7-Zip: 1) Executable that uses external plugins must be compiled with Z7_EXTERNAL_CODECS defined: - 7z.exe, 7zG.exe, 7zFM.exe Note: Z7_EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h that code is used in plugin module (7z.dll). 2) Standalone modules are compiled without Z7_EXTERNAL_CODECS: - SFX modules: 7z.sfx, 7zCon.sfx - standalone versions of console 7-Zip: 7za.exe, 7zr.exe if Z7_EXTERNAL_CODECS is defined, CCodecs class implements interfaces: - ICompressCodecsInfo : for Codecs - IHashers : for Hashers The client application can send CCodecs object to each plugin module. And plugin module can use ICompressCodecsInfo or IHashers interface to access another plugins. There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin 1) for old versions: a) request ISetCompressCodecsInfo from created archive handler. b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo) 2) for new versions: a) request "SetCodecs" function from DLL file b) call SetCodecs(compressCodecsInfo) function from DLL file */ #include "../../../Common/MyBuffer.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/ComTry.h" #ifdef Z7_EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif #include "../../ICoder.h" #include "../../Archive/IArchive.h" #ifdef Z7_EXTERNAL_CODECS struct CDllCodecInfo { unsigned LibIndex; UInt32 CodecIndex; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsFilter; bool IsFilter_Assigned; CLSID Encoder; CLSID Decoder; }; struct CDllHasherInfo { unsigned LibIndex; UInt32 HasherIndex; }; #endif struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { UInt32 Flags; UInt32 TimeFlags; Func_CreateInArchive CreateInArchive; Func_IsArc IsArcFunc; UString Name; CObjectVector Exts; #ifndef Z7_SFX Func_CreateOutArchive CreateOutArchive; bool UpdateEnabled; bool NewInterface; // UInt32 Version; UInt32 SignatureOffset; CObjectVector Signatures; /* #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif */ #endif #ifdef Z7_EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif int Compare(const CArcInfoEx &a) const { const int res = Name.Compare(a.Name); if (res != 0) return res; #ifdef Z7_EXTERNAL_CODECS return MyCompare(LibIndex, a.LibIndex); #else return 0; #endif /* if (LibIndex < a.LibIndex) return -1; if (LibIndex > a.LibIndex) return 1; return 0; */ } bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } bool Flags_NtSecurity() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; } bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; } bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; } bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; } bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; } bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; } bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; } UInt32 Get_TimePrecFlags() const { return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) & (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1); } UInt32 Get_DefaultTimePrec() const { return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) & (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1); } UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const; bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); } bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase("Split"); } bool Is_Xz() const { return Name.IsEqualTo_Ascii_NoCase("xz"); } bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase("bzip2"); } bool Is_GZip() const { return Name.IsEqualTo_Ascii_NoCase("gzip"); } bool Is_Tar() const { return Name.IsEqualTo_Ascii_NoCase("tar"); } bool Is_Zip() const { return Name.IsEqualTo_Ascii_NoCase("zip"); } bool Is_Rar() const { return Name.IsEqualTo_Ascii_NoCase("rar"); } bool Is_Zstd() const { return Name.IsEqualTo_Ascii_NoCase("zstd"); } /* UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s.Add_Space(); s += Exts[i].Ext; } return s; } */ void AddExts(const UString &ext, const UString &addExt); CArcInfoEx(): Flags(0), TimeFlags(0), CreateInArchive(NULL), IsArcFunc(NULL) #ifndef Z7_SFX , CreateOutArchive(NULL) , UpdateEnabled(false) , NewInterface(false) // , Version(0) , SignatureOffset(0) #endif #ifdef Z7_EXTERNAL_CODECS , LibIndex(-1) #endif {} }; #ifdef Z7_EXTERNAL_CODECS struct CCodecLib { NWindows::NDLL::CLibrary Lib; FString Path; Func_CreateObject CreateObject; Func_GetMethodProperty GetMethodProperty; Func_CreateDecoder CreateDecoder; Func_CreateEncoder CreateEncoder; Func_SetCodecs SetCodecs; CMyComPtr ComHashers; UInt32 Version; /* #ifdef NEW_FOLDER_INTERFACE CCodecIcons CodecIcons; void LoadIcons() { CodecIcons.LoadIcons((HMODULE)Lib); } #endif */ CCodecLib(): CreateObject(NULL), GetMethodProperty(NULL), CreateDecoder(NULL), CreateEncoder(NULL), SetCodecs(NULL), Version(0) {} }; #endif struct CCodecError { FString Path; HRESULT ErrorCode; AString Message; CCodecError(): ErrorCode(0) {} }; struct CCodecInfoUser { // unsigned LibIndex; // UInt32 CodecIndex; // UInt64 id; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsFilter; bool IsFilter_Assigned; UInt32 NumStreams; AString Name; }; class CCodecs Z7_final: #ifdef Z7_EXTERNAL_CODECS public ICompressCodecsInfo, public IHashers, #else public IUnknown, #endif public CMyUnknownImp { #ifdef Z7_EXTERNAL_CODECS Z7_IFACES_IMP_UNK_2(ICompressCodecsInfo, IHashers) #else Z7_COM_UNKNOWN_IMP_0 #endif // Z7_EXTERNAL_CODECS Z7_CLASS_NO_COPY(CCodecs) public: #ifdef Z7_EXTERNAL_CODECS CObjectVector Libs; FString MainDll_ErrorPath; CObjectVector Errors; void AddLastError(const FString &path); void CloseLibs(); class CReleaser { Z7_CLASS_NO_COPY(CReleaser) /* CCodecsReleaser object releases CCodecs links. 1) CCodecs is COM object that is deleted when all links to that object will be released/ 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ CCodecs *_codecs; public: CReleaser(): _codecs(NULL) {} void Set(CCodecs *codecs) { _codecs = codecs; } ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } }; bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); HRESULT LoadDllsFromFolder(const FString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const { return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif /* #ifdef NEW_FOLDER_INTERFACE CCodecIcons InternalIcons; #endif */ CObjectVector Formats; #ifdef Z7_EXTERNAL_CODECS CRecordVector Codecs; CRecordVector Hashers; #endif bool CaseSensitive_Change; bool CaseSensitive; CCodecs(): #ifdef Z7_EXTERNAL_CODECS NeedSetLibCodecs(true), #endif CaseSensitive_Change(false), CaseSensitive(false) {} ~CCodecs() { // OutputDebugStringA("~CCodecs"); } const wchar_t *GetFormatNamePtr(int formatIndex) const { return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; } HRESULT Load(); #ifndef Z7_SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif #ifdef Z7_EXTERNAL_CODECS int GetCodec_LibIndex(UInt32 index) const; bool GetCodec_DecoderIsAssigned(UInt32 index) const; bool GetCodec_EncoderIsAssigned(UInt32 index) const; bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const; UInt32 GetCodec_NumStreams(UInt32 index); HRESULT GetCodec_Id(UInt32 index, UInt64 &id); AString GetCodec_Name(UInt32 index); int GetHasherLibIndex(UInt32 index); UInt64 GetHasherId(UInt32 index); AString GetHasherName(UInt32 index); UInt32 GetHasherDigestSize(UInt32 index); void GetCodecsErrorMessage(UString &s); #endif HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef Z7_EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { COM_TRY_BEGIN archive = ai.CreateInArchive(); return S_OK; COM_TRY_END } #ifdef Z7_EXTERNAL_CODECS return CreateArchiveHandler(ai, false, (void **)&archive); #endif } #ifndef Z7_SFX HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef Z7_EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { COM_TRY_BEGIN archive = ai.CreateOutArchive(); return S_OK; COM_TRY_END } #ifdef Z7_EXTERNAL_CODECS return CreateArchiveHandler(ai, true, (void **)&archive); #endif } int FindOutFormatFromName(const UString &name) const { FOR_VECTOR (i, Formats) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.IsEqualTo_NoCase(name)) return (int)i; } return -1; } void Get_CodecsInfoUser_Vector(CObjectVector &v); #endif // Z7_SFX }; #ifdef Z7_EXTERNAL_CODECS #define CREATE_CODECS_OBJECT \ CCodecs *codecs = new CCodecs; \ CExternalCodecs _externalCodecs; \ _externalCodecs.GetCodecs = codecs; \ _externalCodecs.GetHashers = codecs; \ CCodecs::CReleaser codecsReleaser; \ codecsReleaser.Set(codecs); #else #define CREATE_CODECS_OBJECT \ CCodecs *codecs = new CCodecs; \ CMyComPtr _codecsRef = codecs; #endif #endif tmp41wklro_/CPP/7zip/UI/Common/OpenArchive.cpp0000444000175000001440000027744614567042400022156 0ustar nabijaczleweliusers// OpenArchive.cpp #include "StdAfx.h" // #define SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO #include #endif #include "../../../../C/CpuArch.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../../Compress/CopyCoder.h" #include "DefaultName.h" #include "OpenArchive.h" #ifndef Z7_SFX #include "SetProperties.h" #endif #ifndef Z7_SFX #ifdef SHOW_DEBUG_INFO #define PRF(x) x #else #define PRF(x) #endif #endif // increase it, if you need to support larger SFX stubs static const UInt64 kMaxCheckStartPosition = 1 << 23; /* Open: - formatIndex >= 0 (exact Format) 1) Open with main type. Archive handler is allowed to use archive start finder. Warning, if there is tail. - formatIndex = -1 (Parser:0) (default) - same as #1 but doesn't return Parser - formatIndex = -2 (#1) - file has supported extension (like a.7z) Open with that main type (only starting from start of file). - open OK: - if there is no tail - return OK - if there is tail: - archive is not "Self Exe" - return OK with Warning, that there is tail - archive is "Self Exe" ignore "Self Exe" stub, and tries to open tail - tail can be open as archive - shows that archive and stub size property. - tail can't be open as archive - shows Parser ??? - open FAIL: Try to open with all other types from offset 0 only. If some open type is OK and physical archive size is uequal or larger than file size, then return that archive with warning that cannot be open as [extension type]. If extension was EXE, it will try to open as unknown_extension case - file has unknown extension (like a.hhh) It tries to open via parser code. - if there is full archive or tail archive and unknown block or "Self Exe" at front, it shows tail archive and stub size property. - in another cases, if there is some archive inside file, it returns parser/ - in another cases, it retuens S_FALSE - formatIndex = -3 (#2) - same as #1, but - stub (EXE) + archive is open in Parser - formatIndex = -4 (#3) - returns only Parser. skip full file archive. And show other sub-archives - formatIndex = -5 (#4) - returns only Parser. skip full file archive. And show other sub-archives for each byte pos */ using namespace NWindows; /* #ifdef Z7_SFX #define OPEN_PROPS_PARAM #else #define OPEN_PROPS_PARAM , props #endif */ /* CArc::~CArc() { GetRawProps.Release(); Archive.Release(); printf("\nCArc::~CArc()\n"); } */ #ifndef Z7_SFX namespace NArchive { namespace NParser { struct CParseItem { UInt64 Offset; UInt64 Size; // UInt64 OkSize; UString Name; UString Extension; FILETIME FileTime; UString Comment; UString ArcType; bool FileTime_Defined; bool UnpackSize_Defined; bool NumSubDirs_Defined; bool NumSubFiles_Defined; bool IsSelfExe; bool IsNotArcType; UInt64 UnpackSize; UInt64 NumSubDirs; UInt64 NumSubFiles; int FormatIndex; bool LenIsUnknown; CParseItem(): // OkSize(0), FileTime_Defined(false), UnpackSize_Defined(false), NumSubDirs_Defined(false), NumSubFiles_Defined(false), IsSelfExe(false), IsNotArcType(false), LenIsUnknown(false) {} /* bool IsEqualTo(const CParseItem &item) const { return Offset == item.Offset && Size == item.Size; } */ void NormalizeOffset() { if ((Int64)Offset < 0) { Size += Offset; // OkSize += Offset; Offset = 0; } } }; Z7_CLASS_IMP_CHandler_IInArchive_1( IInArchiveGetStream ) public: CObjectVector _items; UInt64 _maxEndOffset; CMyComPtr _stream; UInt64 GetLastEnd() const { if (_items.IsEmpty()) return 0; const CParseItem &back = _items.Back(); return back.Offset + back.Size; } void AddUnknownItem(UInt64 next); int FindInsertPos(const CParseItem &item) const; void AddItem(const CParseItem &item); CHandler(): _maxEndOffset(0) {} }; int CHandler::FindInsertPos(const CParseItem &item) const { unsigned left = 0, right = _items.Size(); while (left != right) { const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const CParseItem &midItem = _items[mid]; if (item.Offset < midItem.Offset) right = mid; else if (item.Offset > midItem.Offset) left = mid + 1; else if (item.Size < midItem.Size) right = mid; /* else if (item.Size > midItem.Size) left = mid + 1; */ else { left = mid + 1; // return -1; } } return (int)left; } void CHandler::AddUnknownItem(UInt64 next) { /* UInt64 prevEnd = 0; if (!_items.IsEmpty()) { const CParseItem &back = _items.Back(); prevEnd = back.Offset + back.Size; } */ if (_maxEndOffset < next) { CParseItem item2; item2.Offset = _maxEndOffset; item2.Size = next - _maxEndOffset; _maxEndOffset = next; _items.Add(item2); } else if (_maxEndOffset > next && !_items.IsEmpty()) { CParseItem &back = _items.Back(); if (back.LenIsUnknown) { back.Size = next - back.Offset; _maxEndOffset = next; } } } void CHandler::AddItem(const CParseItem &item) { AddUnknownItem(item.Offset); const int pos = FindInsertPos(item); if (pos != -1) { _items.Insert((unsigned)pos, item); UInt64 next = item.Offset + item.Size; if (_maxEndOffset < next) _maxEndOffset = next; } } /* static const CStatProp kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidType, VT_BSTR}, { NULL, kpidComment, VT_BSTR}, { NULL, kpidOffset, VT_UI8}, { NULL, kpidUnpackSize, VT_UI8}, // { NULL, kpidNumSubDirs, VT_UI8}, }; */ static const Byte kProps[] = { kpidPath, kpidSize, kpidMTime, kpidType, kpidComment, kpidOffset, kpidUnpackSize }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */)) { COM_TRY_BEGIN { Close(); _stream = stream; } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CHandler::Close()) { _items.Clear(); _stream.Release(); return S_OK; } Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) { *numItems = _items.Size(); return S_OK; } Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN NCOM::CPropVariant prop; const CParseItem &item = _items[index]; switch (propID) { case kpidPath: { char sz[32]; ConvertUInt32ToString(index + 1, sz); UString s(sz); if (!item.Name.IsEmpty()) { s.Add_Dot(); s += item.Name; } if (!item.Extension.IsEmpty()) { s.Add_Dot(); s += item.Extension; } prop = s; break; } case kpidSize: case kpidPackSize: prop = item.Size; break; case kpidOffset: prop = item.Offset; break; case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break; case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break; case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break; case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break; case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break; case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break; default: break; } prop.Detach(value); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) { COM_TRY_BEGIN const bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); if (_stream && numItems == 0) return S_OK; UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) totalSize += _items[allFilesMode ? i : indices[i]].Size; extractCallback->SetTotal(totalSize); totalSize = 0; CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(extractCallback, false); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr inStream(streamSpec); streamSpec->SetStream(_stream); CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; CMyComPtr outStream(outStreamSpec); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr copyCoder = copyCoderSpec; for (i = 0; i < numItems; i++) { lps->InSize = totalSize; lps->OutSize = totalSize; RINOK(lps->SetCur()) CMyComPtr realOutStream; const Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; const UInt32 index = allFilesMode ? i : indices[i]; const CParseItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) UInt64 unpackSize = item.Size; totalSize += unpackSize; bool skipMode = false; if (!testMode && !realOutStream) continue; RINOK(extractCallback->PrepareOperation(askMode)) outStreamSpec->SetStream(realOutStream); realOutStream.Release(); outStreamSpec->Init(skipMode ? 0 : unpackSize, true); Int32 opRes = NExtract::NOperationResult::kOK; RINOK(InStream_SeekSet(_stream, item.Offset)) streamSpec->Init(unpackSize); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) if (outStreamSpec->GetRem() != 0) opRes = NExtract::NOperationResult::kDataError; outStreamSpec->ReleaseStream(); RINOK(extractCallback->SetOperationResult(opRes)) } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) { COM_TRY_BEGIN const CParseItem &item = _items[index]; return CreateLimitedInStream(_stream, item.Offset, item.Size, stream); COM_TRY_END } }} #endif HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw() { NCOM::CPropVariant prop; result = false; RINOK(arc->GetProperty(index, propID, &prop)) if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw() { return Archive_GetItemBoolProp(arc, index, kpidIsDir, result); } HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw() { return Archive_GetItemBoolProp(arc, index, kpidIsAux, result); } HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw() { return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result); } HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw() { return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); } static HRESULT Archive_GetArcProp_Bool(IInArchive *arc, PROPID propid, bool &result) throw() { NCOM::CPropVariant prop; result = false; RINOK(arc->GetArchiveProperty(propid, &prop)) if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined) { defined = false; NCOM::CPropVariant prop; RINOK(arc->GetArchiveProperty(propid, &prop)) switch (prop.vt) { case VT_UI4: result = prop.ulVal; break; case VT_I4: result = (UInt64)(Int64)prop.lVal; break; case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; break; case VT_I8: result = (UInt64)prop.hVal.QuadPart; break; case VT_EMPTY: return S_OK; default: return E_FAIL; } defined = true; return S_OK; } static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined) { defined = false; NCOM::CPropVariant prop; RINOK(arc->GetArchiveProperty(propid, &prop)) switch (prop.vt) { case VT_UI4: result = prop.ulVal; break; case VT_I4: result = prop.lVal; break; case VT_UI8: result = (Int64)prop.uhVal.QuadPart; break; case VT_I8: result = (Int64)prop.hVal.QuadPart; break; case VT_EMPTY: return S_OK; default: return E_FAIL; } defined = true; return S_OK; } #ifndef Z7_SFX HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const { if (!GetRawProps) return E_FAIL; if (index == parent) return S_OK; UInt32 curIndex = index; UString s; bool prevWasAltStream = false; for (;;) { #ifdef MY_CPU_LE const void *p; UInt32 size; UInt32 propType; RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType)) if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) s = (const wchar_t *)p; else #endif { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(curIndex, kpidName, &prop)) if (prop.vt == VT_BSTR && prop.bstrVal) s.SetFromBstr(prop.bstrVal); else if (prop.vt == VT_EMPTY) s.Empty(); else return E_FAIL; } UInt32 curParent = (UInt32)(Int32)-1; UInt32 parentType = 0; RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)) // 18.06: fixed : we don't want to split name to parts /* if (parentType != NParentType::kAltStream) { for (;;) { int pos = s.ReverseFind_PathSepar(); if (pos < 0) { break; } parts.Insert(0, s.Ptr(pos + 1)); s.DeleteFrom(pos); } } */ parts.Insert(0, s); if (prevWasAltStream) { { UString &s2 = parts[parts.Size() - 2]; s2.Add_Colon(); s2 += parts.Back(); } parts.DeleteBack(); } if (parent == curParent) return S_OK; prevWasAltStream = false; if (parentType == NParentType::kAltStream) prevWasAltStream = true; if (curParent == (UInt32)(Int32)-1) return E_FAIL; curIndex = curParent; } } #endif HRESULT CArc::GetItem_Path(UInt32 index, UString &result) const { #ifdef MY_CPU_LE if (GetRawProps) { const void *p; UInt32 size; UInt32 propType; if (!IsTree) { if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK && propType == NPropDataType::kUtf16z) { unsigned len = size / 2 - 1; // (len) doesn't include null terminator /* #if WCHAR_MAX > 0xffff len = (unsigned)Utf16LE__Get_Num_WCHARs(p, len); wchar_t *s = result.GetBuf(len); wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, len, s); if (s + len != sEnd) return E_FAIL; *sEnd = 0; #else */ wchar_t *s = result.GetBuf(len); for (unsigned i = 0; i < len; i++) { wchar_t c = GetUi16(p); p = (const void *)((const Byte *)p + 2); #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; else if (c == L'\\') c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif *s++ = c; } *s = 0; // #endif result.ReleaseBuf_SetLen(len); Convert_UnicodeEsc16_To_UnicodeEscHigh(result); if (len != 0) return S_OK; } } /* else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK && p && propType == NPropDataType::kUtf16z) { size -= 2; UInt32 totalSize = size; bool isOK = false; { UInt32 index2 = index; for (;;) { UInt32 parent = (UInt32)(Int32)-1; UInt32 parentType = 0; if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) break; if (parent == (UInt32)(Int32)-1) { if (parentType != 0) totalSize += 2; isOK = true; break; } index2 = parent; UInt32 size2; const void *p2; if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK && p2 && propType == NPropDataType::kUtf16z) break; totalSize += size2; } } if (isOK) { wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2); UInt32 pos = totalSize - size; memcpy((Byte *)sz + pos, p, size); UInt32 index2 = index; for (;;) { UInt32 parent = (UInt32)(Int32)-1; UInt32 parentType = 0; if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) break; if (parent == (UInt32)(Int32)-1) { if (parentType != 0) sz[pos / 2 - 1] = L':'; break; } index2 = parent; UInt32 size2; const void *p2; if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) break; pos -= size2; memcpy((Byte *)sz + pos, p2, size2); sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':'; } #ifdef _WIN32 // result.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif return S_OK; } } */ } #endif { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidPath, &prop)) if (prop.vt == VT_BSTR && prop.bstrVal) result.SetFromBstr(prop.bstrVal); else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; } if (result.IsEmpty()) return GetItem_DefaultPath(index, result); Convert_UnicodeEsc16_To_UnicodeEscHigh(result); return S_OK; } HRESULT CArc::GetItem_DefaultPath(UInt32 index, UString &result) const { result.Empty(); bool isDir; RINOK(Archive_IsItem_Dir(Archive, index, isDir)) if (!isDir) { result = DefaultName; NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidExtension, &prop)) if (prop.vt == VT_BSTR) { result.Add_Dot(); result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT CArc::GetItem_Path2(UInt32 index, UString &result) const { RINOK(GetItem_Path(index, result)) if (Ask_Deleted) { bool isDeleted = false; RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted)) if (isDeleted) result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); } return S_OK; } #ifdef SUPPORT_ALT_STREAMS int FindAltStreamColon_in_Path(const wchar_t *path) { unsigned i = 0; int colonPos = -1; for (;; i++) { wchar_t c = path[i]; if (c == 0) return colonPos; if (c == ':') { if (colonPos < 0) colonPos = (int)i; continue; } if (c == WCHAR_PATH_SEPARATOR) colonPos = -1; } } #endif HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const { #ifdef SUPPORT_ALT_STREAMS item.IsAltStream = false; item.AltStreamName.Empty(); item.MainPath.Empty(); #endif item.IsDir = false; item.Path.Empty(); item.ParentIndex = (UInt32)(Int32)-1; item.PathParts.Clear(); RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir)) item.MainIsDir = item.IsDir; RINOK(GetItem_Path2(index, item.Path)) #ifndef Z7_SFX UInt32 mainIndex = index; #endif #ifdef SUPPORT_ALT_STREAMS item.MainPath = item.Path; if (Ask_AltStream) { RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream)) } bool needFindAltStream = false; if (item.IsAltStream) { needFindAltStream = true; if (GetRawProps) { UInt32 parentType = 0; UInt32 parentIndex; RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType)) if (parentType == NParentType::kAltStream) { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidName, &prop)) if (prop.vt == VT_BSTR && prop.bstrVal) item.AltStreamName.SetFromBstr(prop.bstrVal); else if (prop.vt != VT_EMPTY) return E_FAIL; else { // item.IsAltStream = false; } /* if (item.AltStreamName.IsEmpty()) item.IsAltStream = false; */ needFindAltStream = false; item.ParentIndex = parentIndex; mainIndex = parentIndex; if (parentIndex == (UInt32)(Int32)-1) { item.MainPath.Empty(); item.MainIsDir = true; } else { RINOK(GetItem_Path2(parentIndex, item.MainPath)) RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir)) } } } } if (item.WriteToAltStreamIfColon || needFindAltStream) { /* Good handler must support GetRawProps::GetParent for alt streams. So the following code currently is not used */ int colon = FindAltStreamColon_in_Path(item.Path); if (colon >= 0) { item.MainPath.DeleteFrom((unsigned)colon); item.AltStreamName = item.Path.Ptr((unsigned)(colon + 1)); item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1])); item.IsAltStream = true; } } #endif #ifndef Z7_SFX if (item._use_baseParentFolder_mode) { RINOK(GetItem_PathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts)) #ifdef SUPPORT_ALT_STREAMS if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty()) { int colon; { UString &s = item.PathParts.Back(); colon = FindAltStreamColon_in_Path(s); if (colon >= 0) { item.AltStreamName = s.Ptr((unsigned)(colon + 1)); item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1])); item.IsAltStream = true; s.DeleteFrom((unsigned)colon); } } if (colon == 0) item.PathParts.DeleteBack(); } #endif } else #endif SplitPathToParts( #ifdef SUPPORT_ALT_STREAMS item.MainPath #else item.Path #endif , item.PathParts); return S_OK; } #ifndef Z7_SFX static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined) { NCOM::CPropVariant prop; defined = false; size = 0; RINOK(archive->GetProperty(index, kpidSize, &prop)) switch (prop.vt) { case VT_UI1: size = prop.bVal; break; case VT_UI2: size = prop.uiVal; break; case VT_UI4: size = prop.ulVal; break; case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; case VT_EMPTY: return S_OK; default: return E_FAIL; } defined = true; return S_OK; } #endif HRESULT CArc::GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const { NCOM::CPropVariant prop; defined = false; size = 0; RINOK(Archive->GetProperty(index, kpidSize, &prop)) switch (prop.vt) { case VT_UI1: size = prop.bVal; break; case VT_UI2: size = prop.uiVal; break; case VT_UI4: size = prop.ulVal; break; case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; case VT_EMPTY: return S_OK; default: return E_FAIL; } defined = true; return S_OK; } HRESULT CArc::GetItem_MTime(UInt32 index, CArcTime &at) const { at.Clear(); NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidMTime, &prop)) if (prop.vt == VT_FILETIME) { /* // for debug if (FILETIME_IsZero(prop.at) && MTime.Def) { at = MTime; return S_OK; } */ at.Set_From_Prop(prop); if (at.Prec == 0) { // (at.Prec == 0) before version 22. // so kpidTimeType is required for that code prop.Clear(); RINOK(Archive->GetProperty(index, kpidTimeType, &prop)) if (prop.vt == VT_UI4) { UInt32 val = prop.ulVal; if (val == NFileTimeType::kWindows) val = k_PropVar_TimePrec_100ns; /* else if (val > k_PropVar_TimePrec_1ns) { val = k_PropVar_TimePrec_100ns; // val = k_PropVar_TimePrec_1ns; // return E_FAIL; // for debug } */ at.Prec = (UInt16)val; } } return S_OK; } if (prop.vt != VT_EMPTY) return E_FAIL; if (MTime.Def) at = MTime; return S_OK; } #ifndef Z7_SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } static void MakeCheckOrder(CCodecs *codecs, CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2, const Byte *data, size_t dataSize) { for (unsigned i = 0; i < numTypes; i++) { const int index = orderIndices[i]; if (index < 0) continue; const CArcInfoEx &ai = codecs->Formats[(unsigned)index]; if (ai.SignatureOffset == 0) { if (ai.Signatures.IsEmpty()) { if (dataSize != 0) // 21.04: no Signature means Empty Signature continue; } else { unsigned k; const CObjectVector &sigs = ai.Signatures; for (k = 0; k < sigs.Size(); k++) { const CByteBuffer &sig = sigs[k]; if (sig.Size() <= dataSize && TestSignature(data, sig, sig.Size())) break; } if (k == sigs.Size()) continue; } } orderIndices2.Add(index); orderIndices[i] = -1; } } #ifdef UNDER_CE static const unsigned kNumHashBytes = 1; #define HASH_VAL(buf) ((buf)[0]) #else static const unsigned kNumHashBytes = 2; // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8)) #define HASH_VAL(buf) GetUi16(buf) #endif static bool IsExeExt(const UString &ext) { return ext.IsEqualTo_Ascii_NoCase("exe"); } static const char * const k_PreArcFormats[] = { "pe" , "elf" , "macho" , "mub" , "te" }; static bool IsNameFromList(const UString &s, const char * const names[], size_t num) { for (unsigned i = 0; i < num; i++) if (StringsAreEqualNoCase_Ascii(s, names[i])) return true; return false; } static bool IsPreArcFormat(const CArcInfoEx &ai) { if (ai.Flags_PreArc()) return true; return IsNameFromList(ai.Name, k_PreArcFormats, Z7_ARRAY_SIZE(k_PreArcFormats)); } static const char * const k_Formats_with_simple_signuature[] = { "7z" , "xz" , "rar" , "bzip2" , "gzip" , "cab" , "wim" , "rpm" , "vhd" , "xar" }; static bool IsNewStyleSignature(const CArcInfoEx &ai) { // if (ai.Version >= 0x91F) if (ai.NewInterface) return true; return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, Z7_ARRAY_SIZE(k_Formats_with_simple_signuature)); } class CArchiveOpenCallback_Offset Z7_final: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, #ifndef Z7_NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(IArchiveOpenCallback) Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback) #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY(ICryptoGetTextPassword) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IArchiveOpenCallback) Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback) #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) #endif public: CMyComPtr Callback; CMyComPtr OpenVolumeCallback; UInt64 Files; UInt64 Offset; #ifndef Z7_NO_CRYPTO CMyComPtr GetTextPassword; #endif }; #ifndef Z7_NO_CRYPTO Z7_COM7F_IMF(CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)) { COM_TRY_BEGIN if (GetTextPassword) return GetTextPassword->CryptoGetTextPassword(password); return E_NOTIMPL; COM_TRY_END } #endif Z7_COM7F_IMF(CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)) { return S_OK; } Z7_COM7F_IMF(CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)) { if (!Callback) return S_OK; UInt64 value = Offset; if (bytes) value += *bytes; return Callback->SetCompleted(&Files, &value); } Z7_COM7F_IMF(CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value)) { if (OpenVolumeCallback) return OpenVolumeCallback->GetProperty(propID, value); NCOM::PropVariant_Clear(value); return S_OK; // return E_NOTIMPL; } Z7_COM7F_IMF(CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream)) { if (OpenVolumeCallback) return OpenVolumeCallback->GetStream(name, inStream); return S_FALSE; } #endif UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp) { if (isDefinedProp != NULL) *isDefinedProp = false; switch (prop.vt) { case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart; case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal; case VT_EMPTY: return 0; default: throw 151199; } } void CArcErrorInfo::ClearErrors() { // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!! ThereIsTail = false; UnexpecedEnd = false; IgnoreTail = false; // NonZerosTail = false; ErrorFlags_Defined = false; ErrorFlags = 0; WarningFlags = 0; TailSize = 0; ErrorMessage.Empty(); WarningMessage.Empty(); } HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) { // OkPhySize_Defined = false; PhySize_Defined = false; PhySize = 0; Offset = 0; AvailPhySize = FileSize - startPos; ErrorInfo.ClearErrors(); { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop)) ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined); } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop)) ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop); } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidError, &prop)) if (prop.vt != VT_EMPTY) ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error"); } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidWarning, &prop)) if (prop.vt != VT_EMPTY) ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning"); } if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) { RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySize_Defined)) /* RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined)); if (!OkPhySize_Defined) { OkPhySize_Defined = PhySize_Defined; OkPhySize = PhySize; } */ bool offsetDefined; RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined)) Int64 globalOffset = (Int64)startPos + Offset; AvailPhySize = (UInt64)((Int64)FileSize - globalOffset); if (PhySize_Defined) { UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize); if (endPos < FileSize) { AvailPhySize = PhySize; ErrorInfo.ThereIsTail = true; ErrorInfo.TailSize = FileSize - endPos; } else if (endPos > FileSize) ErrorInfo.UnexpecedEnd = true; } } return S_OK; } /* static void PrintNumber(const char *s, int n) { char temp[100]; sprintf(temp, "%s %d", s, n); // OutputDebugStringA(temp); printf(temp); } */ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive) { // OutputDebugStringA("a1"); // PrintNumber("formatIndex", formatIndex); RINOK(op.codecs->CreateInArchive(formatIndex, archive)) // OutputDebugStringA("a2"); if (!archive) return S_OK; #ifdef Z7_EXTERNAL_CODECS if (op.codecs->NeedSetLibCodecs) { const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; if (ai.LibIndex >= 0 ? !op.codecs->Libs[(unsigned)ai.LibIndex].SetCodecs : !op.codecs->Libs.IsEmpty()) { CMyComPtr setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)) } } } #endif #ifndef Z7_SFX const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; // OutputDebugStringW(ai.Name); // OutputDebugStringA("a3"); if (ai.Flags_PreArc()) { /* we notify parsers that extract executables, that they don't need to open archive, if there is tail after executable (for SFX cases) */ CMyComPtr allowTail; archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail); if (allowTail) allowTail->AllowTail(BoolToInt(true)); } if (op.props) { /* FOR_VECTOR (y, op.props) { const COptionalOpenProperties &optProps = (*op.props)[y]; if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0) { RINOK(SetProperties(archive, optProps.Props)); break; } } */ RINOK(SetProperties(archive, *op.props)) } #endif return S_OK; } #ifndef Z7_SFX static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi) { pi.Extension = ai.GetMainExt(); pi.FileTime_Defined = false; pi.ArcType = ai.Name; RINOK(Archive_GetArcProp_Bool(archive, kpidIsNotArcType, pi.IsNotArcType)) // RINOK(Archive_GetArcProp_Bool(archive, kpidIsSelfExe, pi.IsSelfExe)); pi.IsSelfExe = ai.Flags_PreArc(); { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidMTime, &prop)) if (prop.vt == VT_FILETIME) { pi.FileTime_Defined = true; pi.FileTime = prop.filetime; } } if (!pi.FileTime_Defined) { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidCTime, &prop)) if (prop.vt == VT_FILETIME) { pi.FileTime_Defined = true; pi.FileTime = prop.filetime; } } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidName, &prop)) if (prop.vt == VT_BSTR) { pi.Name.SetFromBstr(prop.bstrVal); pi.Extension.Empty(); } else { RINOK(archive->GetArchiveProperty(kpidExtension, &prop)) if (prop.vt == VT_BSTR) pi.Extension.SetFromBstr(prop.bstrVal); } } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidShortComment, &prop)) if (prop.vt == VT_BSTR) pi.Comment.SetFromBstr(prop.bstrVal); } UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) // pi.NumSubFiles = numItems; // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined)); // if (!pi.UnpackSize_Defined) { pi.NumSubFiles = 0; pi.NumSubDirs = 0; pi.UnpackSize = 0; for (UInt32 i = 0; i < numItems; i++) { UInt64 size = 0; bool defined = false; Archive_GetItem_Size(archive, i, size, defined); if (defined) { pi.UnpackSize_Defined = true; pi.UnpackSize += size; } bool isDir = false; Archive_IsItem_Dir(archive, i, isDir); if (isDir) pi.NumSubDirs++; else pi.NumSubFiles++; } if (pi.NumSubDirs != 0) pi.NumSubDirs_Defined = true; pi.NumSubFiles_Defined = true; } return S_OK; } #endif HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) { if (!op.stream) return S_OK; RINOK(InStream_SeekSet(op.stream, offset)) const UInt32 kBufSize = 1 << 11; Byte buf[kBufSize]; for (;;) { UInt32 processed = 0; RINOK(op.stream->Read(buf, kBufSize, &processed)) if (processed == 0) { // ErrorInfo.NonZerosTail = false; ErrorInfo.IgnoreTail = true; return S_OK; } for (size_t i = 0; i < processed; i++) { if (buf[i] != 0) { // ErrorInfo.IgnoreTail = false; // ErrorInfo.NonZerosTail = true; return S_OK; } } } } #ifndef Z7_SFX Z7_CLASS_IMP_COM_2( CExtractCallback_To_OpenCallback , IArchiveExtractCallback , ICompressProgressInfo ) Z7_IFACE_COM7_IMP(IProgress) public: CMyComPtr Callback; UInt64 Files; UInt64 Offset; void Init(IArchiveOpenCallback *callback) { Callback = callback; Files = 0; Offset = 0; } }; Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */)) { return S_OK; } Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */)) { return S_OK; } Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)) { if (Callback) { UInt64 value = Offset; if (inSize) value += *inSize; return Callback->SetCompleted(&Files, &value); } return S_OK; } Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */)) { *outStream = NULL; return S_OK; } Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */)) { return S_OK; } Z7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */)) { return S_OK; } static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback, IArchiveExtractCallback *extractCallback) { /* if (needPhySize) { Z7_DECL_CMyComPtr_QI_FROM( IArchiveOpen2, open2, archive) if (open2) return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback); } */ RINOK(archive->Open(stream, maxCheckStartPosition, openCallback)) if (needPhySize) { bool phySize_Defined = false; UInt64 phySize = 0; RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined)) if (phySize_Defined) return S_OK; bool phySizeCantBeDetected = false; RINOK(Archive_GetArcProp_Bool(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)) if (!phySizeCantBeDetected) { PRF(printf("\n-- !phySize_Defined after Open, call archive->Extract()")); // It's for bzip2/gz and some xz archives, where Open operation doesn't know phySize. // But the Handler will know phySize after full archive testing. RINOK(archive->Extract(NULL, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)) PRF(printf("\n-- OK")); } } return S_OK; } static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name) { FOR_VECTOR (i, orderIndices) { int oi = orderIndices[i]; if (oi >= 0) if (StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)oi].Name, name)) return (int)i; } return -1; } #endif HRESULT CArc::OpenStream2(const COpenOptions &op) { // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout); Archive.Release(); GetRawProps.Release(); GetRootProps.Release(); ErrorInfo.ClearErrors(); ErrorInfo.ErrorFormatIndex = -1; IsParseArc = false; ArcStreamOffset = 0; // OutputDebugStringA("1"); // OutputDebugStringW(Path); const UString fileName = ExtractFileNameFromPath(Path); UString extension; { const int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) extension = fileName.Ptr((unsigned)(dotPos + 1)); } CIntVector orderIndices; bool searchMarkerInHandler = false; #ifdef Z7_SFX searchMarkerInHandler = true; #endif CBoolArr isMainFormatArr(op.codecs->Formats.Size()); { FOR_VECTOR(i, op.codecs->Formats) isMainFormatArr[i] = false; } const UInt64 maxStartOffset = op.openType.MaxStartOffset_Defined ? op.openType.MaxStartOffset : kMaxCheckStartPosition; #ifndef Z7_SFX bool isUnknownExt = false; #endif #ifndef Z7_SFX bool isForced = false; #endif unsigned numMainTypes = 0; const int formatIndex = op.openType.FormatIndex; if (formatIndex >= 0) { #ifndef Z7_SFX isForced = true; #endif orderIndices.Add(formatIndex); numMainTypes = 1; isMainFormatArr[(unsigned)formatIndex] = true; searchMarkerInHandler = true; } else { unsigned numFinded = 0; #ifndef Z7_SFX bool isPrearcExt = false; #endif { #ifndef Z7_SFX bool isZip = false; bool isRar = false; const wchar_t c = extension[0]; if (c == 'z' || c == 'Z' || c == 'r' || c == 'R') { bool isNumber = false; for (unsigned k = 1;; k++) { const wchar_t d = extension[k]; if (d == 0) break; if (d < '0' || d > '9') { isNumber = false; break; } isNumber = true; } if (isNumber) { if (c == 'z' || c == 'Z') isZip = true; else isRar = true; } } #endif FOR_VECTOR (i, op.codecs->Formats) { const CArcInfoEx &ai = op.codecs->Formats[i]; if (IgnoreSplit || !op.openType.CanReturnArc) if (ai.Is_Split()) continue; if (op.excludedFormats->FindInSorted((int)i) >= 0) continue; #ifndef Z7_SFX if (IsPreArcFormat(ai)) isPrearcExt = true; #endif if (ai.FindExtension(extension) >= 0 #ifndef Z7_SFX || (isZip && ai.Is_Zip()) || (isRar && ai.Is_Rar()) #endif ) { // PrintNumber("orderIndices.Insert", i); orderIndices.Insert(numFinded++, (int)i); isMainFormatArr[i] = true; } else orderIndices.Add((int)i); } } if (!op.stream) { if (numFinded != 1) return E_NOTIMPL; orderIndices.DeleteFrom(1); } // PrintNumber("numFinded", numFinded ); /* if (op.openOnlySpecifiedByExtension) { if (numFinded != 0 && !IsExeExt(extension)) orderIndices.DeleteFrom(numFinded); } */ #ifndef Z7_SFX if (op.stream && orderIndices.Size() >= 2) { RINOK(InStream_SeekToBegin(op.stream)) CByteBuffer byteBuffer; CIntVector orderIndices2; if (numFinded == 0 || IsExeExt(extension)) { // signature search was here } else if (extension.IsEqualTo("000") || extension.IsEqualTo("001")) { const int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar"); if (i >= 0) { const size_t kBufSize = (1 << 10); byteBuffer.Alloc(kBufSize); size_t processedSize = kBufSize; RINOK(ReadStream(op.stream, byteBuffer, &processedSize)) if (processedSize >= 16) { const Byte *buf = byteBuffer; const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }; if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0) { orderIndices2.Add(orderIndices[(unsigned)i]); orderIndices[(unsigned)i] = -1; if (i >= (int)numFinded) numFinded++; } } } } else { const size_t kBufSize = (1 << 10); byteBuffer.Alloc(kBufSize); size_t processedSize = kBufSize; RINOK(ReadStream(op.stream, byteBuffer, &processedSize)) if (processedSize == 0) return S_FALSE; /* check type order: 0) matched_extension && Backward 1) matched_extension && (no_signuature || SignatureOffset != 0) 2) matched_extension && (matched_signature) // 3) no signuature // 4) matched signuature */ // we move index from orderIndices to orderIndices2 for priority handlers. for (unsigned i = 0; i < numFinded; i++) { const int index = orderIndices[i]; if (index < 0) continue; const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index]; if (ai.Flags_BackwardOpen()) { // backward doesn't need start signatures orderIndices2.Add(index); orderIndices[i] = -1; } } MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0); MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize); // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0); // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize); } FOR_VECTOR (i, orderIndices) { const int val = orderIndices[i]; if (val != -1) orderIndices2.Add(val); } orderIndices = orderIndices2; } if (orderIndices.Size() >= 2) { const int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso"); const int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf"); if (iUdf > iIso && iIso >= 0) { const int isoIndex = orderIndices[(unsigned)iIso]; const int udfIndex = orderIndices[(unsigned)iUdf]; orderIndices[(unsigned)iUdf] = isoIndex; orderIndices[(unsigned)iIso] = udfIndex; } } numMainTypes = numFinded; isUnknownExt = (numMainTypes == 0) || isPrearcExt; #else // Z7_SFX numMainTypes = orderIndices.Size(); // we need correct numMainTypes for mutlivolume SFX (if some volume is missing) if (numFinded != 0) numMainTypes = numFinded; #endif } UInt64 fileSize = 0; if (op.stream) { RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize)) } FileSize = fileSize; #ifndef Z7_SFX CBoolArr skipFrontalFormat(op.codecs->Formats.Size()); { FOR_VECTOR(i, op.codecs->Formats) skipFrontalFormat[i] = false; } #endif const COpenType &mode = op.openType; if (mode.CanReturnArc) { // ---------- OPEN main type by extenssion ---------- unsigned numCheckTypes = orderIndices.Size(); if (formatIndex >= 0) numCheckTypes = numMainTypes; for (unsigned i = 0; i < numCheckTypes; i++) { FormatIndex = orderIndices[i]; // orderIndices[] item cannot be negative here bool exactOnly = false; #ifndef Z7_SFX const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; // OutputDebugStringW(ai.Name); if (i >= numMainTypes) { // here we allow mismatched extension only for backward handlers if (!ai.Flags_BackwardOpen() // && !ai.Flags_PureStartOpen() ) continue; exactOnly = true; } #endif // Some handlers do not set total bytes. So we set it here if (op.callback) RINOK(op.callback->SetTotal(NULL, &fileSize)) if (op.stream) { RINOK(InStream_SeekToBegin(op.stream)) } CMyComPtr archive; RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)) if (!archive) continue; HRESULT result; if (op.stream) { UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0; result = archive->Open(op.stream, &searchLimit, op.callback); } else { CMyComPtr openSeq; archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); if (!openSeq) return E_NOTIMPL; result = openSeq->OpenSeq(op.seqStream); } RINOK(ReadBasicProps(archive, 0, result)) if (result == S_FALSE) { bool isArc = ErrorInfo.IsArc_After_NonOpen(); #ifndef Z7_SFX // if it's archive, we allow another open attempt for parser if (!mode.CanReturnParser || !isArc) skipFrontalFormat[(unsigned)FormatIndex] = true; #endif if (exactOnly) continue; if (i == 0 && numMainTypes == 1) { // we set NonOpenErrorInfo, only if there is only one main format (defined by extension). ErrorInfo.ErrorFormatIndex = FormatIndex; NonOpen_ErrorInfo = ErrorInfo; if (!mode.CanReturnParser && isArc) { // if (formatIndex < 0 && !searchMarkerInHandler) { // if bad archive was detected, we don't need additional open attempts #ifndef Z7_SFX if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */) #endif return S_FALSE; } } } /* #ifndef Z7_SFX if (IsExeExt(extension) || ai.Flags_PreArc()) { // openOnlyFullArc = false; // canReturnTailArc = true; // limitSignatureSearch = true; } #endif */ continue; } RINOK(result) #ifndef Z7_SFX bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); bool thereIsTail = ErrorInfo.ThereIsTail; if (thereIsTail && mode.ZerosTailIsAllowed) { RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))) if (ErrorInfo.IgnoreTail) thereIsTail = false; } if (Offset > 0) { if (exactOnly || !searchMarkerInHandler || !specFlags.CanReturn_NonStart() || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset)) continue; } if (thereIsTail) { if (Offset > 0) { if (!specFlags.CanReturnMid) continue; } else if (!specFlags.CanReturnFrontal) continue; } if (Offset > 0 || thereIsTail) { if (formatIndex < 0) { if (IsPreArcFormat(ai)) { // openOnlyFullArc = false; // canReturnTailArc = true; /* if (mode.SkipSfxStub) limitSignatureSearch = true; */ // if (mode.SkipSfxStub) { // skipFrontalFormat[FormatIndex] = true; continue; } } } } #endif Archive = archive; return S_OK; } } #ifndef Z7_SFX if (!op.stream) return S_FALSE; if (formatIndex >= 0 && !mode.CanReturnParser) { if (mode.MaxStartOffset_Defined) { if (mode.MaxStartOffset == 0) return S_FALSE; } else { const CArcInfoEx &ai = op.codecs->Formats[(unsigned)formatIndex]; if (ai.FindExtension(extension) >= 0) { if (ai.Flags_FindSignature() && searchMarkerInHandler) return S_FALSE; } } } NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler; CMyComPtr handler = handlerSpec; CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback; CMyComPtr extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec; extractCallback_To_OpenCallback_Spec->Init(op.callback); { // ---------- Check all possible START archives ---------- // this code is better for full file archives than Parser's code. CByteBuffer byteBuffer; bool endOfFile = false; size_t processedSize; { size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF) if (bufSize > fileSize) { bufSize = (size_t)fileSize; endOfFile = true; } byteBuffer.Alloc(bufSize); RINOK(InStream_SeekToBegin(op.stream)) processedSize = bufSize; RINOK(ReadStream(op.stream, byteBuffer, &processedSize)) if (processedSize == 0) return S_FALSE; if (processedSize < bufSize) endOfFile = true; } CUIntVector sortedFormats; unsigned i; int splitIndex = -1; for (i = 0; i < orderIndices.Size(); i++) { // orderIndices[] item cannot be negative here unsigned form = (unsigned)orderIndices[i]; if (skipFrontalFormat[form]) continue; const CArcInfoEx &ai = op.codecs->Formats[form]; if (ai.Is_Split()) { splitIndex = (int)form; continue; } if (ai.Flags_ByExtOnlyOpen()) continue; if (ai.IsArcFunc) { UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize); if (isArcRes == k_IsArc_Res_NO) continue; if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) continue; // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue; sortedFormats.Insert(0, form); continue; } const bool isNewStyleSignature = IsNewStyleSignature(ai); bool needCheck = !isNewStyleSignature || ai.Signatures.IsEmpty() || ai.Flags_PureStartOpen() || ai.Flags_StartOpen() || ai.Flags_BackwardOpen(); if (isNewStyleSignature && !ai.Signatures.IsEmpty()) { unsigned k; for (k = 0; k < ai.Signatures.Size(); k++) { const CByteBuffer &sig = ai.Signatures[k]; if (processedSize < ai.SignatureOffset + sig.Size()) { if (!endOfFile) needCheck = true; } else if (TestSignature(sig, byteBuffer + ai.SignatureOffset, sig.Size())) break; } if (k != ai.Signatures.Size()) { sortedFormats.Insert(0, form); continue; } } if (needCheck) sortedFormats.Add(form); } if (splitIndex >= 0) sortedFormats.Insert(0, (unsigned)splitIndex); for (i = 0; i < sortedFormats.Size(); i++) { FormatIndex = (int)sortedFormats[i]; const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; if (op.callback) RINOK(op.callback->SetTotal(NULL, &fileSize)) RINOK(InStream_SeekToBegin(op.stream)) CMyComPtr archive; RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)) if (!archive) continue; PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name)); HRESULT result; { UInt64 searchLimit = 0; /* if (mode.CanReturnArc) result = archive->Open(op.stream, &searchLimit, op.callback); else */ // if (!CanReturnArc), it's ParserMode, and we need phy size result = OpenArchiveSpec(archive, !mode.CanReturnArc, // needPhySize op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); } if (result == S_FALSE) { skipFrontalFormat[(unsigned)FormatIndex] = true; // FIXME: maybe we must use LenIsUnknown. // printf(" OpenForSize Error"); continue; } RINOK(result) RINOK(ReadBasicProps(archive, 0, result)) if (Offset > 0) { continue; // good handler doesn't return such Offset > 0 // but there are some cases like false prefixed PK00 archive, when // we can support it? } NArchive::NParser::CParseItem pi; pi.Offset = (UInt64)Offset; pi.Size = AvailPhySize; // bool needScan = false; if (!PhySize_Defined) { // it's for Z format pi.LenIsUnknown = true; // needScan = true; // phySize = arcRem; // nextNeedCheckStartOpen = false; } /* if (OkPhySize_Defined) pi.OkSize = pi.OkPhySize; else pi.OkSize = pi.Size; */ pi.NormalizeOffset(); // printf(" phySize = %8d", (unsigned)phySize); if (mode.CanReturnArc) { const bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); bool openCur = false; if (!ErrorInfo.ThereIsTail) openCur = true; else { if (mode.ZerosTailIsAllowed) { RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))) if (ErrorInfo.IgnoreTail) openCur = true; } if (!openCur) { openCur = specFlags.CanReturnFrontal; if (formatIndex < 0) // format is not forced { if (IsPreArcFormat(ai)) { // if (mode.SkipSfxStub) { openCur = false; } } } } } if (openCur) { InStream = op.stream; Archive = archive; return S_OK; } } skipFrontalFormat[(unsigned)FormatIndex] = true; // if (!mode.CanReturnArc) /* if (!ErrorInfo.ThereIsTail) continue; */ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) continue; // printf("\nAdd offset = %d", (int)pi.Offset); RINOK(ReadParseItemProps(archive, ai, pi)) handlerSpec->AddItem(pi); } } // ---------- PARSER ---------- CUIntVector arc2sig; // formatIndex to signatureIndex CUIntVector sig2arc; // signatureIndex to formatIndex; { unsigned sum = 0; FOR_VECTOR (i, op.codecs->Formats) { arc2sig.Add(sum); const CObjectVector &sigs = op.codecs->Formats[i].Signatures; sum += sigs.Size(); FOR_VECTOR (k, sigs) sig2arc.Add(i); } } { const size_t kBeforeSize = 1 << 16; const size_t kAfterSize = 1 << 20; const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8); CByteArr hashBuffer(kNumVals); Byte *hash = hashBuffer; memset(hash, 0xFF, kNumVals); Byte prevs[256]; memset(prevs, 0xFF, sizeof(prevs)); if (sig2arc.Size() >= 0xFF) return S_FALSE; CUIntVector difficultFormats; CBoolArr difficultBools(256); { for (unsigned i = 0; i < 256; i++) difficultBools[i] = false; } bool thereAreHandlersForSearch = false; // UInt32 maxSignatureEnd = 0; FOR_VECTOR (i, orderIndices) { int index = orderIndices[i]; if (index < 0) continue; const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index]; if (ai.Flags_ByExtOnlyOpen()) continue; bool isDifficult = false; // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31) if (!ai.NewInterface) isDifficult = true; else { if (ai.Flags_StartOpen()) isDifficult = true; FOR_VECTOR (k, ai.Signatures) { const CByteBuffer &sig = ai.Signatures[k]; /* UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); if (maxSignatureEnd < signatureEnd) maxSignatureEnd = signatureEnd; */ if (sig.Size() < kNumHashBytes) { isDifficult = true; continue; } thereAreHandlersForSearch = true; UInt32 v = HASH_VAL(sig); unsigned sigIndex = arc2sig[(unsigned)index] + k; prevs[sigIndex] = hash[v]; hash[v] = (Byte)sigIndex; } } if (isDifficult) { difficultFormats.Add((unsigned)index); difficultBools[(unsigned)index] = true; } } if (!thereAreHandlersForSearch) { // openOnlyFullArc = true; // canReturnTailArc = true; } RINOK(InStream_SeekToBegin(op.stream)) CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream; CMyComPtr limitedStream = limitedStreamSpec; limitedStreamSpec->SetStream(op.stream); CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL; CMyComPtr openCallback_Offset; if (op.callback) { openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; openCallback_Offset = openCallback_Offset_Spec; openCallback_Offset_Spec->Callback = op.callback; openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback); #ifndef Z7_NO_CRYPTO openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword); #endif } if (op.callback) RINOK(op.callback->SetTotal(NULL, &fileSize)) CByteBuffer &byteBuffer = limitedStreamSpec->Buffer; byteBuffer.Alloc(kBufSize); UInt64 callbackPrev = 0; bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos. bool endOfFile = false; UInt64 bufPhyPos = 0; size_t bytesInBuf = 0; // UInt64 prevPos = 0; // ---------- Main Scan Loop ---------- UInt64 pos = 0; if (!mode.EachPos && handlerSpec->_items.Size() == 1) { NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; if (!pi.LenIsUnknown && pi.Offset == 0) pos = pi.Size; } for (;;) { // printf("\nPos = %d", (int)pos); UInt64 posInBuf = pos - bufPhyPos; // if (pos > ((UInt64)1 << 35)) break; if (!endOfFile) { if (bytesInBuf < kBufSize) { size_t processedSize = kBufSize - bytesInBuf; // printf("\nRead ask = %d", (unsigned)processedSize); UInt64 seekPos = bufPhyPos + bytesInBuf; RINOK(InStream_SeekSet(op.stream, bufPhyPos + bytesInBuf)) RINOK(ReadStream(op.stream, byteBuffer.NonConstData() + bytesInBuf, &processedSize)) // printf(" processed = %d", (unsigned)processedSize); if (processedSize == 0) { fileSize = seekPos; endOfFile = true; } else { bytesInBuf += processedSize; limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos); } continue; } if (bytesInBuf < posInBuf) { UInt64 skipSize = posInBuf - bytesInBuf; if (skipSize <= kBeforeSize) { size_t keepSize = (size_t)(kBeforeSize - skipSize); // printf("\nmemmove skip = %d", (int)keepSize); memmove(byteBuffer, byteBuffer.ConstData() + bytesInBuf - keepSize, keepSize); bytesInBuf = keepSize; bufPhyPos = pos - keepSize; continue; } // printf("\nSkip %d", (int)(skipSize - kBeforeSize)); // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL)); bytesInBuf = 0; bufPhyPos = pos - kBeforeSize; continue; } if (bytesInBuf - posInBuf < kAfterSize) { size_t beg = (size_t)posInBuf - kBeforeSize; // printf("\nmemmove for after beg = %d", (int)beg); memmove(byteBuffer, byteBuffer.ConstData() + beg, bytesInBuf - beg); bufPhyPos += beg; bytesInBuf -= beg; continue; } } if (bytesInBuf <= (size_t)posInBuf) break; bool useOffsetCallback = false; if (openCallback_Offset) { openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); openCallback_Offset_Spec->Offset = pos; useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1); if (pos >= callbackPrev + (1 << 23)) { RINOK(openCallback_Offset->SetCompleted(NULL, NULL)) callbackPrev = pos; } } { UInt64 endPos = bufPhyPos + bytesInBuf; if (fileSize < endPos) { FileSize = fileSize; // why ???? fileSize = endPos; } } const size_t availSize = bytesInBuf - (size_t)posInBuf; if (availSize < kNumHashBytes) break; size_t scanSize = availSize - ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes); { /* UInt64 scanLimit = openOnlyFullArc ? maxSignatureEnd : op.openType.ScanSize + maxSignatureEnd; */ if (!mode.CanReturnParser) { if (pos > maxStartOffset) break; UInt64 remScan = maxStartOffset - pos; if (scanSize > remScan) scanSize = (size_t)remScan; } } scanSize++; const Byte *buf = byteBuffer.ConstData() + (size_t)posInBuf; const Byte *bufLimit = buf + scanSize; size_t ppp = 0; if (!needCheckStartOpen) { for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++); ppp = (size_t)(buf - (byteBuffer.ConstData() + (size_t)posInBuf)); pos += ppp; if (buf == bufLimit) continue; } UInt32 v = HASH_VAL(buf); bool nextNeedCheckStartOpen = true; unsigned i = hash[v]; unsigned indexOfDifficult = 0; // ---------- Open Loop for Current Pos ---------- bool wasOpen = false; for (;;) { unsigned index; bool isDifficult; if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size()) { index = difficultFormats[indexOfDifficult++]; isDifficult = true; } else { if (i == 0xFF) break; index = sig2arc[i]; unsigned sigIndex = i - arc2sig[index]; i = prevs[i]; if (needCheckStartOpen && difficultBools[index]) continue; const CArcInfoEx &ai = op.codecs->Formats[index]; if (pos < ai.SignatureOffset) continue; /* if (openOnlyFullArc) if (pos != ai.SignatureOffset) continue; */ const CByteBuffer &sig = ai.Signatures[sigIndex]; if (ppp + sig.Size() > availSize || !TestSignature(buf, sig, sig.Size())) continue; // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos)); // prevPos = pos; isDifficult = false; } const CArcInfoEx &ai = op.codecs->Formats[index]; if ((isDifficult && pos == 0) || ai.SignatureOffset == pos) { // we don't check same archive second time */ if (skipFrontalFormat[index]) continue; } UInt64 startArcPos = pos; if (!isDifficult) { if (pos < ai.SignatureOffset) continue; startArcPos = pos - ai.SignatureOffset; /* // we don't need the check for Z files if (startArcPos < handlerSpec->GetLastEnd()) continue; */ } if (ai.IsArcFunc && startArcPos >= bufPhyPos) { const size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos); if (offsetInBuf < bytesInBuf) { const UInt32 isArcRes = ai.IsArcFunc(byteBuffer.ConstData() + offsetInBuf, bytesInBuf - offsetInBuf); if (isArcRes == k_IsArc_Res_NO) continue; if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) continue; /* if (isArcRes == k_IsArc_Res_YES_LOW_PROB) { // if (pos != ai.SignatureOffset) continue; } */ } // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name); } PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name)); const bool isMainFormat = isMainFormatArr[index]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); CMyComPtr archive; RINOK(PrepareToOpen(op, index, archive)) if (!archive) return E_FAIL; // OutputDebugStringW(ai.Name); const UInt64 rem = fileSize - startArcPos; UInt64 arcStreamOffset = 0; if (ai.Flags_UseGlobalOffset()) { RINOK(limitedStreamSpec->InitAndSeek(0, fileSize)) RINOK(InStream_SeekSet(limitedStream, startArcPos)) } else { RINOK(limitedStreamSpec->InitAndSeek(startArcPos, rem)) arcStreamOffset = startArcPos; } UInt64 maxCheckStartPosition = 0; if (openCallback_Offset) { openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); openCallback_Offset_Spec->Offset = startArcPos; } // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset); extractCallback_To_OpenCallback_Spec->Files = 0; extractCallback_To_OpenCallback_Spec->Offset = startArcPos; HRESULT result = OpenArchiveSpec(archive, true, // needPhySize limitedStream, &maxCheckStartPosition, useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback, extractCallback_To_OpenCallback); RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)) bool isOpen = false; if (result == S_FALSE) { if (!mode.CanReturnParser) { if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen()) { ErrorInfo.ErrorFormatIndex = (int)index; NonOpen_ErrorInfo = ErrorInfo; // if archive was detected, we don't need additional open attempts return S_FALSE; } continue; } if (!ErrorInfo.IsArc_After_NonOpen() || !PhySize_Defined || PhySize == 0) continue; } else { if (PhySize_Defined && PhySize == 0) { PRF(printf(" phySize_Defined && PhySize == 0 ")); // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function. continue; } isOpen = true; RINOK(result) PRF(printf(" OK ")); } // fprintf(stderr, "\n %8X %S", startArcPos, Path); // printf("\nOpen OK: %S", ai.Name); NArchive::NParser::CParseItem pi; pi.Offset = startArcPos; if (ai.Flags_UseGlobalOffset()) pi.Offset = (UInt64)Offset; else if (Offset != 0) return E_FAIL; const UInt64 arcRem = FileSize - pi.Offset; UInt64 phySize = arcRem; const bool phySize_Defined = PhySize_Defined; if (phySize_Defined) { if (pi.Offset + PhySize > FileSize) { // ErrorInfo.ThereIsTail = true; PhySize = FileSize - pi.Offset; } phySize = PhySize; } if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63)) return E_FAIL; /* if (!ai.UseGlobalOffset) { if (phySize > arcRem) { ThereIsTail = true; phySize = arcRem; } } */ bool needScan = false; if (isOpen && !phySize_Defined) { // it's for Z format, or bzip2,gz,xz with phySize that was not detected pi.LenIsUnknown = true; needScan = true; phySize = arcRem; nextNeedCheckStartOpen = false; } pi.Size = phySize; /* if (OkPhySize_Defined) pi.OkSize = OkPhySize; */ pi.NormalizeOffset(); // printf(" phySize = %8d", (unsigned)phySize); /* if (needSkipFullArc) if (pi.Offset == 0 && phySize_Defined && pi.Size >= fileSize) continue; */ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) { // it's possible for dmg archives if (!mode.CanReturnArc) continue; } if (mode.EachPos) pos++; else if (needScan) { pos++; /* if (!OkPhySize_Defined) pos++; else pos = pi.Offset + pi.OkSize; */ } else pos = pi.Offset + pi.Size; RINOK(ReadParseItemProps(archive, ai, pi)) if (pi.Offset < startArcPos && !mode.EachPos /* && phySize_Defined */) { /* It's for DMG format. This code deletes all previous items that are included to current item */ while (!handlerSpec->_items.IsEmpty()) { { const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back(); if (back.Offset < pi.Offset) break; if (back.Offset + back.Size > pi.Offset + pi.Size) break; } handlerSpec->_items.DeleteBack(); } } if (isOpen && mode.CanReturnArc && phySize_Defined) { // if (pi.Offset + pi.Size >= fileSize) bool openCur = false; bool thereIsTail = ErrorInfo.ThereIsTail; if (thereIsTail && mode.ZerosTailIsAllowed) { RINOK(CheckZerosTail(op, (UInt64)((Int64)arcStreamOffset + Offset + (Int64)PhySize))) if (ErrorInfo.IgnoreTail) thereIsTail = false; } if (pi.Offset != 0) { if (!pi.IsNotArcType) { if (thereIsTail) openCur = specFlags.CanReturnMid; else openCur = specFlags.CanReturnTail; } } else { if (!thereIsTail) openCur = true; else openCur = specFlags.CanReturnFrontal; if (formatIndex >= -2) openCur = true; } if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */) openCur = false; // We open file as SFX, if there is front archive or first archive is "Self Executable" if (!openCur && !pi.IsSelfExe && !thereIsTail && (!pi.IsNotArcType || pi.Offset == 0)) { if (handlerSpec->_items.IsEmpty()) { if (specFlags.CanReturnTail) openCur = true; } else if (handlerSpec->_items.Size() == 1) { if (handlerSpec->_items[0].IsSelfExe) { if (mode.SpecUnknownExt.CanReturnTail) openCur = true; } } } if (openCur) { InStream = op.stream; Archive = archive; FormatIndex = (int)index; ArcStreamOffset = arcStreamOffset; return S_OK; } } /* if (openOnlyFullArc) { ErrorInfo.ClearErrors(); return S_FALSE; } */ pi.FormatIndex = (int)index; // printf("\nAdd offset = %d", (int)pi.Offset); handlerSpec->AddItem(pi); wasOpen = true; break; } // ---------- End of Open Loop for Current Pos ---------- if (!wasOpen) pos++; needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen); } // ---------- End of Main Scan Loop ---------- /* if (handlerSpec->_items.Size() == 1) { const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; if (pi.Size == fileSize && pi.Offset == 0) { Archive = archive; FormatIndex2 = pi.FormatIndex; return S_OK; } } */ if (mode.CanReturnParser) { bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing handlerSpec->AddUnknownItem(fileSize); if (handlerSpec->_items.Size() == 0) return S_FALSE; if (returnParser || handlerSpec->_items.Size() != 1) { // return S_FALSE; handlerSpec->_stream = op.stream; Archive = handler; ErrorInfo.ClearErrors(); IsParseArc = true; FormatIndex = -1; // It's parser Offset = 0; return S_OK; } } } #endif if (!Archive) return S_FALSE; return S_OK; } HRESULT CArc::OpenStream(const COpenOptions &op) { RINOK(OpenStream2(op)) // PrintNumber("op.formatIndex 3", op.formatIndex); if (Archive) { GetRawProps.Release(); GetRootProps.Release(); Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps); Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps); RINOK(Archive_GetArcProp_Bool(Archive, kpidIsTree, IsTree)) RINOK(Archive_GetArcProp_Bool(Archive, kpidIsDeleted, Ask_Deleted)) RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAltStream, Ask_AltStream)) RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAux, Ask_Aux)) RINOK(Archive_GetArcProp_Bool(Archive, kpidINode, Ask_INode)) RINOK(Archive_GetArcProp_Bool(Archive, kpidReadOnly, IsReadOnly)) const UString fileName = ExtractFileNameFromPath(Path); UString extension; { int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) extension = fileName.Ptr((unsigned)(dotPos + 1)); } DefaultName.Empty(); if (FormatIndex >= 0) { const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; if (ai.Exts.Size() == 0) DefaultName = GetDefaultName2(fileName, UString(), UString()); else { int subExtIndex = ai.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; const CArcExtInfo &extInfo = ai.Exts[(unsigned)subExtIndex]; DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } } } return S_OK; } #ifdef Z7_SFX #ifdef _WIN32 #define k_ExeExt ".exe" static const unsigned k_ExeExt_Len = 4; #else #define k_ExeExt "" static const unsigned k_ExeExt_Len = 0; #endif #endif HRESULT CArc::OpenStreamOrFile(COpenOptions &op) { CMyComPtr fileStream; CMyComPtr seqStream; CInFileStream *fileStreamSpec = NULL; if (op.stdInMode) { #if 1 seqStream = new CStdInFileStream; #else if (!CreateStdInStream(seqStream)) return GetLastError_noZero_HRESULT(); #endif op.seqStream = seqStream; } else if (!op.stream) { fileStreamSpec = new CInFileStream; fileStream = fileStreamSpec; Path = filePath; if (!fileStreamSpec->Open(us2fs(Path))) return GetLastError_noZero_HRESULT(); op.stream = fileStream; #ifdef Z7_SFX IgnoreSplit = true; #endif } /* if (callback) { UInt64 fileSize; RINOK(InStream_GetSize_SeekToEnd(op.stream, fileSize)); RINOK(op.callback->SetTotal(NULL, &fileSize)) } */ HRESULT res = OpenStream(op); IgnoreSplit = false; #ifdef Z7_SFX if (res != S_FALSE || !fileStreamSpec || !op.callbackSpec || NonOpen_ErrorInfo.IsArc_After_NonOpen()) return res; { if (filePath.Len() > k_ExeExt_Len && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt)) { const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len); FOR_VECTOR (i, op.codecs->Formats) { const CArcInfoEx &ai = op.codecs->Formats[i]; if (ai.Is_Split()) continue; UString path3 = path2; path3.Add_Dot(); path3 += ai.GetMainExt(); // "7z" for SFX. Path = path3; Path += ".001"; bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); if (!isOk) { Path = path3; isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); } if (isOk) { if (fileStreamSpec->Open(us2fs(Path))) { op.stream = fileStream; NonOpen_ErrorInfo.ClearErrors_Full(); if (OpenStream(op) == S_OK) return S_OK; } } } } } #endif return res; } void CArchiveLink::KeepModeForNextOpen() { for (unsigned i = Arcs.Size(); i != 0;) { i--; CMyComPtr keep; Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep); if (keep) keep->KeepModeForNextOpen(); } } HRESULT CArchiveLink::Close() { for (unsigned i = Arcs.Size(); i != 0;) { i--; RINOK(Arcs[i].Close()) } IsOpen = false; // ErrorsText.Empty(); return S_OK; } void CArchiveLink::Release() { // NonOpenErrorFormatIndex = -1; NonOpen_ErrorInfo.ClearErrors(); NonOpen_ArcPath.Empty(); while (!Arcs.IsEmpty()) Arcs.DeleteBack(); } /* void CArchiveLink::Set_ErrorsText() { FOR_VECTOR(i, Arcs) { const CArc &arc = Arcs[i]; if (!arc.ErrorFlagsText.IsEmpty()) { if (!ErrorsText.IsEmpty()) ErrorsText.Add_LF(); ErrorsText += GetUnicodeString(arc.ErrorFlagsText); } if (!arc.ErrorMessage.IsEmpty()) { if (!ErrorsText.IsEmpty()) ErrorsText.Add_LF(); ErrorsText += arc.ErrorMessage; } if (!arc.WarningMessage.IsEmpty()) { if (!ErrorsText.IsEmpty()) ErrorsText.Add_LF(); ErrorsText += arc.WarningMessage; } } } */ HRESULT CArchiveLink::Open(COpenOptions &op) { Release(); if (op.types->Size() >= 32) return E_NOTIMPL; HRESULT resSpec; for (;;) { resSpec = S_OK; op.openType = COpenType(); if (op.types->Size() >= 1) { COpenType latest; if (Arcs.Size() < op.types->Size()) latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; else { latest = (*op.types)[0]; if (!latest.Recursive) break; } op.openType = latest; } else if (Arcs.Size() >= 32) break; /* op.formatIndex = -1; if (op.types->Size() >= 1) { int latest; if (Arcs.Size() < op.types->Size()) latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; else { latest = (*op.types)[0]; if (latest != -2 && latest != -3) break; } if (latest >= 0) op.formatIndex = latest; else if (latest == -1 || latest == -2) { // default } else if (latest == -3) op.formatIndex = -2; else op.formatIndex = latest + 2; } else if (Arcs.Size() >= 32) break; */ if (Arcs.IsEmpty()) { CArc arc; arc.filePath = op.filePath; arc.Path = op.filePath; arc.SubfileIndex = (UInt32)(Int32)-1; HRESULT result = arc.OpenStreamOrFile(op); if (result != S_OK) { if (result == S_FALSE) { NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo; // NonOpenErrorFormatIndex = arc.ErrorFormatIndex; NonOpen_ArcPath = arc.Path; } return result; } Arcs.Add(arc); continue; } // PrintNumber("op.formatIndex 11", op.formatIndex); const CArc &arc = Arcs.Back(); if (op.types->Size() > Arcs.Size()) resSpec = E_NOTIMPL; UInt32 mainSubfile; { NCOM::CPropVariant prop; RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop)) if (prop.vt == VT_UI4) mainSubfile = prop.ulVal; else break; UInt32 numItems; RINOK(arc.Archive->GetNumberOfItems(&numItems)) if (mainSubfile >= numItems) break; } CMyComPtr getStream; if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) break; CMyComPtr subSeqStream; if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) break; CMyComPtr subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) break; CArc arc2; RINOK(arc.GetItem_Path(mainSubfile, arc2.Path)) bool zerosTailIsAllowed; RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)) if (op.callback) { Z7_DECL_CMyComPtr_QI_FROM( IArchiveOpenSetSubArchiveName, setSubArchiveName, op.callback) if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(arc2.Path); } arc2.SubfileIndex = mainSubfile; // CIntVector incl; CIntVector excl; COpenOptions op2; #ifndef Z7_SFX op2.props = op.props; #endif op2.codecs = op.codecs; // op2.types = &incl; op2.openType = op.openType; op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed; op2.excludedFormats = ! op2.stdInMode = false; op2.stream = subStream; op2.filePath = arc2.Path; op2.callback = op.callback; op2.callbackSpec = op.callbackSpec; HRESULT result = arc2.OpenStream(op2); resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE); if (result == S_FALSE) { NonOpen_ErrorInfo = arc2.ErrorInfo; NonOpen_ArcPath = arc2.Path; break; } RINOK(result) RINOK(arc.GetItem_MTime(mainSubfile, arc2.MTime)) Arcs.Add(arc2); } IsOpen = !Arcs.IsEmpty(); return resSpec; } HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) { VolumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr callback = openCallbackSpec; openCallbackSpec->Callback = callbackUI; FString prefix, name; if (!op.stream && !op.stdInMode) { NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); RINOK(openCallbackSpec->Init2(prefix, name)) } else { openCallbackSpec->SetSubArchiveName(op.filePath); } op.callback = callback; op.callbackSpec = openCallbackSpec; HRESULT res = Open(op); PasswordWasAsked = openCallbackSpec->PasswordWasAsked; // Password = openCallbackSpec->Password; RINOK(res) // VolumePaths.Add(fs2us(prefix + name)); FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed) { if (openCallbackSpec->FileNames_WasUsed[i]) { VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); VolumesSize += openCallbackSpec->FileSizes[i]; } } // VolumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArc::ReOpen(const COpenOptions &op, IArchiveOpenCallback *openCallback_Additional) { ErrorInfo.ClearErrors(); ErrorInfo.ErrorFormatIndex = -1; UInt64 fileSize = 0; if (op.stream) { RINOK(InStream_SeekToBegin(op.stream)) RINOK(InStream_AtBegin_GetSize(op.stream, fileSize)) // RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize)) } FileSize = fileSize; CMyComPtr stream2; Int64 globalOffset = GetGlobalOffset(); if (globalOffset <= 0) stream2 = op.stream; else { CTailInStream *tailStreamSpec = new CTailInStream; stream2 = tailStreamSpec; tailStreamSpec->Stream = op.stream; tailStreamSpec->Offset = (UInt64)globalOffset; tailStreamSpec->Init(); RINOK(tailStreamSpec->SeekToStart()) } // There are archives with embedded STUBs (like ZIP), so we must support signature scanning // But for another archives we can use 0 here. So the code can be fixed !!! UInt64 maxStartPosition = kMaxCheckStartPosition; IArchiveOpenCallback *openCallback = openCallback_Additional; if (!openCallback) openCallback = op.callback; HRESULT res = Archive->Open(stream2, &maxStartPosition, openCallback); if (res == S_OK) { RINOK(ReadBasicProps(Archive, (UInt64)globalOffset, res)) ArcStreamOffset = (UInt64)globalOffset; if (ArcStreamOffset != 0) InStream = op.stream; } return res; } HRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI) { HRESULT res = Open2(op, callbackUI); if (callbackUI) { RINOK(callbackUI->Open_Finished()) } return res; } HRESULT CArchiveLink::ReOpen(COpenOptions &op) { if (Arcs.Size() > 1) return E_NOTIMPL; CObjectVector inc; CIntVector excl; op.types = &inc; op.excludedFormats = ! op.stdInMode = false; op.stream = NULL; if (Arcs.Size() == 0) // ??? return Open2(op, NULL); /* if archive is multivolume (unsupported here still) COpenCallbackImp object will exist after Open stage. */ COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr openCallbackNew = openCallbackSpec; openCallbackSpec->Callback = NULL; openCallbackSpec->ReOpenCallback = op.callback; { FString dirPrefix, fileName; NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName); RINOK(openCallbackSpec->Init2(dirPrefix, fileName)) } CInFileStream *fileStreamSpec = new CInFileStream; CMyComPtr stream(fileStreamSpec); if (!fileStreamSpec->Open(us2fs(op.filePath))) return GetLastError_noZero_HRESULT(); op.stream = stream; CArc &arc = Arcs[0]; const HRESULT res = arc.ReOpen(op, openCallbackNew); openCallbackSpec->ReOpenCallback = NULL; PasswordWasAsked = openCallbackSpec->PasswordWasAsked; // Password = openCallbackSpec->Password; IsOpen = (res == S_OK); return res; } #ifndef Z7_SFX bool ParseComplexSize(const wchar_t *s, UInt64 &result); bool ParseComplexSize(const wchar_t *s, UInt64 &result) { result = 0; const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (end == s) return false; if (*end == 0) { result = number; return true; } if (end[1] != 0) return false; unsigned numBits; switch (MyCharLower_Ascii(*end)) { case 'b': result = number; return true; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static bool ParseTypeParams(const UString &s, COpenType &type) { if (s[0] == 0) return true; if (s[1] == 0) { switch ((unsigned)(Byte)s[0]) { case 'e': type.EachPos = true; return true; case 'a': type.CanReturnArc = true; return true; case 'r': type.Recursive = true; return true; default: break; } return false; } if (s[0] == 's') { UInt64 result; if (!ParseComplexSize(s.Ptr(1), result)) return false; type.MaxStartOffset = result; type.MaxStartOffset_Defined = true; return true; } return false; } static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) { int pos2 = s.Find(L':'); { UString name; if (pos2 < 0) { name = s; pos2 = (int)s.Len(); } else { name = s.Left((unsigned)pos2); pos2++; } int index = codecs.FindFormatForArchiveType(name); type.Recursive = false; if (index < 0) { if (name[0] == '*') { if (name[1] != 0) return false; } else if (name[0] == '#') { if (name[1] != 0) return false; type.CanReturnArc = false; type.CanReturnParser = true; } else if (name.IsEqualTo_Ascii_NoCase("hash")) { // type.CanReturnArc = false; // type.CanReturnParser = false; type.IsHashType = true; } else return false; } type.FormatIndex = index; } for (unsigned i = (unsigned)pos2; i < s.Len();) { int next = s.Find(L':', i); if (next < 0) next = (int)s.Len(); const UString name = s.Mid(i, (unsigned)next - i); if (name.IsEmpty()) return false; if (!ParseTypeParams(name, type)) return false; i = (unsigned)next + 1; } return true; } bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types) { types.Clear(); bool isHashType = false; for (unsigned pos = 0; pos < s.Len();) { int pos2 = s.Find(L'.', pos); if (pos2 < 0) pos2 = (int)s.Len(); UString name = s.Mid(pos, (unsigned)pos2 - pos); if (name.IsEmpty()) return false; COpenType type; if (!ParseType(codecs, name, type)) return false; if (isHashType) return false; if (type.IsHashType) isHashType = true; types.Add(type); pos = (unsigned)pos2 + 1; } return true; } /* bool IsHashType(const CObjectVector &types) { if (types.Size() != 1) return false; return types[0].IsHashType; } */ #endif tmp41wklro_/CPP/7zip/UI/Common/OpenArchive.h0000444000175000001440000003047714413441700021606 0ustar nabijaczleweliusers// OpenArchive.h #ifndef ZIP7_INC_OPEN_ARCHIVE_H #define ZIP7_INC_OPEN_ARCHIVE_H #include "../../../Windows/PropVariant.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" #include "Property.h" #include "DirItem.h" #ifndef Z7_SFX #define SUPPORT_ALT_STREAMS #endif HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); #ifdef SUPPORT_ALT_STREAMS int FindAltStreamColon_in_Path(const wchar_t *path); #endif /* struct COptionalOpenProperties { UString FormatName; CObjectVector Props; }; */ #ifdef Z7_SFX #define OPEN_PROPS_DECL #else #define OPEN_PROPS_DECL const CObjectVector *props; // #define OPEN_PROPS_DECL , const CObjectVector *props #endif struct COpenSpecFlags { // bool CanReturnFull; bool CanReturnFrontal; bool CanReturnTail; bool CanReturnMid; bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; } COpenSpecFlags(): // CanReturnFull(true), CanReturnFrontal(false), CanReturnTail(false), CanReturnMid(false) {} }; struct COpenType { int FormatIndex; COpenSpecFlags SpecForcedType; COpenSpecFlags SpecMainType; COpenSpecFlags SpecWrongExt; COpenSpecFlags SpecUnknownExt; bool Recursive; bool CanReturnArc; bool CanReturnParser; bool IsHashType; bool EachPos; // bool SkipSfxStub; // bool ExeAsUnknown; bool ZerosTailIsAllowed; bool MaxStartOffset_Defined; UInt64 MaxStartOffset; const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const { return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); } COpenType(): FormatIndex(-1), Recursive(true), CanReturnArc(true), CanReturnParser(false), IsHashType(false), EachPos(false), // SkipSfxStub(true), // ExeAsUnknown(true), ZerosTailIsAllowed(false), MaxStartOffset_Defined(false), MaxStartOffset(0) { SpecForcedType.CanReturnFrontal = true; SpecForcedType.CanReturnTail = true; SpecForcedType.CanReturnMid = true; SpecMainType.CanReturnFrontal = true; SpecUnknownExt.CanReturnTail = true; // for sfx SpecUnknownExt.CanReturnMid = true; SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad // ZerosTailIsAllowed = true; } }; struct COpenOptions { CCodecs *codecs; COpenType openType; const CObjectVector *types; const CIntVector *excludedFormats; IInStream *stream; ISequentialInStream *seqStream; IArchiveOpenCallback *callback; COpenCallbackImp *callbackSpec; // it's used for SFX only OPEN_PROPS_DECL // bool openOnlySpecifiedByExtension, bool stdInMode; UString filePath; COpenOptions(): codecs(NULL), types(NULL), excludedFormats(NULL), stream(NULL), seqStream(NULL), callback(NULL), callbackSpec(NULL), stdInMode(false) {} }; UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); struct CArcErrorInfo { bool ThereIsTail; bool UnexpecedEnd; bool IgnoreTail; // all are zeros // bool NonZerosTail; bool ErrorFlags_Defined; UInt32 ErrorFlags; UInt32 WarningFlags; int ErrorFormatIndex; // - 1 means no Error. // if FormatIndex == ErrorFormatIndex, the archive is open with offset UInt64 TailSize; /* if CArc is Open OK with some format: - ErrorFormatIndex shows error format index, if extension is incorrect - other variables show message and warnings of archive that is open */ UString ErrorMessage; UString WarningMessage; // call IsArc_After_NonOpen only if Open returns S_FALSE bool IsArc_After_NonOpen() const { return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); } CArcErrorInfo(): ThereIsTail(false), UnexpecedEnd(false), IgnoreTail(false), // NonZerosTail(false), ErrorFlags_Defined(false), ErrorFlags(0), WarningFlags(0), ErrorFormatIndex(-1), TailSize(0) {} void ClearErrors(); void ClearErrors_Full() { ErrorFormatIndex = -1; ClearErrors(); } bool IsThereErrorOrWarning() const { return ErrorFlags != 0 || WarningFlags != 0 || NeedTailWarning() || UnexpecedEnd || !ErrorMessage.IsEmpty() || !WarningMessage.IsEmpty(); } bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } UInt32 GetWarningFlags() const { UInt32 a = WarningFlags; if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) a |= kpv_ErrorFlags_DataAfterEnd; return a; } UInt32 GetErrorFlags() const { UInt32 a = ErrorFlags; if (UnexpecedEnd) a |= kpv_ErrorFlags_UnexpectedEnd; return a; } }; struct CReadArcItem { UString Path; // Path from root (including alt stream name, if alt stream) UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode #ifdef SUPPORT_ALT_STREAMS UString MainPath; /* MainPath = Path for non-AltStream, MainPath = Path of parent, if there is parent for AltStream. */ UString AltStreamName; bool IsAltStream; bool WriteToAltStreamIfColon; #endif bool IsDir; bool MainIsDir; UInt32 ParentIndex; // use it, if IsAltStream #ifndef Z7_SFX bool _use_baseParentFolder_mode; int _baseParentFolder; #endif CReadArcItem() { #ifdef SUPPORT_ALT_STREAMS WriteToAltStreamIfColon = false; #endif #ifndef Z7_SFX _use_baseParentFolder_mode = false; _baseParentFolder = -1; #endif } }; class CArc { HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive); HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); HRESULT OpenStream2(const COpenOptions &options); #ifndef Z7_SFX // parts.Back() can contain alt stream name "nams:AltName" HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; #endif public: CMyComPtr Archive; CMyComPtr InStream; // we use InStream in 2 cases (ArcStreamOffset != 0): // 1) if we use additional cache stream // 2) we reopen sfx archive with CTailInStream CMyComPtr GetRawProps; CMyComPtr GetRootProps; bool IsParseArc; bool IsTree; bool IsReadOnly; bool Ask_Deleted; bool Ask_AltStream; bool Ask_Aux; bool Ask_INode; bool IgnoreSplit; // don't try split handler UString Path; UString filePath; UString DefaultName; int FormatIndex; // -1 means Parser UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile // CFiTime MTime; // bool MTime_Defined; CArcTime MTime; Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler UInt64 PhySize; // UInt64 OkPhySize; bool PhySize_Defined; // bool OkPhySize_Defined; UInt64 FileSize; UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file CArcErrorInfo ErrorInfo; // for OK archives CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? PhySize : FileSize; } UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive // AString ErrorFlagsText; // void Set_ErrorFlagsText(); CArc(): // MTime_Defined(false), IsTree(false), IsReadOnly(false), Ask_Deleted(false), Ask_AltStream(false), Ask_Aux(false), Ask_INode(false), IgnoreSplit(false) {} HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); HRESULT Close() { InStream.Release(); return Archive->Close(); } HRESULT GetItem_Path(UInt32 index, UString &result) const; HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const; // GetItemPath2 adds [DELETED] dir prefix for deleted items. HRESULT GetItem_Path2(UInt32 index, UString &result) const; HRESULT GetItem(UInt32 index, CReadArcItem &item) const; HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const; /* if (GetProperty() returns vt==VT_EMPTY), this function sets timestamp from archive file timestamp (MTime). So (at) will be set in most cases (at.Def == true) if (at.Prec == 0) { it means that (Prec == 0) was returned for (kpidMTime), and no value was returned for (kpidTimeType). it can mean Windows precision or unknown precision. } */ HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const; HRESULT IsItem_Anti(UInt32 index, bool &result) const { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } HRESULT OpenStream(const COpenOptions &options); HRESULT OpenStreamOrFile(COpenOptions &options); HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional); HRESULT CreateNewTailStream(CMyComPtr &stream); bool IsHashHandler(const COpenOptions &options) const { if (FormatIndex < 0) return false; return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler(); } }; struct CArchiveLink { CObjectVector Arcs; UStringVector VolumePaths; UInt64 VolumesSize; bool IsOpen; bool PasswordWasAsked; // UString Password; // int NonOpenErrorFormatIndex; // - 1 means no Error. UString NonOpen_ArcPath; CArcErrorInfo NonOpen_ErrorInfo; // UString ErrorsText; // void Set_ErrorsText(); CArchiveLink(): VolumesSize(0), IsOpen(false), PasswordWasAsked(false) {} void KeepModeForNextOpen(); HRESULT Close(); void Release(); ~CArchiveLink() { Release(); } const CArc *GetArc() const { return &Arcs.Back(); } IInArchive *GetArchive() const { return Arcs.Back().Archive; } IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } /* Open() opens archive and COpenOptions::callback Open2() uses COpenCallbackImp that implements Volumes and password callback Open3() calls Open2() and callbackUI->Open_Finished(); Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive. */ HRESULT Open(COpenOptions &options); HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI) { HRESULT result = Open3(options, callbackUI); if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0) result = S_FALSE; return result; } HRESULT ReOpen(COpenOptions &options); }; bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types); // bool IsHashType(const CObjectVector &types); struct CDirPathSortPair { unsigned Len; unsigned Index; void SetNumSlashes(const FChar *s); int Compare(const CDirPathSortPair &a) const { // We need sorting order where parent items will be after child items if (Len < a.Len) return 1; if (Len > a.Len) return -1; if (Index < a.Index) return -1; if (Index > a.Index) return 1; return 0; } }; #endif tmp41wklro_/CPP/7zip/UI/Common/Property.h0000444000175000001440000000030214357314620021216 0ustar nabijaczleweliusers// Property.h #ifndef ZIP7_INC_7Z_PROPERTY_H #define ZIP7_INC_7Z_PROPERTY_H #include "../../../Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif tmp41wklro_/CPP/7zip/UI/Common/PropIDUtils.cpp0000444000175000001440000004213614655075400022117 0ustar nabijaczleweliusers// PropIDUtils.cpp #include "StdAfx.h" #include "../../../../C/CpuArch.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/PropVariantConv.h" #include "../../PropID.h" #include "PropIDUtils.h" #ifndef Z7_SFX #define Get16(x) GetUi16(x) #define Get32(x) GetUi32(x) #endif using namespace NWindows; static const unsigned kNumWinAtrribFlags = 30; static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B"; /* FILE_ATTRIBUTE_ 0 READONLY 1 HIDDEN 2 SYSTEM 3 (Volume label - obsolete) 4 DIRECTORY 5 ARCHIVE 6 DEVICE 7 NORMAL 8 TEMPORARY 9 SPARSE_FILE 10 REPARSE_POINT 11 COMPRESSED 12 OFFLINE 13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer) 14 ENCRYPTED 15 INTEGRITY_STREAM (V - ReFS Win8/Win2012) 16 VIRTUAL (reserved) 17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib) 18 RECALL_ON_OPEN or EA 19 PINNED 20 UNPINNED 21 STRICTLY_SEQUENTIAL (10.0.16267) 22 RECALL_ON_DATA_ACCESS 29 STRICTLY_SEQUENTIAL (10.0.17134+) (SMR Blob) */ static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; #define MY_ATTR_CHAR(a, n, c) (((a) & (1 << (n))) ? c : '-') static void ConvertPosixAttribToString(char *s, UInt32 a) throw() { s[0] = kPosixTypes[(a >> 12) & 0xF]; for (int i = 6; i >= 0; i -= 3) { s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); } if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX s[10] = 0; a &= ~(UInt32)0xFFFF; if (a != 0) { s[10] = ' '; ConvertUInt32ToHex8Digits(a, s + 11); } } void ConvertWinAttribToString(char *s, UInt32 wa) throw() { /* some programs store posix attributes in high 16 bits. p7zip - stores additional 0x8000 flag marker. macos - stores additional 0x4000 flag marker. info-zip - no additional marker. But this code works with Attrib from internal 7zip code. So we expect that 0x8000 marker is set, if there are posix attributes. (DT_UNKNOWN == 0) type in high bits is possible in some case for linux files. 0x8000 flag is possible also in ReFS (Windows)? */ const bool isPosix = ( (wa & 0x8000) != 0 // FILE_ATTRIBUTE_UNIX_EXTENSION; // && (wa & 0xFFFF0000u) != 0 ); UInt32 posix = 0; if (isPosix) { posix = wa >> 16; if ((wa & 0xF0000000u) != 0) wa &= (UInt32)0x3FFF; } for (unsigned i = 0; i < kNumWinAtrribFlags; i++) { const UInt32 flag = (UInt32)1 << i; if (wa & flag) { const char c = g_WinAttribChars[i]; if (c != '.') { wa &= ~flag; // if (i != 7) // we can disable N (NORMAL) printing *s++ = c; } } } if (wa != 0) { *s++ = ' '; ConvertUInt32ToHex8Digits(wa, s); s += strlen(s); } *s = 0; if (isPosix) { *s++ = ' '; ConvertPosixAttribToString(s, posix); } } void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw() { *dest = 0; if (prop.vt == VT_FILETIME) { const FILETIME &ft = prop.filetime; unsigned ns100 = 0; int numDigits = kTimestampPrintLevel_NTFS; const unsigned prec = prop.wReserved1; const unsigned ns100_Temp = prop.wReserved2; if (prec != 0 && prec <= k_PropVar_TimePrec_1ns && ns100_Temp < 100 && prop.wReserved3 == 0) { ns100 = ns100_Temp; if (prec == k_PropVar_TimePrec_Unix || prec == k_PropVar_TimePrec_DOS) numDigits = 0; else if (prec == k_PropVar_TimePrec_HighPrec) numDigits = 9; else { numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; if ( // numDigits < kTimestampPrintLevel_DAY // for debuf numDigits < kTimestampPrintLevel_SEC ) numDigits = kTimestampPrintLevel_NTFS; } } if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0 && ns100 == 0) return; if (level > numDigits) level = numDigits; ConvertUtcFileTimeToString2(ft, ns100, dest, level); return; } switch (propID) { case kpidCRC: { if (prop.vt != VT_UI4) break; ConvertUInt32ToHex8Digits(prop.ulVal, dest); return; } case kpidAttrib: { if (prop.vt != VT_UI4) break; const UInt32 a = prop.ulVal; /* if ((a & 0x8000) && (a & 0x7FFF) == 0) ConvertPosixAttribToString(dest, a >> 16); else */ ConvertWinAttribToString(dest, a); return; } case kpidPosixAttrib: { if (prop.vt != VT_UI4) break; ConvertPosixAttribToString(dest, prop.ulVal); return; } case kpidINode: { if (prop.vt != VT_UI8) break; ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest); dest += strlen(dest); *dest++ = '-'; const UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1); ConvertUInt64ToString(low, dest); return; } case kpidVa: { UInt64 v = 0; if (prop.vt == VT_UI4) v = prop.ulVal; else if (prop.vt == VT_UI8) v = (UInt64)prop.uhVal.QuadPart; else break; dest[0] = '0'; dest[1] = 'x'; ConvertUInt64ToHex(v, dest + 2); return; } /* case kpidDevice: { UInt64 v = 0; if (prop.vt == VT_UI4) v = prop.ulVal; else if (prop.vt == VT_UI8) v = (UInt64)prop.uhVal.QuadPart; else break; ConvertUInt32ToString(MY_dev_major(v), dest); dest += strlen(dest); *dest++ = ','; ConvertUInt32ToString(MY_dev_minor(v), dest); return; } */ default: break; } ConvertPropVariantToShortString(prop, dest); } void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level) { if (prop.vt == VT_BSTR) { dest.SetFromBstr(prop.bstrVal); return; } char temp[64]; ConvertPropertyToShortString2(temp, prop, propID, level); dest = temp; } #ifndef Z7_SFX static inline void AddHexToString(AString &res, unsigned v) { res.Add_Char((char)GET_HEX_CHAR_UPPER(v >> 4)); res.Add_Char((char)GET_HEX_CHAR_UPPER(v & 15)); } /* static AString Data_To_Hex(const Byte *data, size_t size) { AString s; for (size_t i = 0; i < size; i++) AddHexToString(s, data[i]); return s; } */ static const char * const sidNames[] = { "0" , "Dialup" , "Network" , "Batch" , "Interactive" , "Logon" // S-1-5-5-X-Y , "Service" , "Anonymous" , "Proxy" , "EnterpriseDC" , "Self" , "AuthenticatedUsers" , "RestrictedCode" , "TerminalServer" , "RemoteInteractiveLogon" , "ThisOrganization" , "16" , "IUserIIS" , "LocalSystem" , "LocalService" , "NetworkService" , "Domains" }; struct CSecID2Name { UInt32 n; const char *sz; }; static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id) { for (unsigned i = 0; i < num; i++) if (pairs[i].n == id) return (int)i; return -1; } static const CSecID2Name sid_32_Names[] = { { 544, "Administrators" }, { 545, "Users" }, { 546, "Guests" }, { 547, "PowerUsers" }, { 548, "AccountOperators" }, { 549, "ServerOperators" }, { 550, "PrintOperators" }, { 551, "BackupOperators" }, { 552, "Replicators" }, { 553, "Backup Operators" }, { 554, "PreWindows2000CompatibleAccess" }, { 555, "RemoteDesktopUsers" }, { 556, "NetworkConfigurationOperators" }, { 557, "IncomingForestTrustBuilders" }, { 558, "PerformanceMonitorUsers" }, { 559, "PerformanceLogUsers" }, { 560, "WindowsAuthorizationAccessGroup" }, { 561, "TerminalServerLicenseServers" }, { 562, "DistributedCOMUsers" }, { 569, "CryptographicOperators" }, { 573, "EventLogReaders" }, { 574, "CertificateServiceDCOMAccess" } }; static const CSecID2Name sid_21_Names[] = { { 500, "Administrator" }, { 501, "Guest" }, { 502, "KRBTGT" }, { 512, "DomainAdmins" }, { 513, "DomainUsers" }, { 515, "DomainComputers" }, { 516, "DomainControllers" }, { 517, "CertPublishers" }, { 518, "SchemaAdmins" }, { 519, "EnterpriseAdmins" }, { 520, "GroupPolicyCreatorOwners" }, { 553, "RASandIASServers" }, { 553, "RASandIASServers" }, { 571, "AllowedRODCPasswordReplicationGroup" }, { 572, "DeniedRODCPasswordReplicationGroup" } }; struct CServicesToName { UInt32 n[5]; const char *sz; }; static const CServicesToName services_to_name[] = { { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" } }; static void ParseSid(AString &s, const Byte *p, size_t lim /* , unsigned &sidSize */) { // sidSize = 0; if (lim < 8) { s += "ERROR"; return; } if (p[0] != 1) // rev { s += "UNSUPPORTED"; return; } const unsigned num = p[1]; const unsigned sidSize_Loc = 8 + num * 4; if (sidSize_Loc > lim) { s += "ERROR"; return; } // sidSize = sidSize_Loc; const UInt32 authority = GetBe32(p + 4); if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1) { const UInt32 v0 = Get32(p + 8); if (v0 < Z7_ARRAY_SIZE(sidNames)) { s += sidNames[v0]; return; } if (v0 == 32 && num == 2) { const UInt32 v1 = Get32(p + 12); const int index = FindPairIndex(sid_32_Names, Z7_ARRAY_SIZE(sid_32_Names), v1); if (index >= 0) { s += sid_32_Names[(unsigned)index].sz; return; } } if (v0 == 21 && num == 5) { UInt32 v4 = Get32(p + 8 + 4 * 4); const int index = FindPairIndex(sid_21_Names, Z7_ARRAY_SIZE(sid_21_Names), v4); if (index >= 0) { s += sid_21_Names[(unsigned)index].sz; return; } } if (v0 == 80 && num == 6) { for (unsigned i = 0; i < Z7_ARRAY_SIZE(services_to_name); i++) { const CServicesToName &sn = services_to_name[i]; int j; for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++); if (j == 5) { s += sn.sz; return; } } } } s += "S-1-"; if (p[2] == 0 && p[3] == 0) s.Add_UInt32(authority); else { s += "0x"; for (int i = 2; i < 8; i++) AddHexToString(s, p[i]); } for (UInt32 i = 0; i < num; i++) { s.Add_Minus(); s.Add_UInt32(Get32(p + 8 + i * 4)); } } static void ParseOwner(AString &s, const Byte *p, size_t size, UInt32 pos) { if (pos > size) { s += "ERROR"; return; } // unsigned sidSize = 0; ParseSid(s, p + pos, size - pos /* , sidSize */); } static void ParseAcl(AString &s, const Byte *p, size_t size, const char *strName, UInt32 flags, UInt32 offset) { const unsigned control = Get16(p + 2); if ((flags & control) == 0) return; const UInt32 pos = Get32(p + offset); s.Add_Space(); s += strName; if (pos >= size) return; p += pos; size -= (size_t)pos; if (size < 8) return; if (Get16(p) != 2) // revision return; const UInt32 num = Get32(p + 4); s.Add_UInt32(num); /* UInt32 aclSize = Get16(p + 2); if (num >= (1 << 16)) return; if (aclSize > size) return; size = aclSize; size -= 8; p += 8; for (UInt32 i = 0 ; i < num; i++) { if (size <= 8) return; // Byte type = p[0]; // Byte flags = p[1]; // UInt32 aceSize = Get16(p + 2); // UInt32 mask = Get32(p + 4); p += 8; size -= 8; UInt32 sidSize = 0; s.Add_Space(); ParseSid(s, p, size, sidSize); if (sidSize == 0) return; p += sidSize; size -= sidSize; } // the tail can contain zeros. So (size != 0) is not ERROR // if (size != 0) s += " ERROR"; */ } /* #define MY_SE_OWNER_DEFAULTED (0x0001) #define MY_SE_GROUP_DEFAULTED (0x0002) */ #define MY_SE_DACL_PRESENT (0x0004) /* #define MY_SE_DACL_DEFAULTED (0x0008) */ #define MY_SE_SACL_PRESENT (0x0010) /* #define MY_SE_SACL_DEFAULTED (0x0020) #define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100) #define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200) #define MY_SE_DACL_AUTO_INHERITED (0x0400) #define MY_SE_SACL_AUTO_INHERITED (0x0800) #define MY_SE_DACL_PROTECTED (0x1000) #define MY_SE_SACL_PROTECTED (0x2000) #define MY_SE_RM_CONTROL_VALID (0x4000) #define MY_SE_SELF_RELATIVE (0x8000) */ void ConvertNtSecureToString(const Byte *data, size_t size, AString &s) { s.Empty(); if (size < 20 || size > (1 << 18)) { s += "ERROR"; return; } if (Get16(data) != 1) // revision { s += "UNSUPPORTED"; return; } ParseOwner(s, data, size, Get32(data + 4)); s.Add_Space(); ParseOwner(s, data, size, Get32(data + 8)); ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); s.Add_Space(); s.Add_UInt32((UInt32)size); // s.Add_LF(); // s += Data_To_Hex(data, size); } #ifdef _WIN32 static bool CheckSid(const Byte *data, size_t size, UInt32 pos) throw() { if (pos >= size) return false; size -= pos; if (size < 8) return false; if (data[pos] != 1) // rev return false; const unsigned num = data[pos + 1]; return (8 + num * 4 <= size); } static bool CheckAcl(const Byte *p, size_t size, UInt32 flags, size_t offset) throw() { const unsigned control = Get16(p + 2); if ((flags & control) == 0) return true; const UInt32 pos = Get32(p + offset); if (pos >= size) return false; p += pos; size -= pos; if (size < 8) return false; const unsigned aclSize = Get16(p + 2); return (aclSize <= size); } bool CheckNtSecure(const Byte *data, size_t size) throw() { if (size < 20) return false; if (Get16(data) != 1) // revision return true; // windows function can handle such error, so we allow it if (size > (1 << 18)) return false; if (!CheckSid(data, size, Get32(data + 4))) return false; if (!CheckSid(data, size, Get32(data + 8))) return false; if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false; if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false; return true; } #endif // IO_REPARSE_TAG_* static const CSecID2Name k_ReparseTags[] = { { 0xA0000003, "MOUNT_POINT" }, { 0xC0000004, "HSM" }, { 0x80000005, "DRIVE_EXTENDER" }, { 0x80000006, "HSM2" }, { 0x80000007, "SIS" }, { 0x80000008, "WIM" }, { 0x80000009, "CSV" }, { 0x8000000A, "DFS" }, { 0x8000000B, "FILTER_MANAGER" }, { 0xA000000C, "SYMLINK" }, { 0xA0000010, "IIS_CACHE" }, { 0x80000012, "DFSR" }, { 0x80000013, "DEDUP" }, { 0xC0000014, "APPXSTRM" }, { 0x80000014, "NFS" }, { 0x80000015, "FILE_PLACEHOLDER" }, { 0x80000016, "DFM" }, { 0x80000017, "WOF" }, { 0x80000018, "WCI" }, { 0x8000001B, "APPEXECLINK" }, { 0xA000001D, "LX_SYMLINK" }, { 0x80000023, "AF_UNIX" }, { 0x80000024, "LX_FIFO" }, { 0x80000025, "LX_CHR" }, { 0x80000026, "LX_BLK" } }; bool ConvertNtReparseToString(const Byte *data, size_t size, UString &s) { s.Empty(); NFile::CReparseAttr attr; if (attr.Parse(data, size)) { if (attr.IsSymLink_WSL()) { s += "WSL: "; s += attr.GetPath(); } else { if (!attr.IsSymLink_Win()) s += "Junction: "; s += attr.GetPath(); if (s.IsEmpty()) s += "Link: "; if (!attr.IsOkNamePair()) { s += " : "; s += attr.PrintName; } } if (attr.MinorError) s += " : MINOR_ERROR"; return true; // s.Add_Space(); // for debug } if (size < 8) return false; const UInt32 tag = Get32(data); const UInt32 len = Get16(data + 4); if (len + 8 > size) return false; if (Get16(data + 6) != 0) // padding return false; /* #define my_IO_REPARSE_TAG_DEDUP (0x80000013L) if (tag == my_IO_REPARSE_TAG_DEDUP) { } */ { const int index = FindPairIndex(k_ReparseTags, Z7_ARRAY_SIZE(k_ReparseTags), tag); if (index >= 0) s += k_ReparseTags[(unsigned)index].sz; else { s += "REPARSE:"; char hex[16]; ConvertUInt32ToHex8Digits(tag, hex); s += hex; } } s.Add_Colon(); s.Add_UInt32(len); if (len != 0) { s.Add_Space(); data += 8; for (UInt32 i = 0; i < len; i++) { if (i >= 16) { s += "..."; break; } const unsigned b = data[i]; s.Add_Char((char)GET_HEX_CHAR_UPPER(b >> 4)); s.Add_Char((char)GET_HEX_CHAR_UPPER(b & 15)); } } return true; } #endif tmp41wklro_/CPP/7zip/UI/Common/PropIDUtils.h0000444000175000001440000000127414475560000021555 0ustar nabijaczleweliusers// PropIDUtils.h #ifndef ZIP7_INC_PROPID_UTILS_H #define ZIP7_INC_PROPID_UTILS_H #include "../../../Common/MyString.h" // provide at least 64 bytes for buffer including zero-end void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw(); void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0); bool ConvertNtReparseToString(const Byte *data, size_t size, UString &s); void ConvertNtSecureToString(const Byte *data, size_t size, AString &s); bool CheckNtSecure(const Byte *data, size_t size) throw(); void ConvertWinAttribToString(char *s, UInt32 wa) throw(); #endif tmp41wklro_/CPP/7zip/UI/Common/SetProperties.cpp0000444000175000001440000000411514504600000022523 0ustar nabijaczleweliusers// SetProperties.cpp #include "StdAfx.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #include "../../Archive/IArchive.h" #include "SetProperties.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *end; const UInt64 result = ConvertStringToUInt64(s, &end); if (*end != 0 || s.IsEmpty()) prop = s; else if (result <= (UInt32)0xFFFFFFFF) prop = (UInt32)result; else prop = result; } struct CPropPropetiesVector { CPropVariant *values; CPropPropetiesVector(unsigned num) { values = new CPropVariant[num]; } ~CPropPropetiesVector() { delete []values; } }; HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties) { if (properties.IsEmpty()) return S_OK; Z7_DECL_CMyComPtr_QI_FROM( ISetProperties, setProperties, unknown) if (!setProperties) return S_OK; UStringVector realNames; CPropPropetiesVector values(properties.Size()); { unsigned i; for (i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { const wchar_t c = name.Back(); if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name.DeleteBack(); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values.values[i] = propVariant; } CRecordVector names; for (i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); return setProperties->SetProperties(names.ConstData(), values.values, names.Size()); } } tmp41wklro_/CPP/7zip/UI/Common/SetProperties.h0000444000175000001440000000032614357314620022210 0ustar nabijaczleweliusers// SetProperties.h #ifndef ZIP7_INC_SETPROPERTIES_H #define ZIP7_INC_SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties); #endif tmp41wklro_/CPP/7zip/UI/Common/SortUtils.cpp0000444000175000001440000000122412620313761021675 0ustar nabijaczleweliusers// SortUtils.cpp #include "StdAfx.h" #include "../../../Common/Wildcard.h" #include "SortUtils.h" static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CUIntVector &indices) { const unsigned numItems = strings.Size(); indices.ClearAndSetSize(numItems); if (numItems == 0) return; unsigned *vals = &indices[0]; for (unsigned i = 0; i < numItems; i++) vals[i] = i; indices.Sort(CompareStrings, (void *)&strings); } tmp41wklro_/CPP/7zip/UI/Common/SortUtils.h0000444000175000001440000000031414357314620021345 0ustar nabijaczleweliusers// SortUtils.h #ifndef ZIP7_INC_SORT_UTLS_H #define ZIP7_INC_SORT_UTLS_H #include "../../../Common/MyString.h" void SortFileNames(const UStringVector &strings, CUIntVector &indices); #endif tmp41wklro_/CPP/7zip/UI/Common/StdAfx.h0000444000175000001440000000036114360505460020566 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/UI/Common/TempFiles.cpp0000444000175000001440000000045512621411062021614 0ustar nabijaczleweliusers// TempFiles.cpp #include "StdAfx.h" #include "../../../Windows/FileDir.h" #include "TempFiles.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while (!Paths.IsEmpty()) { NDir::DeleteFileAlways(Paths.Back()); Paths.DeleteBack(); } } tmp41wklro_/CPP/7zip/UI/Common/TempFiles.h0000444000175000001440000000035614357314620021273 0ustar nabijaczleweliusers// TempFiles.h #ifndef ZIP7_INC_TEMP_FILES_H #define ZIP7_INC_TEMP_FILES_H #include "../../../Common/MyString.h" class CTempFiles { void Clear(); public: FStringVector Paths; ~CTempFiles() { Clear(); } }; #endif tmp41wklro_/CPP/7zip/UI/Common/Update.cpp0000444000175000001440000014242614646226760021175 0ustar nabijaczleweliusers// Update.cpp #include "StdAfx.h" // #include #include "Update.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" #include "../../../Windows/TimeUtils.h" #include "../../Common/FileStreams.h" #include "../../Common/LimitedStreams.h" #include "../../Common/MultiOutStream.h" #include "../../Common/StreamUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char * const kUpdateIsNotSupoorted = "update operations are not supported for this archive"; static const char * const kUpdateIsNotSupported_MultiVol = "Updating for multivolume archives is not implemented"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NDir; using namespace NName; #ifdef _WIN32 static CFSTR const kTempFolderPrefix = FTEXT("7zE"); #endif void CUpdateErrorInfo::SetFromLastError(const char *message) { SystemError = ::GetLastError(); Message = message; } HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName) { SetFromLastError(message); FileNames.Add(fileName); return Get_HRESULT_Error(); } HRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error) { Message = message; FileNames.Add(fileName); SystemError = error; return Get_HRESULT_Error(); } using namespace NUpdateArchive; struct CMultiOutStream_Rec { CMultiOutStream *Spec; CMyComPtr Ref; }; struct CMultiOutStream_Bunch { CObjectVector Items; HRESULT Destruct() { HRESULT hres = S_OK; FOR_VECTOR (i, Items) { CMultiOutStream_Rec &rec = Items[i]; if (rec.Ref) { const HRESULT hres2 = rec.Spec->Destruct(); if (hres == S_OK) hres = hres2; } } Items.Clear(); return hres; } void DisableDeletion() { FOR_VECTOR (i, Items) { CMultiOutStream_Rec &rec = Items[i]; if (rec.Ref) rec.Spec->NeedDelete = false; } } }; void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) { OriginalPath = path; SplitPathToParts_2(path, Prefix, Name); if (mode == k_ArcNameMode_Add) return; if (mode != k_ArcNameMode_Exact) { int dotPos = Name.ReverseFind_Dot(); if (dotPos < 0) return; if ((unsigned)dotPos == Name.Len() - 1) Name.DeleteBack(); else { const UString ext = Name.Ptr((unsigned)(dotPos + 1)); if (BaseExtension.IsEqualTo_NoCase(ext)) { BaseExtension = ext; Name.DeleteFrom((unsigned)dotPos); return; } } } BaseExtension.Empty(); } UString CArchivePath::GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) { path.Add_Dot(); path += BaseExtension; } return path; } UString CArchivePath::GetFinalVolPath() const { UString path = GetPathWithoutExt(); // if BaseExtension is empty, we must ignore VolExtension also. if (!BaseExtension.IsEmpty()) { path.Add_Dot(); path += VolExtension; } return path; } FString CArchivePath::GetTempPath() const { FString path = TempPrefix; path += us2fs(Name); if (!BaseExtension.IsEmpty()) { path.Add_Dot(); path += us2fs(BaseExtension); } path += ".tmp"; path += TempPostfix; return path; } static const char * const kDefaultArcType = "7z"; static const char * const kDefaultArcExt = "7z"; static const char * const kSFXExtension = #ifdef _WIN32 "exe"; #else ""; #endif bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath) { if (types.Size() > 1) return false; // int arcTypeIndex = -1; if (types.Size() != 0) { MethodMode.Type = types[0]; MethodMode.Type_Defined = true; } if (MethodMode.Type.FormatIndex < 0) { // MethodMode.Type = -1; MethodMode.Type = COpenType(); if (ArcNameMode != k_ArcNameMode_Add) { MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.Type.FormatIndex >= 0) MethodMode.Type_Defined = true; } } return true; } bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) { UString typeExt; int formatIndex = MethodMode.Type.FormatIndex; if (formatIndex < 0) { typeExt = kDefaultArcExt; } else { const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; if (!arcInfo.UpdateEnabled) return false; typeExt = arcInfo.GetMainExt(); } UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath, ArcNameMode); FOR_VECTOR (i, Commands) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode); } return true; } struct CUpdateProduceCallbackImp Z7_final: public IUpdateProduceCallback { const CObjectVector *_arcItems; CDirItemsStat *_stat; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp( const CObjectVector *a, CDirItemsStat *stat, IUpdateCallbackUI *callback): _arcItems(a), _stat(stat), _callback(callback) {} virtual HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override; }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex) { const CArcItem &ai = (*_arcItems)[arcIndex]; { CDirItemsStat &stat = *_stat; if (ai.IsDir) stat.NumDirs++; else if (ai.IsAltStream) { stat.NumAltStreams++; stat.AltStreamsSize += ai.Size; } else { stat.NumFiles++; stat.FilesSize += ai.Size; } } return _callback->ShowDeleteFile(ai.Name, ai.IsDir); } bool CRenamePair::Prepare() { if (RecursedType != NRecursedType::kNonRecursed) return false; if (!WildcardParsing) return true; return !DoesNameContainWildcard(OldName); } extern bool g_CaseSensitive; static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2) { for (unsigned i = 0;; i++) { wchar_t c1 = s1[i]; wchar_t c2 = s2[i]; if (c1 == 0 || c2 == 0) return i; if (c1 == c2) continue; if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2))) continue; if (IsPathSepar(c1) && IsPathSepar(c2)) continue; return i; } } bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const { unsigned num = CompareTwoNames(OldName, src); if (OldName[num] == 0) { if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1])) return false; } else { // OldName[num] != 0 // OldName = "1\1a.txt" // src = "1" if (!isFolder || src[num] != 0 || !IsPathSepar(OldName[num]) || OldName[num + 1] != 0) return false; } dest = NewName + src.Ptr(num); return true; } #ifdef SUPPORT_ALT_STREAMS int FindAltStreamColon_in_Path(const wchar_t *path); #endif static HRESULT Compress( const CUpdateOptions &options, bool isUpdatingItself, CCodecs *codecs, const CActionSet &actionSet, const CArc *arc, CArchivePath &archivePath, const CObjectVector &arcItems, Byte *processedItemsStatuses, const CDirItems &dirItems, const CDirItem *parentDirItem, CTempFiles &tempFiles, CMultiOutStream_Bunch &multiStreams, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback, CFinishArchiveStat &st) { CMyComPtr outArchive; int formatIndex = options.MethodMode.Type.FormatIndex; if (arc) { formatIndex = arc->FormatIndex; if (formatIndex < 0) return E_NOTIMPL; CMyComPtr archive2 = arc->Archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if (result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive)) #ifdef Z7_EXTERNAL_CODECS { CMyComPtr setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)) } } #endif } if (!outArchive) throw kUpdateIsNotSupoorted; // we need to set properties to get fileTimeType. RINOK(SetProperties(outArchive, options.MethodMode.Properties)) NFileTimeType::EEnum fileTimeType; { /* how we compare file_in_archive::MTime with dirItem.MTime for GetUpdatePairInfoList(): if (kpidMTime is not defined), external MTime of archive is used. before 22.00: if (kpidTimeType is defined) { kpidTimeType is used as precision. (kpidTimeType > kDOS) is not allowed. } else GetFileTimeType() value is used as precision. 22.00: if (kpidMTime is defined) { if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision. else { if (kpidTimeType is defined), kpidTimeType is used as precision. else GetFileTimeType() value is used as precision. } } else external MTime of archive is used as precision. */ UInt32 value; RINOK(outArchive->GetFileTimeType(&value)) // we support any future fileType here. fileTimeType = (NFileTimeType::EEnum)value; /* old 21.07 code: switch (value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } */ } // bool noTimestampExpected = false; { const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; // if (arcInfo.Flags_KeepName()) noTimestampExpected = true; if (arcInfo.Is_Xz() || arcInfo.Is_BZip2()) { /* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2, but we want to set timestamp without reduction to unix. */ // noTimestampExpected = true; fileTimeType = NFileTimeType::kNotDefined; // it means not defined } if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) return E_NOTIMPL; if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity()) return E_NOTIMPL; if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler()) return E_NOTIMPL; } CRecordVector updatePairs2; UStringVector newNames; CArcToDoStat stat2; if (options.RenamePairs.Size() != 0) { FOR_VECTOR (i, arcItems) { const CArcItem &ai = arcItems[i]; bool needRename = false; UString dest; if (ai.Censored) { FOR_VECTOR (j, options.RenamePairs) { const CRenamePair &rp = options.RenamePairs[j]; if (rp.GetNewPath(ai.IsDir, ai.Name, dest)) { needRename = true; break; } #ifdef SUPPORT_ALT_STREAMS if (ai.IsAltStream) { int colonPos = FindAltStreamColon_in_Path(ai.Name); if (colonPos >= 0) { UString mainName = ai.Name.Left((unsigned)colonPos); /* actually we must improve that code to support cases with folder renaming like: rn arc dir1\ dir2\ */ if (rp.GetNewPath(false, mainName, dest)) { needRename = true; dest.Add_Colon(); dest += ai.Name.Ptr((unsigned)(colonPos + 1)); break; } } } #endif } } CUpdatePair2 up2; up2.SetAs_NoChangeArcItem(ai.IndexInServer); if (needRename) { up2.NewProps = true; RINOK(arc->IsItem_Anti(i, up2.IsAnti)) up2.NewNameIndex = (int)newNames.Add(dest); } updatePairs2.Add(up2); } } else { CRecordVector updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL); } { FOR_VECTOR (i, updatePairs2) { const CUpdatePair2 &up = updatePairs2[i]; // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases)) if (up.NewData && !up.UseArcProps) { if (up.ExistOnDisk()) { CDirItemsStat2 &stat = stat2.NewData; const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex]; if (di.IsDir()) { if (up.IsAnti) stat.Anti_NumDirs++; else stat.NumDirs++; } #ifdef _WIN32 else if (di.IsAltStream) { if (up.IsAnti) stat.Anti_NumAltStreams++; else { stat.NumAltStreams++; stat.AltStreamsSize += di.Size; } } #endif else { if (up.IsAnti) stat.Anti_NumFiles++; else { stat.NumFiles++; stat.FilesSize += di.Size; } } } } else if (up.ArcIndex >= 0) { CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData); const CArcItem &ai = arcItems[(unsigned)up.ArcIndex]; if (ai.IsDir) { if (up.IsAnti) stat.Anti_NumDirs++; else stat.NumDirs++; } else if (ai.IsAltStream) { if (up.IsAnti) stat.Anti_NumAltStreams++; else { stat.NumAltStreams++; stat.AltStreamsSize += ai.Size; } } else { if (up.IsAnti) stat.Anti_NumFiles++; else { stat.NumFiles++; stat.FilesSize += ai.Size; } } } } RINOK(callback->SetNumItems(stat2)) } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); updateCallbackSpec->PreserveATime = options.PreserveATime; updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError; updateCallbackSpec->StdInMode = options.StdInMode; updateCallbackSpec->Callback = callback; if (arc) { // we set Archive to allow to transfer GetProperty requests back to DLL. updateCallbackSpec->Archive = arc->Archive; } updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ParentDirItem = parentDirItem; updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val; updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val; updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val; updateCallbackSpec->Arc = arc; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses; { const UString arcPath = archivePath.GetFinalPath(); updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath); } if (options.RenamePairs.Size() != 0) updateCallbackSpec->NewNames = &newNames; if (options.SetArcMTime) { // updateCallbackSpec->Need_ArcMTime_Report = true; updateCallbackSpec->Need_LatestMTime = true; } CMyComPtr outSeekStream; CMyComPtr outStream; if (!options.StdOutMode) { FString dirPrefix; if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) throw 1417161; CreateComplexDir(dirPrefix); } COutFileStream *outStreamSpec = NULL; CStdOutFileStream *stdOutFileStreamSpec = NULL; CMultiOutStream *volStreamSpec = NULL; if (options.VolumesSizes.Size() == 0) { if (options.StdOutMode) { stdOutFileStreamSpec = new CStdOutFileStream; outStream = stdOutFileStreamSpec; } else { outStreamSpec = new COutFileStream; outSeekStream = outStreamSpec; outStream = outSeekStream; bool isOK = false; FString realPath; for (unsigned i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { archivePath.TempPostfix.Empty(); archivePath.TempPostfix.Add_UInt32(i); } realPath = archivePath.GetTempPath(); } else realPath = us2fs(archivePath.GetFinalPath()); if (outStreamSpec->Create_NEW(realPath)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) return errorInfo.SetFromLastError("cannot open file", realPath); } } else { if (options.StdOutMode) return E_FAIL; if (arc && arc->GetGlobalOffset() > 0) return E_NOTIMPL; volStreamSpec = new CMultiOutStream(); outSeekStream = volStreamSpec; outStream = outSeekStream; volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath()); volStreamSpec->Prefix.Add_Dot(); volStreamSpec->Init(options.VolumesSizes); { CMultiOutStream_Rec &rec = multiStreams.Items.AddNew(); rec.Spec = volStreamSpec; rec.Ref = rec.Spec; } /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension; */ } if (options.SfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(options.SfxModule)) return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule); CMyComPtr sfxOutStream; COutFileStream *outStreamSpec2 = NULL; if (options.VolumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec2 = new COutFileStream; sfxOutStream = outStreamSpec2; const FString realPath = us2fs(archivePath.GetFinalPath()); if (!outStreamSpec2->Create_NEW(realPath)) return errorInfo.SetFromLastError("cannot open file", realPath); } { UInt64 sfxSize; RINOK(sfxStreamSpec->GetSize(&sfxSize)) RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize)) } RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)) if (outStreamSpec2) { RINOK(outStreamSpec2->Close()) } } CMyComPtr tailStream; if (options.SfxMode || !arc || arc->ArcStreamOffset == 0) tailStream = outStream; else { // Int64 globalOffset = arc->GetGlobalOffset(); RINOK(InStream_SeekToBegin(arc->InStream)) RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL)) if (options.StdOutMode) tailStream = outStream; else { CTailOutStream *tailStreamSpec = new CTailOutStream; tailStream = tailStreamSpec; tailStreamSpec->Stream = outSeekStream; tailStreamSpec->Offset = arc->ArcStreamOffset; tailStreamSpec->Init(); } } CFiTime ft; FiTime_Clear(ft); bool ft_Defined = false; { FOR_VECTOR (i, updatePairs2) { const CUpdatePair2 &pair2 = updatePairs2[i]; CFiTime ft2; FiTime_Clear(ft2); bool ft2_Defined = false; /* we use full precision of dirItem, if dirItem is defined and (dirItem will be used or dirItem is sameTime in dir and arc */ if (pair2.DirIndex >= 0 && (pair2.NewProps || pair2.IsSameTime)) { ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime; ft2_Defined = true; } else if (pair2.UseArcProps && pair2.ArcIndex >= 0) { const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex]; if (arcItem.MTime.Def) { arcItem.MTime.Write_To_FiTime(ft2); ft2_Defined = true; } } if (ft2_Defined) { if (!ft_Defined || Compare_FiTime(&ft, &ft2) < 0) { ft = ft2; ft_Defined = true; } } } /* if (fileTimeType != NFileTimeType::kNotDefined) FiTime_Normalize_With_Prec(ft, fileTimeType); */ } if (volStreamSpec && options.SetArcMTime && ft_Defined) { volStreamSpec->MTime = ft; volStreamSpec->MTime_Defined = true; } HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback); // callback->Finalize(); RINOK(result) if (!updateCallbackSpec->AreAllFilesClosed()) { errorInfo.Message = "There are unclosed input files:"; errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths; return E_FAIL; } if (options.SetArcMTime) { // bool needNormalizeAfterStream; // needParse; /* if (updateCallbackSpec->ArcMTime_WasReported) { isDefined = updateCallbackSpec->Reported_ArcMTime.Def; if (isDefined) updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft); else fileTimeType = NFileTimeType::kNotDefined; } if (!isDefined) */ { if (updateCallbackSpec->LatestMTime_Defined) { // CArcTime at = StreamCallback_ArcMTime; // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft); // we must normalize with precision from archive; if (!ft_Defined || Compare_FiTime(&ft, &updateCallbackSpec->LatestMTime) < 0) ft = updateCallbackSpec->LatestMTime; ft_Defined = true; } /* if (fileTimeType != NFileTimeType::kNotDefined) FiTime_Normalize_With_Prec(ft, fileTimeType); */ } // if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0) if (ft_Defined) { // we ignore set time errors here. // note that user could move some finished volumes to another folder. if (outStreamSpec) outStreamSpec->SetMTime(&ft); else if (volStreamSpec) volStreamSpec->SetMTime_Final(ft); } } if (callback) { UInt64 size = 0; if (outStreamSpec) outStreamSpec->GetSize(&size); else if (stdOutFileStreamSpec) size = stdOutFileStreamSpec->GetSize(); else size = volStreamSpec->GetSize(); st.OutArcFileSize = size; } if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) { result = volStreamSpec->FinalFlush_and_CloseFiles(st.NumVolumes); st.IsMultiVolMode = true; } RINOK(result) if (processedItemsStatuses) { FOR_VECTOR (i, updatePairs2) { const CUpdatePair2 &up = updatePairs2[i]; if (up.NewData && up.DirIndex >= 0) { const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex]; if (di.AreReparseData() || (!di.IsDir() && di.Size == 0)) processedItemsStatuses[(unsigned)up.DirIndex] = 1; } } } return result; } static bool Censor_AreAllAllowed(const NWildcard::CCensor &censor) { if (censor.Pairs.Size() != 1) return false; const NWildcard::CPair &pair = censor.Pairs[0]; /* Censor_CheckPath() ignores (CPair::Prefix). So we also ignore (CPair::Prefix) here */ // if (!pair.Prefix.IsEmpty()) return false; return pair.Head.AreAllAllowed(); } bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item) { bool finded = false; FOR_VECTOR (i, censor.Pairs) { /* (CPair::Prefix) in not used for matching items in archive. So we ignore (CPair::Prefix) here */ bool include; if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include)) { // Check it and FIXME !!!! // here we can exclude item via some Pair, that is still allowed by another Pair if (!include) return false; finded = true; } } return finded; } static HRESULT EnumerateInArchiveItems( // bool storeStreamsMode, const NWildcard::CCensor &censor, const CArc &arc, CObjectVector &arcItems) { arcItems.Clear(); UInt32 numItems; IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)) arcItems.ClearAndReserve(numItems); CReadArcItem item; const bool allFilesAreAllowed = Censor_AreAllAllowed(censor); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(arc.GetItem(i, item)) ai.Name = item.Path; ai.IsDir = item.IsDir; ai.IsAltStream = #ifdef SUPPORT_ALT_STREAMS item.IsAltStream; #else false; #endif /* if (!storeStreamsMode && ai.IsAltStream) continue; */ if (allFilesAreAllowed) ai.Censored = true; else ai.Censored = Censor_CheckPath(censor, item); // ai.MTime will be set to archive MTime, if not present in archive item RINOK(arc.GetItem_MTime(i, ai.MTime)) RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined)) ai.IndexInServer = i; arcItems.AddInReserved(ai); } return S_OK; } #if defined(_WIN32) && !defined(UNDER_CE) #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif extern "C" { #ifdef MAPI_FORCE_UNICODE #define Z7_WIN_LPMAPISENDMAILW LPMAPISENDMAILW #define Z7_WIN_MapiFileDescW MapiFileDescW #define Z7_WIN_MapiMessageW MapiMessageW #define Z7_WIN_MapiRecipDescW MapiRecipDescW #else typedef struct { ULONG ulReserved; ULONG ulRecipClass; PWSTR lpszName; PWSTR lpszAddress; ULONG ulEIDSize; PVOID lpEntryID; } Z7_WIN_MapiRecipDescW, *Z7_WIN_lpMapiRecipDescW; typedef struct { ULONG ulReserved; ULONG flFlags; ULONG nPosition; PWSTR lpszPathName; PWSTR lpszFileName; PVOID lpFileType; } Z7_WIN_MapiFileDescW, *Z7_WIN_lpMapiFileDescW; typedef struct { ULONG ulReserved; PWSTR lpszSubject; PWSTR lpszNoteText; PWSTR lpszMessageType; PWSTR lpszDateReceived; PWSTR lpszConversationID; FLAGS flFlags; Z7_WIN_lpMapiRecipDescW lpOriginator; ULONG nRecipCount; Z7_WIN_lpMapiRecipDescW lpRecips; ULONG nFileCount; Z7_WIN_lpMapiFileDescW lpFiles; } Z7_WIN_MapiMessageW, *Z7_WIN_lpMapiMessageW; typedef ULONG (FAR PASCAL Z7_WIN_MAPISENDMAILW)( LHANDLE lhSession, ULONG_PTR ulUIParam, Z7_WIN_lpMapiMessageW lpMessage, FLAGS flFlags, ULONG ulReserved ); typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW; #endif // MAPI_FORCE_UNICODE } #endif // _WIN32 HRESULT UpdateArchive( CCodecs *codecs, const CObjectVector &types, const UString &cmdArcPath2, NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback, bool needSetPath) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (types.Size() > 1) return E_NOTIMPL; bool renameMode = !options.RenamePairs.IsEmpty(); if (renameMode) { if (options.Commands.Size() != 1) return E_FAIL; } if (options.DeleteAfterCompressing) { if (options.Commands.Size() != 1) return E_NOTIMPL; const CActionSet &as = options.Commands[0].ActionSet; for (unsigned i = 2; i < NPairState::kNumValues; i++) if (as.StateActions[i] != NPairAction::kCompress) return E_NOTIMPL; } censor.AddPathsToCensor(options.PathMode); #ifdef _WIN32 ConvertToLongNames(censor); #endif censor.ExtendExclude(); if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = "rsfx"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = "SFX file is not specified"; return E_FAIL; } bool found = false; if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0) { const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule; if (NFind::DoesFileExist_FollowLink(fullName)) { options.SfxModule = fullName; found = true; } } if (!found) { if (!NFind::DoesFileExist_FollowLink(options.SfxModule)) return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule); } } CArchiveLink arcLink; if (needSetPath) { if (!options.InitFormatIndex(codecs, types, cmdArcPath2) || !options.SetArcPath(codecs, cmdArcPath2)) return E_NOTIMPL; } UString arcPath = options.ArchivePath.GetFinalPath(); if (!options.VolumesSizes.IsEmpty()) { arcPath = options.ArchivePath.GetFinalVolPath(); arcPath += ".001"; } if (cmdArcPath2.IsEmpty()) { if (options.MethodMode.Type.FormatIndex < 0) throw "type of archive is not specified"; } else { NFind::CFileInfo fi; if (!fi.Find_FollowLink(us2fs(arcPath))) { if (renameMode) throw "can't find archive"; if (options.MethodMode.Type.FormatIndex < 0) { if (!options.SetArcPath(codecs, cmdArcPath2)) return E_NOTIMPL; } } else { if (fi.IsDir()) return errorInfo.SetFromError_DWORD("There is a folder with the name of archive", us2fs(arcPath), #ifdef _WIN32 ERROR_ACCESS_DENIED #else EISDIR #endif ); #ifdef _WIN32 if (fi.IsDevice) return E_NOTIMPL; #endif if (!options.StdOutMode && options.UpdateArchiveItself) if (fi.IsReadOnly()) { return errorInfo.SetFromError_DWORD("The file is read-only", us2fs(arcPath), #ifdef _WIN32 ERROR_ACCESS_DENIED #else EACCES #endif ); } if (options.VolumesSizes.Size() > 0) { errorInfo.FileNames.Add(us2fs(arcPath)); // errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = kUpdateIsNotSupported_MultiVol; return E_NOTIMPL; } CObjectVector types2; // change it. if (options.MethodMode.Type_Defined) types2.Add(options.MethodMode.Type); // We need to set Properties to open archive only in some cases (WIM archives). CIntVector excl; COpenOptions op; #ifndef Z7_SFX op.props = &options.MethodMode.Properties; #endif op.codecs = codecs; op.types = &types2; op.excludedFormats = ! op.stdInMode = false; op.stream = NULL; op.filePath = arcPath; RINOK(callback->StartOpenArchive(arcPath)) HRESULT result = arcLink.Open_Strict(op, openCallback); if (result == E_ABORT) return result; HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result); /* if (result == S_FALSE) return E_FAIL; */ RINOK(res2) RINOK(result) if (arcLink.VolumePaths.Size() > 1) { // errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = kUpdateIsNotSupported_MultiVol; return E_NOTIMPL; } CArc &arc = arcLink.Arcs.Back(); arc.MTime.Def = #ifdef _WIN32 !fi.IsDevice; #else true; #endif if (arc.MTime.Def) arc.MTime.Set_From_FiTime(fi.MTime); if (arc.ErrorInfo.ThereIsTail) { // errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = "There is some data block after the end of the archive"; return E_NOTIMPL; } if (options.MethodMode.Type.FormatIndex < 0) { options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex; if (!options.SetArcPath(codecs, cmdArcPath2)) return E_NOTIMPL; } } } if (options.MethodMode.Type.FormatIndex < 0) { options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType); if (options.MethodMode.Type.FormatIndex < 0) return E_NOTIMPL; } bool thereIsInArchive = arcLink.IsOpen; if (!thereIsInArchive && renameMode) return E_FAIL; CDirItems dirItems; dirItems.Callback = callback; CDirItem parentDirItem; CDirItem *parentDirItem_Ptr = NULL; /* FStringVector requestedPaths; FStringVector *requestedPaths_Ptr = NULL; if (options.DeleteAfterCompressing) requestedPaths_Ptr = &requestedPaths; */ if (options.StdInMode) { CDirItem di; // di.ClearBase(); // di.Size = (UInt64)(Int64)-1; if (!di.SetAs_StdInFile()) return GetLastError_noZero_HRESULT(); di.Name = options.StdInFileName; // di.Attrib_IsDefined = false; // NTime::GetCurUtc_FiTime(di.MTime); // di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; if (!renameMode) FOR_VECTOR (i, options.Commands) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { RINOK(callback->StartScanning()) dirItems.SymLinks = options.SymLinks.Val; #if defined(_WIN32) && !defined(UNDER_CE) dirItems.ReadSecure = options.NtSecurity.Val; #endif dirItems.ScanAltStreams = options.AltStreams.Val; dirItems.ExcludeDirItems = censor.ExcludeDirItems; dirItems.ExcludeFileItems = censor.ExcludeFileItems; dirItems.ShareForWrite = options.OpenShareForWrite; #ifndef _WIN32 dirItems.StoreOwnerName = options.StoreOwnerName.Val; #endif const HRESULT res = EnumerateItems(censor, options.PathMode, UString(), // options.AddPathPrefix, dirItems); if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = "Scanning error"; return res; } RINOK(callback->FinishScanning(dirItems.Stat)) // 22.00: we don't need parent folder, if absolute path mode if (options.PathMode != NWildcard::k_AbsPath) if (censor.Pairs.Size() == 1) { NFind::CFileInfo fi; FString prefix = us2fs(censor.Pairs[0].Prefix); prefix.Add_Dot(); // UString prefix = censor.Pairs[0].Prefix; /* if (prefix.Back() == WCHAR_PATH_SEPARATOR) { prefix.DeleteBack(); } */ if (fi.Find(prefix)) if (fi.IsDir()) { parentDirItem.Copy_From_FileInfoBase(fi); parentDirItem_Ptr = &parentDirItem; int secureIndex = -1; #if defined(_WIN32) && !defined(UNDER_CE) if (options.NtSecurity.Val) dirItems.AddSecurityItem(prefix, secureIndex); #endif parentDirItem.SecureIndex = secureIndex; } } } } FString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 CTempDir tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) ap.TempPrefix = options.WorkingDir; else ap.TempPrefix = us2fs(ap.Prefix); NormalizeDirPathPrefix(ap.TempPrefix); } } unsigned ci; // self including protection if (options.DeleteAfterCompressing) { for (ci = 0; ci < options.Commands.Size(); ci++) { CArchivePath &ap = options.Commands[ci].ArchivePath; const FString path = us2fs(ap.GetFinalPath()); // maybe we must compare absolute paths path here FOR_VECTOR (i, dirItems.Items) { const FString phyPath = dirItems.GetPhyPath(i); if (phyPath == path) { UString s; s = "It is not allowed to include archive to itself"; s.Add_LF(); s += fs2us(path); throw s; } } } } for (ci = 0; ci < options.Commands.Size(); ci++) { CArchivePath &ap = options.Commands[ci].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = fs2us(tempDirPrefix); // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (!options.StdOutMode && (ci > 0 || !createTempFile)) { const FString path = us2fs(ap.GetFinalPath()); if (NFind::DoesFileOrDirExist(path)) { errorInfo.SystemError = ERROR_FILE_EXISTS; errorInfo.Message = "The file already exists"; errorInfo.FileNames.Add(path); return errorInfo.Get_HRESULT_Error(); } } } CObjectVector arcItems; if (thereIsInArchive) { RINOK(EnumerateInArchiveItems( // options.StoreAltStreams, censor, arcLink.Arcs.Back(), arcItems)) } /* FStringVector processedFilePaths; FStringVector *processedFilePaths_Ptr = NULL; if (options.DeleteAfterCompressing) processedFilePaths_Ptr = &processedFilePaths; */ CByteBuffer processedItems; if (options.DeleteAfterCompressing) { const unsigned num = dirItems.Items.Size(); processedItems.Alloc(num); for (unsigned i = 0; i < num; i++) processedItems[i] = 0; } CMultiOutStream_Bunch multiStreams; /* #ifndef Z7_NO_CRYPTO if (arcLink.PasswordWasAsked) { // We set password, if open have requested password RINOK(callback->SetPassword(arcLink.Password)); } #endif */ for (ci = 0; ci < options.Commands.Size(); ci++) { const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL; CUpdateArchiveCommand &command = options.Commands[ci]; UString name; bool isUpdating; if (options.StdOutMode) { name = "stdout"; isUpdating = thereIsInArchive; } else { name = command.ArchivePath.GetFinalPath(); isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive); } RINOK(callback->StartArchive(name, isUpdating)) CFinishArchiveStat st; RINOK(Compress(options, isUpdating, codecs, command.ActionSet, arc, command.ArchivePath, arcItems, options.DeleteAfterCompressing ? (Byte *)processedItems : NULL, dirItems, parentDirItem_Ptr, tempFiles, multiStreams, errorInfo, callback, st)) RINOK(callback->FinishArchive(st)) } if (thereIsInArchive) { RINOK(arcLink.Close()) arcLink.Release(); } multiStreams.DisableDeletion(); RINOK(multiStreams.Destruct()) tempFiles.Paths.Clear(); if (createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const FString &tempPath = ap.GetTempPath(); // DWORD attrib = 0; if (thereIsInArchive) { // attrib = NFind::GetFileAttrib(us2fs(arcPath)); if (!DeleteFileAlways(us2fs(arcPath))) return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); } if (!MyMoveFile(tempPath, us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = "cannot move the file"; if (errorInfo.SystemError == ERROR_INVALID_PARAMETER) { NFind::CFileInfo fi; if (fi.Find(tempPath) && fi.Size > (UInt32)(Int32)-1) { // bool isFsDetected = false; // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected) { errorInfo.Message.Add_LF(); errorInfo.Message += "Archive file size exceeds 4 GB"; } } } errorInfo.FileNames.Add(tempPath); errorInfo.FileNames.Add(us2fs(arcPath)); return errorInfo.Get_HRESULT_Error(); } /* if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) { DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath)); if (attrib2 != INVALID_FILE_ATTRIBUTES) NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY); } */ } catch(...) { throw; } } #if defined(_WIN32) && !defined(UNDER_CE) Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(FTEXT("Mapi32.dll"))) { errorInfo.SetFromLastError("cannot load Mapi32.dll"); return errorInfo.Get_HRESULT_Error(); } FStringVector fullPaths; unsigned i; for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; const FString finalPath = us2fs(ap.GetFinalPath()); FString arcPath2; if (!MyGetFullPathName(finalPath, arcPath2)) return errorInfo.SetFromLastError("GetFullPathName error", finalPath); fullPaths.Add(arcPath2); } /* LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function"); return errorInfo.Get_HRESULT_Error(); } */ const Z7_WIN_LPMAPISENDMAILW sendMailW = Z7_GET_PROC_ADDRESS( Z7_WIN_LPMAPISENDMAILW, mapiLib.Get_HMODULE(), "MAPISendMailW"); if (sendMailW) { CCurrentDirRestorer curDirRestorer; UStringVector paths; UStringVector names; for (i = 0; i < fullPaths.Size(); i++) { const UString arcPath2 = fs2us(fullPaths[i]); const UString fileName = ExtractFileNameFromPath(arcPath2); paths.Add(arcPath2); names.Add(fileName); // Warning!!! MAPISendDocuments function changes Current directory // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } CRecordVector files; files.ClearAndSetSize(paths.Size()); for (i = 0; i < paths.Size(); i++) { Z7_WIN_MapiFileDescW &f = files[i]; memset(&f, 0, sizeof(f)); f.nPosition = 0xFFFFFFFF; f.lpszPathName = paths[i].Ptr_non_const(); f.lpszFileName = names[i].Ptr_non_const(); } { Z7_WIN_MapiMessageW m; memset(&m, 0, sizeof(m)); m.nFileCount = files.Size(); m.lpFiles = files.NonConstData(); const UString addr (options.EMailAddress); Z7_WIN_MapiRecipDescW rec; if (!addr.IsEmpty()) { memset(&rec, 0, sizeof(rec)); rec.ulRecipClass = MAPI_TO; rec.lpszAddress = addr.Ptr_non_const(); m.nRecipCount = 1; m.lpRecips = &rec; } sendMailW((LHANDLE)0, 0, &m, MAPI_DIALOG, 0); } } else { const LPMAPISENDMAIL sendMail = Z7_GET_PROC_ADDRESS( LPMAPISENDMAIL, mapiLib.Get_HMODULE(), "MAPISendMail"); if (!sendMail) { errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function"); return errorInfo.Get_HRESULT_Error(); } CCurrentDirRestorer curDirRestorer; AStringVector paths; AStringVector names; for (i = 0; i < fullPaths.Size(); i++) { const UString arcPath2 = fs2us(fullPaths[i]); const UString fileName = ExtractFileNameFromPath(arcPath2); paths.Add(GetAnsiString(arcPath2)); names.Add(GetAnsiString(fileName)); // const AString path (GetAnsiString(arcPath2)); // const AString name (GetAnsiString(fileName)); // Warning!!! MAPISendDocuments function changes Current directory // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } CRecordVector files; files.ClearAndSetSize(paths.Size()); for (i = 0; i < paths.Size(); i++) { MapiFileDesc &f = files[i]; memset(&f, 0, sizeof(f)); f.nPosition = 0xFFFFFFFF; f.lpszPathName = paths[i].Ptr_non_const(); f.lpszFileName = names[i].Ptr_non_const(); } { MapiMessage m; memset(&m, 0, sizeof(m)); m.nFileCount = files.Size(); m.lpFiles = files.NonConstData(); const AString addr (GetAnsiString(options.EMailAddress)); MapiRecipDesc rec; if (!addr.IsEmpty()) { memset(&rec, 0, sizeof(rec)); rec.ulRecipClass = MAPI_TO; rec.lpszAddress = addr.Ptr_non_const(); m.nRecipCount = 1; m.lpRecips = &rec; } sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0); } } } #endif if (options.DeleteAfterCompressing) { CRecordVector pairs; FStringVector foldersNames; unsigned i; for (i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; const FString phyPath = dirItems.GetPhyPath(i); if (dirItem.IsDir()) { CDirPathSortPair pair; pair.Index = i; pair.SetNumSlashes(phyPath); pairs.Add(pair); } else { // 21.04: we have set processedItems[*] before for all required items if (processedItems[i] != 0 // || dirItem.Size == 0 // || dirItem.AreReparseData() ) { NFind::CFileInfo fileInfo; /* if (!SymLinks), we follow link here, similar to (dirItem) filling */ if (fileInfo.Find(phyPath, !options.SymLinks.Val)) { bool is_SameSize = false; if (options.SymLinks.Val && dirItem.AreReparseData()) { /* (dirItem.Size = dirItem.ReparseData.Size()) was set before. So we don't compare sizes for that case here */ is_SameSize = fileInfo.IsOsSymLink(); } else is_SameSize = (fileInfo.Size == dirItem.Size); if (is_SameSize && Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0 && Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0) { RINOK(callback->DeletingAfterArchiving(phyPath, false)) DeleteFileAlways(phyPath); } } } else { // file was skipped by some reason. We can throw error for debug: /* errorInfo.SystemError = 0; errorInfo.Message = "file was not processed"; errorInfo.FileNames.Add(phyPath); return E_FAIL; */ } } } pairs.Sort2(); for (i = 0; i < pairs.Size(); i++) { const FString phyPath = dirItems.GetPhyPath(pairs[i].Index); if (NFind::DoesDirExist(phyPath)) { RINOK(callback->DeletingAfterArchiving(phyPath, true)) RemoveDir(phyPath); } } RINOK(callback->FinishDeletingAfterArchiving()) } return S_OK; } tmp41wklro_/CPP/7zip/UI/Common/Update.h0000444000175000001440000001247614413342460020627 0ustar nabijaczleweliusers// Update.h #ifndef ZIP7_INC_COMMON_UPDATE_H #define ZIP7_INC_COMMON_UPDATE_H #include "../../../Common/Wildcard.h" #include "ArchiveOpenCallback.h" #include "LoadCodecs.h" #include "OpenArchive.h" #include "Property.h" #include "UpdateAction.h" #include "UpdateCallback.h" #include "DirItem.h" enum EArcNameMode { k_ArcNameMode_Smart, k_ArcNameMode_Exact, k_ArcNameMode_Add }; struct CArchivePath { UString OriginalPath; UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; FString TempPrefix; // path(folder) for temp location FString TempPostfix; CArchivePath(): Temp(false) {} void ParseFromPath(const UString &path, EArcNameMode mode); UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const; UString GetFinalVolPath() const; FString GetTempPath() const; }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { bool Type_Defined; COpenType Type; CObjectVector Properties; CCompressionMethodMode(): Type_Defined(false) {} }; namespace NRecursedType { enum EEnum { kRecursed, kWildcardOnlyRecursed, kNonRecursed };} struct CRenamePair { UString OldName; UString NewName; bool WildcardParsing; NRecursedType::EEnum RecursedType; CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {} bool Prepare(); bool GetNewPath(bool isFolder, const UString &src, UString &dest) const; }; struct CUpdateOptions { bool UpdateArchiveItself; bool SfxMode; bool PreserveATime; bool OpenShareForWrite; bool StopAfterOpenError; bool StdInMode; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; bool DeleteAfterCompressing; bool SetArcMTime; CBoolPair NtSecurity; CBoolPair AltStreams; CBoolPair HardLinks; CBoolPair SymLinks; CBoolPair StoreOwnerId; CBoolPair StoreOwnerName; EArcNameMode ArcNameMode; NWildcard::ECensorPathMode PathMode; CCompressionMethodMode MethodMode; CObjectVector Commands; CArchivePath ArchivePath; FString SfxModule; UString StdInFileName; UString EMailAddress; FString WorkingDir; // UString AddPathPrefix; CObjectVector RenamePairs; CRecordVector VolumesSizes; bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath); bool SetArcPath(const CCodecs *codecs, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), PreserveATime(false), OpenShareForWrite(false), StopAfterOpenError(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), DeleteAfterCompressing(false), SetArcMTime(false), ArcNameMode(k_ArcNameMode_Smart), PathMode(NWildcard::k_RelatPath) {} void SetActionCommand_Add() { Commands.Clear(); CUpdateArchiveCommand c; c.ActionSet = NUpdateArchive::k_ActionSet_Add; Commands.Add(c); } }; struct CUpdateErrorInfo { DWORD SystemError; // it's DWORD (WRes) only; AString Message; FStringVector FileNames; bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); } HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); } void SetFromLastError(const char *message); HRESULT SetFromLastError(const char *message, const FString &fileName); HRESULT SetFromError_DWORD(const char *message, const FString &fileName, DWORD error); CUpdateErrorInfo(): SystemError(0) {} }; struct CFinishArchiveStat { UInt64 OutArcFileSize; unsigned NumVolumes; bool IsMultiVolMode; CFinishArchiveStat(): OutArcFileSize(0), NumVolumes(0), IsMultiVolMode(false) {} }; Z7_PURE_INTERFACES_BEGIN // INTERFACE_IUpdateCallbackUI(x) // INTERFACE_IDirItemsCallback(x) #define Z7_IFACEN_IUpdateCallbackUI2(x) \ virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x \ virtual HRESULT StartScanning() x \ virtual HRESULT FinishScanning(const CDirItemsStat &st) x \ virtual HRESULT StartOpenArchive(const wchar_t *name) x \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x \ virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \ virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \ virtual HRESULT FinishDeletingAfterArchiving() x \ DECLARE_INTERFACE(IUpdateCallbackUI2): public IUpdateCallbackUI, public IDirItemsCallback { Z7_IFACE_PURE(IUpdateCallbackUI2) }; Z7_PURE_INTERFACES_END HRESULT UpdateArchive( CCodecs *codecs, const CObjectVector &types, const UString &cmdArcPath2, NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback, bool needSetPath); #endif tmp41wklro_/CPP/7zip/UI/Common/UpdateAction.cpp0000444000175000001440000000230512330166726022313 0ustar nabijaczleweliusers// UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet k_ActionSet_Add = {{ NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }}; const CActionSet k_ActionSet_Update = {{ NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }}; const CActionSet k_ActionSet_Fresh = {{ NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }}; const CActionSet k_ActionSet_Sync = {{ NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }}; const CActionSet k_ActionSet_Delete = {{ NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }}; } tmp41wklro_/CPP/7zip/UI/Common/UpdateAction.h0000444000175000001440000000263514357314620021765 0ustar nabijaczleweliusers// UpdateAction.h #ifndef ZIP7_INC_UPDATE_ACTION_H #define ZIP7_INC_UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const unsigned kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool IsEqualTo(const CActionSet &a) const { for (unsigned i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] != a.StateActions[i]) return false; return true; } bool NeedScanning() const { unsigned i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet k_ActionSet_Add; extern const CActionSet k_ActionSet_Update; extern const CActionSet k_ActionSet_Fresh; extern const CActionSet k_ActionSet_Sync; extern const CActionSet k_ActionSet_Delete; } #endif tmp41wklro_/CPP/7zip/UI/Common/UpdateCallback.cpp0000444000175000001440000006655714571117200022605 0ustar nabijaczleweliusers// UpdateCallback.cpp #include "StdAfx.h" // #include #ifndef _WIN32 // #include // #include // for major()/minor(): #if defined(__APPLE__) || defined(__DragonFly__) || \ defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #endif // _WIN32 #ifndef Z7_ST #include "../../../Windows/Synchronization.h" #endif #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Common/UTFConvert.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/PropVariant.h" #include "../../Common/StreamObjects.h" #include "UpdateCallback.h" #if defined(_WIN32) && !defined(UNDER_CE) #define Z7_USE_SECURITY_CODE #include "../../../Windows/SecurityUtils.h" #endif using namespace NWindows; using namespace NFile; #ifndef Z7_ST static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif #ifdef Z7_USE_SECURITY_CODE bool InitLocalPrivileges(); #endif CArchiveUpdateCallback::CArchiveUpdateCallback(): PreserveATime(false), ShareForWrite(false), StopAfterOpenError(false), StdInMode(false), KeepOriginalItemNames(false), StoreNtSecurity(false), StoreHardLinks(false), StoreSymLinks(false), #ifndef _WIN32 StoreOwnerId(false), StoreOwnerName(false), #endif /* , Need_ArcMTime_Report(false), , ArcMTime_WasReported(false), */ Need_LatestMTime(false), LatestMTime_Defined(false), Callback(NULL), DirItems(NULL), ParentDirItem(NULL), Arc(NULL), ArcItems(NULL), UpdatePairs(NULL), NewNames(NULL), Comment(NULL), CommentIndex(-1), ProcessedItemsStatuses(NULL), _hardIndex_From((UInt32)(Int32)-1) { #ifdef Z7_USE_SECURITY_CODE _saclEnabled = InitLocalPrivileges(); #endif } Z7_COM7F_IMF(CArchiveUpdateCallback::SetTotal(UInt64 size)) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* static const CStatProp kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; Z7_COM7F_IMF(CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProps, Z7_ARRAY_SIZE(kProps), enumerator); } */ Z7_COM7F_IMF(CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()) const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData) *newData = BoolToInt(up.NewData); if (newProps) *newProps = BoolToInt(up.NewProps); if (indexInArchive) { *indexInArchive = (UInt32)(Int32)-1; if (up.ExistInArchive()) *indexInArchive = ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex; } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)) { NCOM::CPropVariant prop; switch (propID) { case kpidIsDir: prop = true; break; case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->GetWinAttrib(); break; case kpidCTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->CTime); break; case kpidATime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->ATime); break; case kpidMTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->MTime); break; case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break; default: break; } prop.Detach(value); return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)) { *parentType = NParentType::kDir; *parent = (UInt32)(Int32)-1; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)) { *numProps = 0; if (StoreNtSecurity) *numProps = 1; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)) { *name = NULL; *propID = kpidNtSecure; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetRootRawProp(PROPID propID , const void **data, UInt32 *dataSize, UInt32 *propType)) { #ifndef Z7_USE_SECURITY_CODE UNUSED_VAR(propID) #endif *data = NULL; *dataSize = 0; *propType = 0; if (!StoreNtSecurity) return S_OK; #ifdef Z7_USE_SECURITY_CODE if (propID == kpidNtSecure) { if (StdInMode) return S_OK; if (ParentDirItem) { if (ParentDirItem->SecureIndex < 0) return S_OK; const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)ParentDirItem->SecureIndex]; *data = buf; *dataSize = (UInt32)buf.Size(); *propType = NPropDataType::kRaw; return S_OK; } if (Arc && Arc->GetRootProps) return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType); } #endif return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) { *data = NULL; *dataSize = 0; *propType = 0; if (propID == kpidNtSecure || propID == kpidNtReparse) { if (StdInMode) return S_OK; const CUpdatePair2 &up = (*UpdatePairs)[index]; if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps) return Arc->GetRawProps->GetRawProp( ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, data, dataSize, propType); { /* if (!up.NewData) return E_FAIL; */ if (up.IsAnti) return S_OK; #if defined(_WIN32) && !defined(UNDER_CE) const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; #endif #ifdef Z7_USE_SECURITY_CODE if (propID == kpidNtSecure) { if (!StoreNtSecurity) return S_OK; if (di.SecureIndex < 0) return S_OK; const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)di.SecureIndex]; *data = buf; *dataSize = (UInt32)buf.Size(); *propType = NPropDataType::kRaw; } else #endif if (propID == kpidNtReparse) { if (!StoreSymLinks) return S_OK; #if defined(_WIN32) && !defined(UNDER_CE) // we use ReparseData2 instead of ReparseData for WIM format const CByteBuffer *buf = &di.ReparseData2; if (buf->Size() == 0) buf = &di.ReparseData; if (buf->Size() != 0) { *data = *buf; *dataSize = (UInt32)buf->Size(); *propType = NPropDataType::kRaw; } #endif } return S_OK; } } return S_OK; } #if defined(_WIN32) && !defined(UNDER_CE) static UString GetRelativePath(const UString &to, const UString &from) { UStringVector partsTo, partsFrom; SplitPathToParts(to, partsTo); SplitPathToParts(from, partsFrom); unsigned i; for (i = 0;; i++) { if (i + 1 >= partsFrom.Size() || i + 1 >= partsTo.Size()) break; if (CompareFileNames(partsFrom[i], partsTo[i]) != 0) break; } if (i == 0) { #ifdef _WIN32 if (NName::IsDrivePath(to) || NName::IsDrivePath(from)) return to; #endif } UString s; unsigned k; for (k = i + 1; k < partsFrom.Size(); k++) s += ".." STRING_PATH_SEPARATOR; for (k = i; k < partsTo.Size(); k++) { if (k != i) s.Add_PathSepar(); s += partsTo[k]; } return s; } #endif Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NCOM::CPropVariant prop; if (up.NewData) { /* if (propID == kpidIsHardLink) { prop = _isHardLink; prop.Detach(value); return S_OK; } */ if (propID == kpidSymLink) { if (index == _hardIndex_From) { prop.Detach(value); return S_OK; } #if !defined(UNDER_CE) if (up.DirIndex >= 0) { const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; #ifdef _WIN32 // if (di.IsDir()) { CReparseAttr attr; if (attr.Parse(di.ReparseData, di.ReparseData.Size())) { const UString simpleName = attr.GetPath(); if (!attr.IsSymLink_WSL() && attr.IsRelative_Win()) prop = simpleName; else { const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); FString fullPath; if (NDir::MyGetFullPathName(phyPath, fullPath)) { prop = GetRelativePath(simpleName, fs2us(fullPath)); } } prop.Detach(value); return S_OK; } } #else // _WIN32 if (di.ReparseData.Size() != 0) { AString utf; utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); UString us; if (ConvertUTF8ToUnicode(utf, us)) { prop = us; prop.Detach(value); return S_OK; } } #endif // _WIN32 } #endif // !defined(UNDER_CE) } else if (propID == kpidHardLink) { if (index == _hardIndex_From) { const CKeyKeyValPair &pair = _map[_hardIndex_To]; const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; prop = DirItems->GetLogPath((unsigned)up2.DirIndex); prop.Detach(value); return S_OK; } if (up.DirIndex >= 0) { prop.Detach(value); return S_OK; } } } if (up.IsAnti && propID != kpidIsDir && propID != kpidPath && propID != kpidIsAltStream) { switch (propID) { case kpidSize: prop = (UInt64)0; break; case kpidIsAnti: prop = true; break; default: break; } } else if (propID == kpidPath && up.NewNameIndex >= 0) prop = (*NewNames)[(unsigned)up.NewNameIndex]; else if (propID == kpidComment && CommentIndex >= 0 && (unsigned)CommentIndex == index && Comment) prop = *Comment; else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) { // we can generate new ShortName here; } else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) && up.ExistInArchive() && Archive) return Archive->GetProperty(ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, value); else if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; switch (propID) { case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = (UInt64)(di.IsDir() ? (UInt64)0 : di.Size); break; case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break; case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break; case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break; case kpidAttrib: /* if (di.Attrib_IsDefined) */ prop = (UInt32)di.GetWinAttrib(); break; case kpidPosixAttrib: /* if (di.Attrib_IsDefined) */ prop = (UInt32)di.GetPosixAttrib(); break; #if defined(_WIN32) case kpidIsAltStream: prop = di.IsAltStream; break; // case kpidShortName: prop = di.ShortName; break; #else #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #endif case kpidDeviceMajor: /* printf("\ndi.mode = %o\n", di.mode); printf("\nst.st_rdev major = %d\n", (unsigned)major(di.rdev)); printf("\nst.st_rdev minor = %d\n", (unsigned)minor(di.rdev)); */ if (S_ISCHR(di.mode) || S_ISBLK(di.mode)) prop = (UInt32)major(di.rdev); break; case kpidDeviceMinor: if (S_ISCHR(di.mode) || S_ISBLK(di.mode)) prop = (UInt32)minor(di.rdev); break; #if defined(__APPLE__) #pragma GCC diagnostic pop #endif // case kpidDevice: if (S_ISCHR(di.mode) || S_ISBLK(di.mode)) prop = (UInt64)(di.rdev); break; case kpidUserId: if (StoreOwnerId) prop = (UInt32)di.uid; break; case kpidGroupId: if (StoreOwnerId) prop = (UInt32)di.gid; break; case kpidUser: if (di.OwnerNameIndex >= 0) prop = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex]; break; case kpidGroup: if (di.OwnerGroupIndex >= 0) prop = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex]; break; #endif default: break; } } prop.Detach(value); return S_OK; COM_TRY_END } #ifndef Z7_ST static NSynchronization::CCriticalSection g_CS; #endif void CArchiveUpdateCallback::UpdateProcessedItemStatus(unsigned dirIndex) { if (ProcessedItemsStatuses) { #ifndef Z7_ST NSynchronization::CCriticalSectionLock lock(g_CS); #endif ProcessedItemsStatuses[dirIndex] = 1; } } Z7_COM7F_IMF(CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)) { COM_TRY_BEGIN *inStream = NULL; const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()) // RINOK(Callback->Finalize()); bool isDir = IsDir(up); if (up.IsAnti) { UString name; if (up.ArcIndex >= 0) name = (*ArcItems)[(unsigned)up.ArcIndex].Name; else if (up.DirIndex >= 0) name = DirItems->GetLogPath((unsigned)up.DirIndex); RINOK(Callback->GetStream(name, isDir, true, mode)) /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. so we return empty stream */ if (!isDir) { CBufInStream *inStreamSpec = new CBufInStream(); CMyComPtr inStreamLoc = inStreamSpec; inStreamSpec->Init(NULL, 0); *inStream = inStreamLoc.Detach(); } return S_OK; } RINOK(Callback->GetStream(DirItems->GetLogPath((unsigned)up.DirIndex), isDir, false, mode)) if (isDir) return S_OK; if (StdInMode) { if (mode != NUpdateNotifyOp::kAdd && mode != NUpdateNotifyOp::kUpdate) return S_OK; #if 1 CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr inStreamLoc(inStreamSpec); #else CMyComPtr inStreamLoc; if (!CreateStdInStream(inStreamLoc)) return GetLastError_noZero_HRESULT(); #endif *inStream = inStreamLoc.Detach(); } else { #if !defined(UNDER_CE) const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; if (di.AreReparseData()) { /* // we still need DeviceIoControlOut() instead of Read if (!inStreamSpec->File.OpenReparse(path)) { return Callback->OpenFileError(path, ::GetLastError()); } */ // 20.03: we use Reparse Data instead of real data CBufInStream *inStreamSpec = new CBufInStream(); CMyComPtr inStreamLoc = inStreamSpec; inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); *inStream = inStreamLoc.Detach(); UpdateProcessedItemStatus((unsigned)up.DirIndex); return S_OK; } #endif // !defined(UNDER_CE) CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); /* // for debug: #ifdef _WIN32 inStreamSpec->StoreOwnerName = true; inStreamSpec->OwnerName = "user_name"; inStreamSpec->OwnerName += di.Name; inStreamSpec->OwnerName += "11111111112222222222222333333333333"; inStreamSpec->OwnerGroup = "gname_"; inStreamSpec->OwnerGroup += inStreamSpec->OwnerName; #endif */ #ifndef _WIN32 inStreamSpec->StoreOwnerId = StoreOwnerId; inStreamSpec->StoreOwnerName = StoreOwnerName; // if (StoreOwner) { inStreamSpec->_uid = di.uid; inStreamSpec->_gid = di.gid; if (di.OwnerNameIndex >= 0) inStreamSpec->OwnerName = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex]; if (di.OwnerGroupIndex >= 0) inStreamSpec->OwnerGroup = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex]; } #endif inStreamSpec->SupportHardLinks = StoreHardLinks; const bool preserveATime = (PreserveATime || mode == NUpdateNotifyOp::kAnalyze); // 22.00 : we don't change access time in Analyze pass. inStreamSpec->Set_PreserveATime(preserveATime); const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex); _openFiles_Indexes.Add(index); _openFiles_Paths.Add(path); // _openFiles_Streams.Add(inStreamSpec); /* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding for correct working if exception was raised in GetPhyPath */ inStreamSpec->Callback = this; inStreamSpec->CallbackRef = index; if (!inStreamSpec->OpenShared(path, ShareForWrite)) { bool isOpen = false; if (preserveATime) { inStreamSpec->Set_PreserveATime(false); isOpen = inStreamSpec->OpenShared(path, ShareForWrite); } if (!isOpen) { const DWORD error = ::GetLastError(); const HRESULT hres = Callback->OpenFileError(path, error); if (hres == S_OK || hres == S_FALSE) if (StopAfterOpenError || // v23: we check also for some critical errors: #ifdef _WIN32 error == ERROR_NO_SYSTEM_RESOURCES #else error == EMFILE #endif ) { if (error == 0) return E_FAIL; return HRESULT_FROM_WIN32(error); } return hres; } } /* { // for debug: Byte b = 0; UInt32 processedSize = 0; if (inStreamSpec->Read(&b, 1, &processedSize) != S_OK || processedSize != 1) return E_FAIL; } */ if (Need_LatestMTime) { inStreamSpec->ReloadProps(); } // #if defined(Z7_FILE_STREAMS_USE_WIN_FILE) || !defined(_WIN32) if (StoreHardLinks) { CStreamFileProps props; if (inStreamSpec->GetProps2(&props) == S_OK) { if (props.NumLinks > 1) { CKeyKeyValPair pair; pair.Key1 = props.VolID; pair.Key2 = props.FileID_Low; pair.Value = index; const unsigned numItems = _map.Size(); const unsigned pairIndex = _map.AddToUniqueSorted2(pair); if (numItems == _map.Size()) { // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex]; _hardIndex_From = index; _hardIndex_To = pairIndex; // we could return NULL as stream, but it's better to return real stream // return S_OK; } } } } // #endif UpdateProcessedItemStatus((unsigned)up.DirIndex); *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::SetOperationResult(Int32 opRes)) { COM_TRY_BEGIN return Callback->SetOperationResult(opRes); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)) { COM_TRY_BEGIN return GetStream2(index, inStream, (*UpdatePairs)[index].ArcIndex < 0 ? NUpdateNotifyOp::kAdd : NUpdateNotifyOp::kUpdate); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)) { COM_TRY_BEGIN // if (op == NUpdateNotifyOp::kOpFinished) return Callback->ReportFinished(indexType, index); bool isDir = false; if (indexType == NArchive::NEventIndexType::kOutArcIndex) { UString name; if (index != (UInt32)(Int32)-1) { const CUpdatePair2 &up = (*UpdatePairs)[index]; if (up.ExistOnDisk()) { name = DirItems->GetLogPath((unsigned)up.DirIndex); isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir(); } } return Callback->ReportUpdateOperation(op, name.IsEmpty() ? NULL : name.Ptr(), isDir); } wchar_t temp[16]; UString s2; const wchar_t *s = NULL; if (indexType == NArchive::NEventIndexType::kInArcIndex) { if (index != (UInt32)(Int32)-1) { if (ArcItems) { const CArcItem &ai = (*ArcItems)[index]; s = ai.Name; isDir = ai.IsDir; } else if (Arc) { RINOK(Arc->GetItem_Path(index, s2)) s = s2; RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir)) } } } else if (indexType == NArchive::NEventIndexType::kBlockIndex) { temp[0] = '#'; ConvertUInt32ToString(index, temp + 1); s = temp; } if (!s) s = L""; return Callback->ReportUpdateOperation(op, s, isDir); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)) { COM_TRY_BEGIN bool isEncrypted = false; wchar_t temp[16]; UString s2; const wchar_t *s = NULL; if (indexType == NArchive::NEventIndexType::kOutArcIndex) { /* UString name; if (index != (UInt32)(Int32)-1) { const CUpdatePair2 &up = (*UpdatePairs)[index]; if (up.ExistOnDisk()) { s2 = DirItems->GetLogPath(up.DirIndex); s = s2; } } */ return E_FAIL; } if (indexType == NArchive::NEventIndexType::kInArcIndex) { if (index != (UInt32)(Int32)-1) { if (ArcItems) s = (*ArcItems)[index].Name; else if (Arc) { RINOK(Arc->GetItem_Path(index, s2)) s = s2; } if (Archive) { RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted)) } } } else if (indexType == NArchive::NEventIndexType::kBlockIndex) { temp[0] = '#'; ConvertUInt32ToString(index, temp + 1); s = temp; } return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s); COM_TRY_END } /* Z7_COM7F_IMF(CArchiveUpdateCallback::DoNeedArcProp(PROPID propID, Int32 *answer)) { *answer = 0; if (Need_ArcMTime_Report && propID == kpidComboMTime) *answer = 1; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)) { if (indexType == NArchive::NEventIndexType::kArcProp) { if (propID == kpidComboMTime) { ArcMTime_WasReported = true; if (value->vt == VT_FILETIME) { Reported_ArcMTime.Set_From_Prop(*value); Reported_ArcMTime.Def = true; } else { Reported_ArcMTime.Clear(); if (value->vt != VT_EMPTY) return E_FAIL; // for debug } } } return Callback->ReportProp(indexType, index, propID, value); } Z7_COM7F_IMF(CArchiveUpdateCallback::ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)) { return Callback->ReportRawProp(indexType, index, propID, data, dataSize, propType); } Z7_COM7F_IMF(CArchiveUpdateCallback::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)) { return Callback->ReportFinished(indexType, index, opRes); } */ Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)) { COM_TRY_BEGIN char temp[16]; ConvertUInt32ToString(index + 1, temp); FString res (temp); while (res.Len() < 2) res.InsertAtFront(FTEXT('0')); FString fileName = VolName; fileName.Add_Dot(); fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr streamLoc(streamSpec); if (!streamSpec->Create_NEW(fileName)) return GetLastError_noZero_HRESULT(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } Z7_COM7F_IMF(CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword(password); COM_TRY_END } HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error) { #ifdef _WIN32 // FIX IT !!! // why did we check only for ERROR_LOCK_VIOLATION ? // if (error == ERROR_LOCK_VIOLATION) #endif { MT_LOCK const UInt32 index = (UInt32)val; FOR_VECTOR(i, _openFiles_Indexes) { if (_openFiles_Indexes[i] == index) { RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error)) break; } } } return HRESULT_FROM_WIN32(error); } void CArchiveUpdateCallback::InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) { MT_LOCK if (Need_LatestMTime) { if (stream->_info_WasLoaded) { const CFiTime &ft = ST_MTIME(stream->_info); if (!LatestMTime_Defined || Compare_FiTime(&LatestMTime, &ft) < 0) LatestMTime = ft; LatestMTime_Defined = true; } } const UInt32 index = (UInt32)val; FOR_VECTOR(i, _openFiles_Indexes) { if (_openFiles_Indexes[i] == index) { _openFiles_Indexes.Delete(i); _openFiles_Paths.Delete(i); // _openFiles_Streams.Delete(i); return; } } /* 21.02 : this function can be called in destructor. And destructor can be called after some exception. If we don't want to throw exception in desctructors or after another exceptions, we must disable the code below that raises new exception. */ // throw 20141125; } tmp41wklro_/CPP/7zip/UI/Common/UpdateCallback.h0000444000175000001440000001326514413450720022240 0ustar nabijaczleweliusers// UpdateCallback.h #ifndef ZIP7_INC_UPDATE_CALLBACK_H #define ZIP7_INC_UPDATE_CALLBACK_H #include "../../../Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #include "OpenArchive.h" struct CArcToDoStat { CDirItemsStat2 NewData; CDirItemsStat2 OldData; CDirItemsStat2 DeleteData; UInt64 Get_NumDataItems_Total() const { return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2(); } }; Z7_PURE_INTERFACES_BEGIN #define Z7_IFACEN_IUpdateCallbackUI(x) \ virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x \ virtual HRESULT SetTotal(UInt64 size) x \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x \ virtual HRESULT CheckBreak() x \ /* virtual HRESULT Finalize() x */ \ virtual HRESULT SetNumItems(const CArcToDoStat &stat) x \ virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x \ virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \ virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x \ virtual HRESULT SetOperationResult(Int32 opRes) x \ virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x \ virtual HRESULT ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir) x \ /* virtual HRESULT SetPassword(const UString &password) x */ \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x \ virtual HRESULT CryptoGetTextPassword(BSTR *password) x \ virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x \ /* virtual HRESULT ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x \ virtual HRESULT ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x \ virtual HRESULT ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) x \ */ /* virtual HRESULT CloseProgress() { return S_OK; } */ Z7_IFACE_DECL_PURE(IUpdateCallbackUI) Z7_PURE_INTERFACES_END struct CKeyKeyValPair { UInt64 Key1; UInt64 Key2; unsigned Value; int Compare(const CKeyKeyValPair &a) const { if (Key1 < a.Key1) return -1; if (Key1 > a.Key1) return 1; return MyCompare(Key2, a.Key2); } }; class CArchiveUpdateCallback Z7_final: public IArchiveUpdateCallback2, public IArchiveUpdateCallbackFile, // public IArchiveUpdateCallbackArcProp, public IArchiveExtractCallbackMessage2, public IArchiveGetRawProps, public IArchiveGetRootProps, public ICryptoGetTextPassword2, public ICryptoGetTextPassword, public ICompressProgressInfo, public IInFileStream_Callback, public CMyUnknownImp { Z7_COM_QI_BEGIN2(IArchiveUpdateCallback2) Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile) // Z7_COM_QI_ENTRY(IArchiveUpdateCallbackArcProp) Z7_COM_QI_ENTRY(IArchiveExtractCallbackMessage2) Z7_COM_QI_ENTRY(IArchiveGetRawProps) Z7_COM_QI_ENTRY(IArchiveGetRootProps) Z7_COM_QI_ENTRY(ICryptoGetTextPassword2) Z7_COM_QI_ENTRY(ICryptoGetTextPassword) Z7_COM_QI_ENTRY(ICompressProgressInfo) Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(ICompressProgressInfo) Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IArchiveUpdateCallback) Z7_IFACE_COM7_IMP(IArchiveUpdateCallback2) Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile) // Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackArcProp) Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2) Z7_IFACE_COM7_IMP(IArchiveGetRawProps) Z7_IFACE_COM7_IMP(IArchiveGetRootProps) Z7_IFACE_COM7_IMP(ICryptoGetTextPassword2) Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) void UpdateProcessedItemStatus(unsigned dirIndex); public: bool PreserveATime; bool ShareForWrite; bool StopAfterOpenError; bool StdInMode; bool KeepOriginalItemNames; bool StoreNtSecurity; bool StoreHardLinks; bool StoreSymLinks; bool StoreOwnerId; bool StoreOwnerName; bool Need_LatestMTime; bool LatestMTime_Defined; /* bool Need_ArcMTime_Report; bool ArcMTime_WasReported; */ CRecordVector _openFiles_Indexes; FStringVector _openFiles_Paths; // CRecordVector< CInFileStream* > _openFiles_Streams; bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); } virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) Z7_override; virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) Z7_override; IUpdateCallbackUI *Callback; const CDirItems *DirItems; const CDirItem *ParentDirItem; const CArc *Arc; CMyComPtr Archive; const CObjectVector *ArcItems; const CRecordVector *UpdatePairs; CRecordVector VolumesSizes; FString VolName; FString VolExt; UString ArcFileName; // without path prefix const UStringVector *NewNames; const UString *Comment; int CommentIndex; /* CArcTime Reported_ArcMTime; */ CFiTime LatestMTime; Byte *ProcessedItemsStatuses; CArchiveUpdateCallback(); bool IsDir(const CUpdatePair2 &up) const { if (up.DirIndex >= 0) return DirItems->Items[(unsigned)up.DirIndex].IsDir(); else if (up.ArcIndex >= 0) return (*ArcItems)[(unsigned)up.ArcIndex].IsDir; return false; } private: #if defined(_WIN32) && !defined(UNDER_CE) bool _saclEnabled; #endif CRecordVector _map; UInt32 _hardIndex_From; UInt32 _hardIndex_To; }; #endif tmp41wklro_/CPP/7zip/UI/Common/UpdatePair.cpp0000444000175000001440000002067114413450720021771 0ustar nabijaczleweliusers// UpdatePair.cpp #include "StdAfx.h" #include // #include #include "../../../Common/Wildcard.h" #include "../../../Windows/TimeUtils.h" #include "SortUtils.h" #include "UpdatePair.h" using namespace NWindows; using namespace NTime; /* a2.Prec = { 0 (k_PropVar_TimePrec_0): if GetProperty(kpidMTime) returned 0 and GetProperty(kpidTimeType) did not returned VT_UI4. 7z, wim, tar in 7-Zip before v21) in that case we use (prec) that is set by IOutArchive::GetFileTimeType() } */ static int MyCompareTime(unsigned prec, const CFiTime &f1, const CArcTime &a2) { // except of precision, we also have limitation, when timestamp is out of range /* if (Prec) in archive item is defined, then use global (prec) */ if (a2.Prec != k_PropVar_TimePrec_0) prec = a2.Prec; CArcTime a1; a1.Set_From_FiTime(f1); /* Set_From_FiTime() must set full form precision: k_PropVar_TimePrec_Base + numDigits windows: 7 digits, non-windows: 9 digits */ if (prec == k_PropVar_TimePrec_DOS) { const UInt32 dosTime1 = a1.Get_DosTime(); const UInt32 dosTime2 = a2.Get_DosTime(); return MyCompare(dosTime1, dosTime2); } if (prec == k_PropVar_TimePrec_Unix) { const Int64 u2 = FileTime_To_UnixTime64(a2.FT); if (u2 == 0 || u2 == (UInt32)0xFFFFFFFF) { // timestamp probably was saturated in archive to 32-bit // so we use saturated 32-bit value for disk file too. UInt32 u1; FileTime_To_UnixTime(a1.FT, u1); const UInt32 u2_32 = (UInt32)u2; return MyCompare(u1, u2_32); } const Int64 u1 = FileTime_To_UnixTime64(a1.FT); return MyCompare(u1, u2); // prec = k_PropVar_TimePrec_Base; // for debug } if (prec == k_PropVar_TimePrec_0) prec = k_PropVar_TimePrec_Base + 7; else if (prec == k_PropVar_TimePrec_HighPrec) prec = k_PropVar_TimePrec_Base + 9; else if (prec < k_PropVar_TimePrec_Base) prec = k_PropVar_TimePrec_Base; else if (prec > k_PropVar_TimePrec_Base + 9) prec = k_PropVar_TimePrec_Base + 7; // prec now is full form: k_PropVar_TimePrec_Base + numDigits; if (prec > a1.Prec && a1.Prec >= k_PropVar_TimePrec_Base) prec = a1.Prec; const unsigned numDigits = prec - k_PropVar_TimePrec_Base; if (numDigits >= 7) { const int comp = CompareFileTime(&a1.FT, &a2.FT); if (comp != 0 || numDigits == 7) return comp; return MyCompare(a1.Ns100, a2.Ns100); } UInt32 d = 1; for (unsigned k = numDigits; k < 7; k++) d *= 10; const UInt64 v1 = a1.Get_FILETIME_as_UInt64() / d * d; const UInt64 v2 = a2.Get_FILETIME_as_UInt64() / d * d; // printf("\ndelta=%d numDigits=%d\n", (unsigned)(v1- v2), numDigits); return MyCompare(v1, v2); } static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; Z7_ATTR_NORETURN static void ThrowError(const char *message, const UString &s1, const UString &s2) { UString m (message); m.Add_LF(); m += s1; m.Add_LF(); m += s2; throw m; } static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2) { const int res = CompareFileNames(ai1.Name, ai2.Name); if (res != 0) return res; if (ai1.IsDir != ai2.IsDir) return ai1.IsDir ? -1 : 1; return 0; } static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) { const unsigned i1 = *p1; const unsigned i2 = *p2; const CObjectVector &arcItems = *(const CObjectVector *)param; const int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); if (res != 0) return res; return MyCompare(i1, i2); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector &updatePairs) { CUIntVector dirIndices, arcIndices; const unsigned numDirItems = dirItems.Items.Size(); const unsigned numArcItems = arcItems.Size(); CIntArr duplicatedArcItem(numArcItems); { int *vals = &duplicatedArcItem[0]; for (unsigned i = 0; i < numArcItems; i++) vals[i] = 0; } { arcIndices.ClearAndSetSize(numArcItems); if (numArcItems != 0) { unsigned *vals = &arcIndices[0]; for (unsigned i = 0; i < numArcItems; i++) vals[i] = i; } arcIndices.Sort(CompareArcItems, (void *)&arcItems); for (unsigned i = 0; i + 1 < numArcItems; i++) if (CompareArcItemsBase( arcItems[arcIndices[i]], arcItems[arcIndices[i + 1]]) == 0) { duplicatedArcItem[i] = 1; duplicatedArcItem[i + 1] = -1; } } UStringVector dirNames; { dirNames.ClearAndReserve(numDirItems); unsigned i; for (i = 0; i < numDirItems; i++) dirNames.AddInReserved(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); for (i = 0; i + 1 < numDirItems; i++) { const UString &s1 = dirNames[dirIndices[i]]; const UString &s2 = dirNames[dirIndices[i + 1]]; if (CompareFileNames(s1, s2) == 0) ThrowError(k_Duplicate_inDir_Message, s1, s2); } } unsigned dirIndex = 0; unsigned arcIndex = 0; int prevHostFile = -1; const UString *prevHostName = NULL; while (dirIndex < numDirItems || arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = -1; int arcIndex2 = -1; const CDirItem *di = NULL; const CArcItem *ai = NULL; int compareResult = -1; const UString *name = NULL; if (dirIndex < numDirItems) { dirIndex2 = (int)dirIndices[dirIndex]; di = &dirItems.Items[(unsigned)dirIndex2]; } if (arcIndex < numArcItems) { arcIndex2 = (int)arcIndices[arcIndex]; ai = &arcItems[(unsigned)arcIndex2]; compareResult = 1; if (dirIndex < numDirItems) { compareResult = CompareFileNames(dirNames[(unsigned)dirIndex2], ai->Name); if (compareResult == 0) { if (di->IsDir() != ai->IsDir) compareResult = (ai->IsDir ? 1 : -1); } } } if (compareResult < 0) { name = &dirNames[(unsigned)dirIndex2]; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { name = &ai->Name; pair.State = ai->Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { const int dupl = duplicatedArcItem[arcIndex]; if (dupl != 0) ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name); name = &dirNames[(unsigned)dirIndex2]; if (!ai->Censored) ThrowError(k_NotCensoredCollision_Message, *name, ai->Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; int compResult = 0; if (ai->MTime.Def) { compResult = MyCompareTime((unsigned)fileTimeType, di->MTime, ai->MTime); } switch (compResult) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: pair.State = (ai->Size_Defined && di->Size == ai->Size) ? NUpdateArchive::NPairState::kSameFiles : NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } if ( #ifdef _WIN32 (di && di->IsAltStream) || #endif (ai && ai->IsAltStream)) { if (prevHostName) { const unsigned hostLen = prevHostName->Len(); if (name->Len() > hostLen) if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0) pair.HostIndex = prevHostFile; } } else { prevHostFile = (int)updatePairs.Size(); prevHostName = name; } updatePairs.Add(pair); } updatePairs.ReserveDown(); } tmp41wklro_/CPP/7zip/UI/Common/UpdatePair.h0000444000175000001440000000116314357314620021436 0ustar nabijaczleweliusers// UpdatePair.h #ifndef ZIP7_INC_UPDATE_PAIR_H #define ZIP7_INC_UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; int HostIndex; // >= 0 for alt streams only, contains index of host pair CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector &updatePairs); #endif tmp41wklro_/CPP/7zip/UI/Common/UpdateProduce.cpp0000444000175000001440000000410014571117200022462 0ustar nabijaczleweliusers// UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char * const kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector &updatePairs, const CActionSet &actionSet, CRecordVector &operationChain, IUpdateProduceCallback *callback) { FOR_VECTOR (i, updatePairs) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; up2.UseArcProps = false; switch ((int)actionSet.StateActions[(unsigned)pair.State]) { case NPairAction::kIgnore: if (pair.ArcIndex >= 0 && callback) callback->ShowDeleteFile((unsigned)pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; if (pair.State == NPairState::kOnlyInArchive) { if (pair.HostIndex >= 0) { /* ignore alt stream if 1) no such alt stream in Disk 2) there is Host file in disk */ if (updatePairs[(unsigned)pair.HostIndex].DirIndex >= 0) continue; } } up2.NewData = up2.NewProps = false; up2.UseArcProps = true; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; up2.UseArcProps = (pair.ArcIndex >= 0); break; default: throw 123; // break; // is unexpected case } up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles); operationChain.Add(up2); } operationChain.ReserveDown(); } tmp41wklro_/CPP/7zip/UI/Common/UpdateProduce.h0000444000175000001440000000255414366515220022150 0ustar nabijaczleweliusers// UpdateProduce.h #ifndef ZIP7_INC_UPDATE_PRODUCE_H #define ZIP7_INC_UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties. bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status int DirIndex; int ArcIndex; int NewNameIndex; bool IsMainRenameItem; bool IsSameTime; void SetAs_NoChangeArcItem(unsigned arcIndex) // int { NewData = NewProps = false; UseArcProps = true; IsAnti = false; ArcIndex = (int)arcIndex; } bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): NewData(false), NewProps(false), UseArcProps(false), IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1), IsMainRenameItem(false), IsSameTime(false) {} }; Z7_PURE_INTERFACES_BEGIN DECLARE_INTERFACE(IUpdateProduceCallback) { virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0; }; Z7_PURE_INTERFACES_END void UpdateProduce( const CRecordVector &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector &operationChain, IUpdateProduceCallback *callback); #endif tmp41wklro_/CPP/7zip/UI/Common/WorkDir.cpp0000444000175000001440000000436614413450720021317 0ustar nabijaczleweliusers// WorkDir.cpp #include "StdAfx.h" #include "../../../Windows/FileName.h" #include "../../../Windows/FileSystem.h" #include "WorkDir.h" using namespace NWindows; using namespace NFile; using namespace NDir; FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; #if defined(_WIN32) && !defined(UNDER_CE) if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; const FString prefix = path.Left(3); if (NName::IsDrivePath(prefix)) { const UINT driveType = NSystem::MyGetDriveType(prefix); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } #endif const int pos = path.ReverseFind_PathSepar() + 1; fileName = path.Ptr((unsigned)pos); FString tempDir; switch ((int)mode) { case NWorkDir::NMode::kCurrent: tempDir = path.Left((unsigned)pos); break; case NWorkDir::NMode::kSpecified: tempDir = workDirInfo.Path; break; // case NWorkDir::NMode::kSystem: default: if (!MyGetTempPath(tempDir)) throw 141717; break; } NName::NormalizeDirPathPrefix(tempDir); return tempDir; } HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) { NWorkDir::CInfo workDirInfo; workDirInfo.Load(); FString namePart; const FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); CreateComplexDir(workDir); _outStreamSpec = new COutFileStream; OutStream = _outStreamSpec; if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) { return GetLastError_noZero_HRESULT(); } _originalPath = originalPath; return S_OK; } HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) { OutStream.Release(); if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) { return GetLastError_noZero_HRESULT(); } return S_OK; } tmp41wklro_/CPP/7zip/UI/Common/WorkDir.h0000444000175000001440000000111114357314620020752 0ustar nabijaczleweliusers// WorkDir.h #ifndef ZIP7_INC_WORK_DIR_H #define ZIP7_INC_WORK_DIR_H #include "../../../Windows/FileDir.h" #include "../../Common/FileStreams.h" #include "ZipRegistry.h" FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); class CWorkDirTempFile { FString _originalPath; NWindows::NFile::NDir::CTempFile _tempFile; COutFileStream *_outStreamSpec; public: CMyComPtr OutStream; HRESULT CreateTempFile(const FString &originalPath); HRESULT MoveToOriginal(bool deleteOriginal); }; #endif tmp41wklro_/CPP/7zip/UI/Common/ZipRegistry.h0000444000175000001440000000740414575350020021673 0ustar nabijaczleweliusers// ZipRegistry.h #ifndef ZIP7_INC_ZIP_REGISTRY_H #define ZIP7_INC_ZIP_REGISTRY_H #include "../../../Common/MyTypes.h" #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" #include "ExtractMode.h" /* CBoolPair::Def in writing functions means: if ( CBoolPair::Def ), we write CBoolPair::Val if ( !CBoolPair::Def ) { in NCompression functions we delete registry value in another functions we do nothing } */ namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; bool PathMode_Force; bool OverwriteMode_Force; CBoolPair SplitDest; CBoolPair ElimDup; // CBoolPair AltStreams; CBoolPair NtSecurity; CBoolPair ShowPassword; UStringVector Paths; void Save() const; void Load(); }; void Save_ShowPassword(bool showPassword); bool Read_ShowPassword(); void Save_LimitGB(UInt32 limit_GB); UInt32 Read_LimitGB(); } namespace NCompression { struct CMemUse { // UString Str; bool IsDefined; bool IsPercent; UInt64 Val; CMemUse(): IsDefined(false), IsPercent(false), Val(0) {} void Clear() { // Str.Empty(); IsDefined = false; IsPercent = false; Val = 0; } UInt64 GetBytes(UInt64 ramSize) const { if (!IsPercent) return Val; return Calc_From_Val_Percents(ramSize, Val); } void Parse(const UString &s); }; struct CFormatOptions { UInt32 Level; UInt32 Dictionary; // UInt32 DictionaryChain; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; UInt32 TimePrec; CBoolPair MTime; CBoolPair ATime; CBoolPair CTime; CBoolPair SetArcMTime; CSysString FormatID; UString Method; UString Options; UString EncryptionMethod; UString MemUse; void Reset_TimePrec() { TimePrec = (UInt32)(Int32)-1; } bool IsSet_TimePrec() const { return TimePrec != (UInt32)(Int32)-1; } void Reset_BlockLogSize() { BlockLogSize = (UInt32)(Int32)-1; } void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1; // DictionaryChain = (UInt32)(Int32)-1; Method.Empty(); // Options.Empty(); // EncryptionMethod.Empty(); } CFormatOptions() { // TimePrec = 0; Reset_TimePrec(); ResetForLevelChange(); } }; struct CInfo { UInt32 Level; bool ShowPassword; bool EncryptHeaders; CBoolPair NtSecurity; CBoolPair AltStreams; CBoolPair HardLinks; CBoolPair SymLinks; CBoolPair PreserveATime; UString ArcType; UStringVector ArcPaths; CObjectVector Formats; void Save() const; void Load(); }; } namespace NWorkDir { namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; bool ForRemovableOnly; FString Path; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } void Save() const; void Load(); }; } struct CContextMenuInfo { CBoolPair Cascaded; CBoolPair MenuIcons; CBoolPair ElimDup; bool Flags_Def; UInt32 Flags; UInt32 WriteZone; /* CContextMenuInfo(): Flags_Def(0), WriteZone((UInt32)(Int32)-1), Flags((UInt32)(Int32)-1) {} */ void Save() const; void Load(); }; #endif tmp41wklro_/CPP/7zip/UI/Console/0000700000175000001440000000000014706260545017374 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/Console/BenchCon.cpp0000444000175000001440000000153614412077460021570 0ustar nabijaczleweliusers// BenchCon.cpp #include "StdAfx.h" #include "../Common/Bench.h" #include "BenchCon.h" #include "ConsoleClose.h" struct CPrintBenchCallback Z7_final: public IBenchPrintCallback { FILE *_file; void Print(const char *s) Z7_override; void NewLine() Z7_override; HRESULT CheckBreak() Z7_override; }; void CPrintBenchCallback::Print(const char *s) { fputs(s, _file); } void CPrintBenchCallback::NewLine() { fputc('\n', _file); } HRESULT CPrintBenchCallback::CheckBreak() { return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK; } HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS const CObjectVector &props, UInt32 numIterations, FILE *f) { CPrintBenchCallback callback; callback._file = f; return Bench(EXTERNAL_CODECS_LOC_VARS &callback, NULL, props, numIterations, true); } tmp41wklro_/CPP/7zip/UI/Console/BenchCon.h0000444000175000001440000000047314412077460021234 0ustar nabijaczleweliusers// BenchCon.h #ifndef ZIP7_INC_BENCH_CON_H #define ZIP7_INC_BENCH_CON_H #include #include "../../Common/CreateCoder.h" #include "../../UI/Common/Property.h" HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS const CObjectVector &props, UInt32 numIterations, FILE *f); #endif tmp41wklro_/CPP/7zip/UI/Console/Console.mak0000444000175000001440000000177514555655400021512 0ustar nabijaczleweliusersMY_CONSOLE = 1 !IFNDEF UNDER_CE CFLAGS = $(CFLAGS) -DZ7_DEVICE_FILE # -DZ7_LONG_PATH -DZ7_LARGE_PAGES !ENDIF CONSOLE_OBJS = \ $O\BenchCon.obj \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\HashCon.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\Bench.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\HashCalc.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ C_OBJS = $(C_OBJS) \ $O\DllSecur.obj \ # we need empty line after last line above tmp41wklro_/CPP/7zip/UI/Console/Console.manifest0000444000175000001440000000215014412233000022510 0ustar nabijaczleweliusers true tmp41wklro_/CPP/7zip/UI/Console/ConsoleClose.cpp0000444000175000001440000000362113775105212022474 0ustar nabijaczleweliusers// ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" #ifndef UNDER_CE #ifdef _WIN32 #include "../../../Common/MyWindows.h" #else #include #include #endif namespace NConsoleClose { unsigned g_BreakCounter = 0; static const unsigned kBreakAbortThreshold = 2; #ifdef _WIN32 static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch (ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } CCtrlHandlerSetter::CCtrlHandlerSetter() { if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) { // warning for throw in destructor. // throw "SetConsoleCtrlHandler fails"; } } #else // _WIN32 static void HandlerRoutine(int) { g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return; exit(EXIT_FAILURE); } CCtrlHandlerSetter::CCtrlHandlerSetter() { memo_sig_int = signal(SIGINT, HandlerRoutine); // CTRL-C if (memo_sig_int == SIG_ERR) throw "SetConsoleCtrlHandler fails (SIGINT)"; memo_sig_term = signal(SIGTERM, HandlerRoutine); // for kill -15 (before "kill -9") if (memo_sig_term == SIG_ERR) throw "SetConsoleCtrlHandler fails (SIGTERM)"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { signal(SIGINT, memo_sig_int); // CTRL-C signal(SIGTERM, memo_sig_term); // kill {pid} } #endif // _WIN32 /* void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } */ } #endif tmp41wklro_/CPP/7zip/UI/Console/ConsoleClose.h0000444000175000001440000000111214412474560022136 0ustar nabijaczleweliusers// ConsoleClose.h #ifndef ZIP7_INC_CONSOLE_CLOSE_H #define ZIP7_INC_CONSOLE_CLOSE_H namespace NConsoleClose { class CCtrlBreakException {}; #ifdef UNDER_CE inline bool TestBreakSignal() { return false; } struct CCtrlHandlerSetter {}; #else extern unsigned g_BreakCounter; inline bool TestBreakSignal() { return (g_BreakCounter != 0); } class CCtrlHandlerSetter Z7_final { #ifndef _WIN32 void (*memo_sig_int)(int); void (*memo_sig_term)(int); #endif public: CCtrlHandlerSetter(); ~CCtrlHandlerSetter(); }; #endif } #endif tmp41wklro_/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp0000444000175000001440000005745314646226760024504 0ustar nabijaczleweliusers// ExtractCallbackConsole.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/TimeUtils.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/PropVariantConv.h" #ifndef Z7_ST #include "../../../Windows/Synchronization.h" #endif #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" using namespace NWindows; using namespace NFile; using namespace NDir; static HRESULT CheckBreak2() { return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } static const char * const kError = "ERROR: "; void CExtractScanConsole::StartScanning() { if (NeedPercents()) _percent.Command = "Scan"; } HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) { if (NeedPercents()) { _percent.Files = st.NumDirs + st.NumFiles; _percent.Completed = st.GetTotalBytes(); _percent.FileName = fs2us(path); _percent.Print(); } return CheckBreak2(); } HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) { // 22.00: // ScanErrors.AddError(path, systemError); ClosePercentsAndFlush(); if (_se) { *_se << endl << kError << NError::MyFormatMessage(systemError) << endl; _se->NormalizePrint_UString_Path(fs2us(path)); *_se << endl << endl; _se->Flush(); } return HRESULT_FROM_WIN32(systemError); // 22.00: commented // CommonError(path, systemError, true); // return S_OK; } void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) { char temp[32]; ConvertUInt64ToString(val, temp); s += temp; s.Add_Space(); s += name; } void PrintSize_bytes_Smart(AString &s, UInt64 val); void PrintSize_bytes_Smart(AString &s, UInt64 val) { Print_UInt64_and_String(s, val, "bytes"); if (val == 0) return; unsigned numBits = 10; char c = 'K'; char temp[4] = { 'K', 'i', 'B', 0 }; if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; } else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; } temp[0] = c; s += " ("; Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp); s.Add_Char(')'); } static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) { if (val == (UInt64)(Int64)-1) return; s += ", "; PrintSize_bytes_Smart(s, val); } void Print_DirItemsStat(AString &s, const CDirItemsStat &st); void Print_DirItemsStat(AString &s, const CDirItemsStat &st) { if (st.NumDirs != 0) { Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders"); s += ", "; } Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files"); PrintSize_bytes_Smart_comma(s, st.FilesSize); if (st.NumAltStreams != 0) { s.Add_LF(); Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams"); PrintSize_bytes_Smart_comma(s, st.AltStreamsSize); } } void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st) { Print_DirItemsStat(s, (CDirItemsStat &)st); bool needLF = true; if (st.Anti_NumDirs != 0) { if (needLF) s.Add_LF(); needLF = false; Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders"); } if (st.Anti_NumFiles != 0) { if (needLF) s.Add_LF(); else s += ", "; needLF = false; Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files"); } if (st.Anti_NumAltStreams != 0) { if (needLF) s.Add_LF(); else s += ", "; needLF = false; Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams"); } } void CExtractScanConsole::PrintStat(const CDirItemsStat &st) { if (_so) { AString s; Print_DirItemsStat(s, st); *_so << s << endl; } } #ifndef Z7_ST static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const char * const kTestString = "T"; static const char * const kExtractString = "-"; static const char * const kSkipString = "."; static const char * const kReadString = "H"; // static const char * const kCantAutoRename = "cannot create file with auto name\n"; // static const char * const kCantRenameFile = "cannot rename existing file\n"; // static const char * const kCantDeleteOutputFile = "cannot delete output file "; static const char * const kMemoryExceptionMessage = "Can't allocate required memory!"; static const char * const kExtracting = "Extracting archive: "; static const char * const kTesting = "Testing archive: "; static const char * const kEverythingIsOk = "Everything is Ok"; static const char * const kNoFiles = "No files to process"; static const char * const kUnsupportedMethod = "Unsupported Method"; static const char * const kCrcFailed = "CRC Failed"; static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char * const kDataError = "Data Error"; static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char * const kUnavailableData = "Unavailable data"; static const char * const kUnexpectedEnd = "Unexpected end of data"; static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; static const char * const kIsNotArc = "Is not archive"; static const char * const kHeadersError = "Headers Error"; static const char * const kWrongPassword = "Wrong password"; static const char * const k_ErrorFlagsMessages[] = { "Is not archive" , "Headers Error" , "Headers Error in encrypted archive. Wrong password?" , "Unavailable start of archive" , "Unconfirmed start of archive" , "Unexpected end of archive" , "There are data after the end of archive" , "Unsupported method" , "Unsupported feature" , "Data Error" , "CRC Error" }; Z7_COM7F_IMF(CExtractCallbackConsole::SetTotal(UInt64 size)) { MT_LOCK if (NeedPercents()) { _percent.Total = size; _percent.Print(); } return CheckBreak2(); } Z7_COM7F_IMF(CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)) { MT_LOCK if (NeedPercents()) { if (completeValue) _percent.Completed = *completeValue; _percent.Print(); } return CheckBreak2(); } static const char * const kTab = " "; static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) { *_so << kTab << "Path: "; _so->NormalizePrint_wstr_Path(path); *_so << endl; if (size && *size != (UInt64)(Int64)-1) { AString s; PrintSize_bytes_Smart(s, *size); *_so << kTab << "Size: " << s << endl; } if (ft) { char temp[64]; if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC)) *_so << kTab << "Modified: " << temp << endl; } } Z7_COM7F_IMF(CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer)) { MT_LOCK RINOK(CheckBreak2()) ClosePercentsAndFlush(); if (_so) { *_so << endl << "Would you like to replace the existing file:\n"; PrintFileInfo(_so, existName, existTime, existSize); *_so << "with the file from archive:\n"; PrintFileInfo(_so, newName, newTime, newSize); } NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so); switch ((int)overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; case NUserAnswerMode::kEof: return E_ABORT; case NUserAnswerMode::kError: return E_FAIL; default: return E_FAIL; } if (_so) { *_so << endl; if (NeedFlush) _so->Flush(); } return CheckBreak2(); } Z7_COM7F_IMF(CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)) { MT_LOCK _currentName = name; const char *s; unsigned requiredLevel = 1; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break; case NArchive::NExtract::NAskMode::kReadExternal: s = kReadString; requiredLevel = 0; break; default: s = "???"; requiredLevel = 2; } const bool show2 = (LogLevel >= requiredLevel && _so); if (show2) { ClosePercents_for_so(); _tempA = s; if (name) _tempA.Add_Space(); *_so << _tempA; _tempU.Empty(); if (name) { _tempU = name; _so->Normalize_UString_Path(_tempU); // 21.04 if (isFolder) { if (!_tempU.IsEmpty() && _tempU.Back() != WCHAR_PATH_SEPARATOR) _tempU.Add_PathSepar(); } } _so->PrintUString(_tempU, _tempA); if (position) *_so << " <" << *position << ">"; *_so << endl; if (NeedFlush) _so->Flush(); // _so->Flush(); // for debug only } if (NeedPercents()) { if (PercentsNameLevel >= 1) { _percent.FileName.Empty(); _percent.Command.Empty(); if (PercentsNameLevel > 1 || !show2) { _percent.Command = s; if (name) _percent.FileName = name; } } _percent.Print(); } return CheckBreak2(); } Z7_COM7F_IMF(CExtractCallbackConsole::MessageError(const wchar_t *message)) { MT_LOCK RINOK(CheckBreak2()) NumFileErrors_in_Current++; NumFileErrors++; ClosePercentsAndFlush(); if (_se) { *_se << kError << message << endl; _se->Flush(); } return CheckBreak2(); } void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) { dest.Empty(); const char *s = NULL; switch (opRes) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: s = kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: s = (encrypted ? kDataErrorEncrypted : kDataError); break; case NArchive::NExtract::NOperationResult::kUnavailable: s = kUnavailableData; break; case NArchive::NExtract::NOperationResult::kUnexpectedEnd: s = kUnexpectedEnd; break; case NArchive::NExtract::NOperationResult::kDataAfterEnd: s = kDataAfterEnd; break; case NArchive::NExtract::NOperationResult::kIsNotArc: s = kIsNotArc; break; case NArchive::NExtract::NOperationResult::kHeadersError: s = kHeadersError; break; case NArchive::NExtract::NOperationResult::kWrongPassword: s = kWrongPassword; break; default: break; } dest += kError; if (s) dest += s; else { dest += "Error #"; dest.Add_UInt32((UInt32)opRes); } } Z7_COM7F_IMF(CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)) { MT_LOCK if (opRes == NArchive::NExtract::NOperationResult::kOK) { if (NeedPercents()) { _percent.Command.Empty(); _percent.FileName.Empty(); _percent.Files++; } } else { NumFileErrors_in_Current++; NumFileErrors++; if (_se) { ClosePercentsAndFlush(); AString s; SetExtractErrorMessage(opRes, encrypted, s); *_se << s; if (!_currentName.IsEmpty()) { *_se << " : "; _se->NormalizePrint_UString_Path(_currentName); } *_se << endl; _se->Flush(); } } return CheckBreak2(); } Z7_COM7F_IMF(CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)) { if (opRes != NArchive::NExtract::NOperationResult::kOK) { _currentName = name; return SetOperationResult(opRes, encrypted); } return CheckBreak2(); } #ifndef Z7_NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } Z7_COM7F_IMF(CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)) { COM_TRY_BEGIN MT_LOCK return Open_CryptoGetTextPassword(password); COM_TRY_END } #endif #ifndef Z7_SFX void CExtractCallbackConsole::PrintTo_se_Path_WithTitle(const UString &path, const char *title) { *_se << title; _se->NormalizePrint_UString_Path(path); *_se << endl; } void CExtractCallbackConsole::Add_ArchiveName_Error() { if (_needWriteArchivePath) { PrintTo_se_Path_WithTitle(_currentArchivePath, "Archive: "); _needWriteArchivePath = false; } } Z7_COM7F_IMF(CExtractCallbackConsole::RequestMemoryUse( UInt32 flags, UInt32 /* indexType */, UInt32 /* index */, const wchar_t *path, UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags)) { if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0 && requiredSize <= *allowedSize) { #if 0 // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already, // because it's default answer for (requiredSize <= *allowedSize) case. // optional code: *answerFlags = NRequestMemoryAnswerFlags::k_Allow; #endif } else { if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0) if (_se) { const UInt64 num_GB_allowed = (*allowedSize + ((1u << 30) - 1)) >> 30; const UInt64 num_GB_required = (requiredSize + ((1u << 30) - 1)) >> 30; ClosePercentsAndFlush(); Add_ArchiveName_Error(); if (path) PrintTo_se_Path_WithTitle(path, "File: "); *_se << "The extraction operation requires big amount memory (RAM):" << endl << " " << num_GB_required << " GB : required memory usage size" << endl << " " << num_GB_allowed << " GB : allowed memory usage limit" << endl << " Use -smemx{size}g switch to set allowed memory usage limit for extraction." << endl; *_se << "ERROR: Memory usage limit was exceeded." << endl; const char *m = NULL; // if (indexType == NArchive::NEventIndexType::kNoIndex) if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) || (flags & NRequestMemoryUseFlags::k_Report_SkipArc)) m = "Archive unpacking was skipped."; /* else if ((flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected) || (flags & NRequestMemoryUseFlags::k_Report_SkipBigFiles)) m = "Extraction for some files will be skipped."; else if ((flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected) || (flags & NRequestMemoryUseFlags::k_Report_SkipBigFile)) m = "File extraction was skipped."; */ if (m) *_se << m; _se->Flush(); } if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0) { // default answer can be k_Allow, if limit was not forced, // so we change answer to non-allowed here. *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded; if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc; /* else if (flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected) *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFile; else if (flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected) *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFiles; */ } } return CheckBreak2(); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode) { _currentArchivePath = name; _needWriteArchivePath = true; RINOK(CheckBreak2()) NumTryArcs++; ThereIsError_in_Current = false; ThereIsWarning_in_Current = false; NumFileErrors_in_Current = 0; ClosePercents_for_so(); if (_so) { *_so << endl << (testMode ? kTesting : kExtracting); _so->NormalizePrint_wstr_Path(name); *_so << endl; } if (NeedPercents()) _percent.Command = "Open"; return S_OK; } HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); static AString GetOpenArcErrorMessage(UInt32 errorFlags) { AString s; for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsMessages); i++) { UInt32 f = (1 << i); if ((errorFlags & f) == 0) continue; const char *m = k_ErrorFlagsMessages[i]; if (!s.IsEmpty()) s.Add_LF(); s += m; errorFlags &= ~f; } if (errorFlags != 0) { char sz[16]; sz[0] = '0'; sz[1] = 'x'; ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) s.Add_LF(); s += sz; } return s; } void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) { if (errorFlags == 0) return; so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; } static void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) { s.Add_LF(); s += pre; s += " as ["; s += arcType; s += "] archive"; } void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc) { const CArcErrorInfo &er = arc.ErrorInfo; *_so << "WARNING:\n"; _so->NormalizePrint_UString_Path(arc.Path); UString s; if (arc.FormatIndex == er.ErrorFormatIndex) { s.Add_LF(); s += "The archive is open with offset"; } else { Add_Messsage_Pre_ArcType(s, "Cannot open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex)); Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex)); } *_so << s << endl << endl; } HRESULT CExtractCallbackConsole::OpenResult( const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { _currentArchivePath = name; _needWriteArchivePath = true; ClosePercents(); if (NeedPercents()) { _percent.Files = 0; _percent.Command.Empty(); _percent.FileName.Empty(); } ClosePercentsAndFlush(); FOR_VECTOR (level, arcLink.Arcs) { const CArc &arc = arcLink.Arcs[level]; const CArcErrorInfo &er = arc.ErrorInfo; UInt32 errorFlags = er.GetErrorFlags(); if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) { if (_se) { *_se << endl; if (level != 0) { _se->NormalizePrint_UString_Path(arc.Path); *_se << endl; } } if (errorFlags != 0) { if (_se) PrintErrorFlags(*_se, "ERRORS:", errorFlags); NumOpenArcErrors++; ThereIsError_in_Current = true; } if (!er.ErrorMessage.IsEmpty()) { if (_se) *_se << "ERRORS:" << endl << er.ErrorMessage << endl; NumOpenArcErrors++; ThereIsError_in_Current = true; } if (_se) { *_se << endl; _se->Flush(); } } UInt32 warningFlags = er.GetWarningFlags(); if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) { if (_so) { *_so << endl; if (level != 0) { _so->NormalizePrint_UString_Path(arc.Path); *_so << endl; } } if (warningFlags != 0) { if (_so) PrintErrorFlags(*_so, "WARNINGS:", warningFlags); NumOpenArcWarnings++; ThereIsWarning_in_Current = true; } if (!er.WarningMessage.IsEmpty()) { if (_so) *_so << "WARNINGS:" << endl << er.WarningMessage << endl; NumOpenArcWarnings++; ThereIsWarning_in_Current = true; } if (_so) { *_so << endl; if (NeedFlush) _so->Flush(); } } if (er.ErrorFormatIndex >= 0) { if (_so) { Print_ErrorFormatIndex_Warning(_so, codecs, arc); if (NeedFlush) _so->Flush(); } ThereIsWarning_in_Current = true; } } if (result == S_OK) { if (_so) { RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)) *_so << endl; } } else { NumCantOpenArcs++; if (_so) _so->Flush(); if (_se) { *_se << kError; _se->NormalizePrint_wstr_Path(name); *_se << endl; const HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); RINOK(res) if (result == S_FALSE) { } else { if (result == E_OUTOFMEMORY) *_se << "Can't allocate required memory"; else *_se << NError::MyFormatMessage(result); *_se << endl; } _se->Flush(); } } return CheckBreak2(); } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { ClosePercents_for_so(); if (_so) { *_so << endl << kNoFiles << endl; if (NeedFlush) _so->Flush(); } return CheckBreak2(); } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { MT_LOCK if (NeedPercents()) { _percent.ClosePrint(true); _percent.Command.Empty(); _percent.FileName.Empty(); } if (_so) _so->Flush(); if (result == S_OK) { if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current) { if (ThereIsWarning_in_Current) NumArcsWithWarnings++; else NumOkArcs++; if (_so) *_so << kEverythingIsOk << endl; } else { NumArcsWithError++; if (_so) { *_so << endl; if (NumFileErrors_in_Current != 0) *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl; } } if (_so && NeedFlush) _so->Flush(); } else { // we don't update NumArcsWithError, if error is not related to archive data. if (result == E_ABORT || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)) return result; NumArcsWithError++; if (_se) { *_se << endl << kError; if (result == E_OUTOFMEMORY) *_se << kMemoryExceptionMessage; else *_se << NError::MyFormatMessage(result); *_se << endl; _se->Flush(); } } return CheckBreak2(); } tmp41wklro_/CPP/7zip/UI/Console/ExtractCallbackConsole.h0000444000175000001440000001071214634013460024120 0ustar nabijaczleweliusers// ExtractCallbackConsole.h #ifndef ZIP7_INC_EXTRACT_CALLBACK_CONSOLE_H #define ZIP7_INC_EXTRACT_CALLBACK_CONSOLE_H #include "../../../Common/StdOutStream.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" #include "PercentPrinter.h" #include "OpenCallbackConsole.h" /* struct CErrorPathCodes2 { FStringVector Paths; CRecordVector Codes; void AddError(const FString &path, DWORD systemError) { Paths.Add(path); Codes.Add(systemError); } void Clear() { Paths.Clear(); Codes.Clear(); } }; */ class CExtractScanConsole Z7_final: public IDirItemsCallback { Z7_IFACE_IMP(IDirItemsCallback) CStdOutStream *_so; CStdOutStream *_se; CPercentPrinter _percent; // CErrorPathCodes2 ScanErrors; bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; } void ClosePercentsAndFlush() { if (NeedPercents()) _percent.ClosePrint(true); if (_so) _so->Flush(); } public: void Init( CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream, bool disablePercents) { _so = outStream; _se = errorStream; _percent._so = percentStream; _percent.DisablePrint = disablePercents; } void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } void StartScanning(); void CloseScanning() { if (NeedPercents()) _percent.ClosePrint(true); } void PrintStat(const CDirItemsStat &st); }; class CExtractCallbackConsole Z7_final: public IFolderArchiveExtractCallback, public IExtractCallbackUI, // public IArchiveExtractCallbackMessage, public IFolderArchiveExtractCallback2, #ifndef Z7_NO_CRYPTO public ICryptoGetTextPassword, #endif #ifndef Z7_SFX public IArchiveRequestMemoryUseCallback, #endif public COpenCallbackConsole, public CMyUnknownImp { Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback) // Z7_COM_QI_ENTRY(IArchiveExtractCallbackMessage) Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2) #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY(ICryptoGetTextPassword) #endif #ifndef Z7_SFX Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback) Z7_IFACE_IMP(IExtractCallbackUI) // Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage) Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2) #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) #endif #ifndef Z7_SFX Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) #endif bool _needWriteArchivePath; public: bool ThereIsError_in_Current; bool ThereIsWarning_in_Current; bool NeedFlush; private: AString _tempA; UString _tempU; UString _currentArchivePath; UString _currentName; #ifndef Z7_SFX void PrintTo_se_Path_WithTitle(const UString &path, const char *title); void Add_ArchiveName_Error(); #endif void ClosePercents_for_so() { if (NeedPercents() && _so == _percent._so) _percent.ClosePrint(false); } void ClosePercentsAndFlush() { if (NeedPercents()) _percent.ClosePrint(true); if (_so) _so->Flush(); } public: UInt64 NumTryArcs; UInt64 NumOkArcs; UInt64 NumCantOpenArcs; UInt64 NumArcsWithError; UInt64 NumArcsWithWarnings; UInt64 NumOpenArcErrors; UInt64 NumOpenArcWarnings; UInt64 NumFileErrors; UInt64 NumFileErrors_in_Current; unsigned PercentsNameLevel; unsigned LogLevel; CExtractCallbackConsole(): _needWriteArchivePath(true), NeedFlush(false), PercentsNameLevel(1), LogLevel(0) {} void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } void Init( CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream, bool disablePercents) { COpenCallbackConsole::Init(outStream, errorStream, percentStream, disablePercents); NumTryArcs = 0; ThereIsError_in_Current = false; ThereIsWarning_in_Current = false; NumOkArcs = 0; NumCantOpenArcs = 0; NumArcsWithError = 0; NumArcsWithWarnings = 0; NumOpenArcErrors = 0; NumOpenArcWarnings = 0; NumFileErrors = 0; NumFileErrors_in_Current = 0; } }; #endif tmp41wklro_/CPP/7zip/UI/Console/HashCon.cpp0000444000175000001440000002255514561373640021444 0ustar nabijaczleweliusers// HashCon.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Windows/FileName.h" #include "ConsoleClose.h" #include "HashCon.h" static const char * const kEmptyFileAlias = "[Content]"; static const char * const kScanningMessage = "Scanning"; static HRESULT CheckBreak2() { return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } HRESULT CHashCallbackConsole::CheckBreak() { return CheckBreak2(); } HRESULT CHashCallbackConsole::StartScanning() { if (PrintHeaders && _so) *_so << kScanningMessage << endl; if (NeedPercents()) { _percent.ClearCurState(); _percent.Command = "Scan"; } return CheckBreak2(); } HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) { if (NeedPercents()) { _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; _percent.Completed = st.GetTotalBytes(); _percent.FileName = fs2us(path); if (isDir) NWindows::NFile::NName::NormalizeDirPathPrefix(_percent.FileName); _percent.Print(); } return CheckBreak2(); } HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError) { return ScanError_Base(path, systemError); } void Print_DirItemsStat(AString &s, const CDirItemsStat &st); HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st) { if (NeedPercents()) { _percent.ClosePrint(true); _percent.ClearCurState(); } if (PrintHeaders && _so) { Print_DirItemsStat(_s, st); *_so << _s << endl << endl; } return CheckBreak2(); } HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return CheckBreak2(); } HRESULT CHashCallbackConsole::SetTotal(UInt64 size) { if (NeedPercents()) { _percent.Total = size; _percent.Print(); } return CheckBreak2(); } HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue) { if (completeValue && NeedPercents()) { _percent.Completed = *completeValue; _percent.Print(); } return CheckBreak2(); } static void AddMinuses(AString &s, unsigned num) { for (unsigned i = 0; i < num; i++) s.Add_Minus(); } static void AddSpaces_if_Positive(AString &s, int num) { for (int i = 0; i < num; i++) s.Add_Space(); } static void SetSpacesAndNul(char *s, unsigned num) { for (unsigned i = 0; i < num; i++) s[i] = ' '; s[num] = 0; } static void SetSpacesAndNul_if_Positive(char *s, int num) { if (num < 0) return; for (int i = 0; i < num; i++) s[i] = ' '; s[num] = 0; } static const unsigned kSizeField_Len = 13; static const unsigned kNameField_Len = 12; static const unsigned kHashColumnWidth_Min = 4 * 2; static unsigned GetColumnWidth(unsigned digestSize) { unsigned width = digestSize * 2; return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width; } AString CHashCallbackConsole::GetFields() const { AString s (PrintFields); if (s.IsEmpty()) s = "hsn"; s.MakeLower_Ascii(); return s; } void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector &hashers) { _s.Empty(); const AString fields = GetFields(); for (unsigned pos = 0; pos < fields.Len(); pos++) { const char c = fields[pos]; if (c == 'h') { for (unsigned i = 0; i < hashers.Size(); i++) { AddSpace(); const CHasherState &h = hashers[i]; AddMinuses(_s, GetColumnWidth(h.DigestSize)); } } else if (c == 's') { AddSpace(); AddMinuses(_s, kSizeField_Len); } else if (c == 'n') { AddSpacesBeforeName(); AddMinuses(_s, kNameField_Len); } } *_so << _s << endl; } HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) { if (PrintHeaders && _so) { _s.Empty(); ClosePercents_for_so(); const AString fields = GetFields(); for (unsigned pos = 0; pos < fields.Len(); pos++) { const char c = fields[pos]; if (c == 'h') { FOR_VECTOR (i, hb.Hashers) { AddSpace(); const CHasherState &h = hb.Hashers[i]; _s += h.Name; AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len()); } } else if (c == 's') { AddSpace(); const AString s2 ("Size"); AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len()); _s += s2; } else if (c == 'n') { AddSpacesBeforeName(); _s += "Name"; } } *_so << _s << endl; PrintSeparatorLine(hb.Hashers); } return CheckBreak2(); } HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError) { return OpenFileError_Base(path, systemError); } HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool isDir) { _fileName = name; if (isDir) NWindows::NFile::NName::NormalizeDirPathPrefix(_fileName); if (NeedPercents()) { if (PrintNameInPercents) { _percent.FileName.Empty(); if (name) _percent.FileName = name; } _percent.Print(); } return CheckBreak2(); } static const unsigned k_DigestStringSize = k_HashCalc_DigestSize_Max * 2 + k_HashCalc_ExtraSize * 2 + 16; void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, const CObjectVector &hashers, unsigned digestIndex, bool showHash, const AString &path) { ClosePercents_for_so(); _s.Empty(); const AString fields = GetFields(); for (unsigned pos = 0; pos < fields.Len(); pos++) { const char c = fields[pos]; if (c == 'h') { FOR_VECTOR (i, hashers) { AddSpace(); const CHasherState &h = hashers[i]; char s[k_DigestStringSize]; s[0] = 0; if (showHash) h.WriteToString(digestIndex, s); const unsigned len = (unsigned)strlen(s); SetSpacesAndNul_if_Positive(s + len, (int)GetColumnWidth(h.DigestSize) - (int)len); _s += s; } } else if (c == 's') { AddSpace(); char s[kSizeField_Len + 32]; char *p = s; SetSpacesAndNul(s, kSizeField_Len); if (showHash) { p = s + kSizeField_Len; ConvertUInt64ToString(fileSize, p); const int numSpaces = (int)kSizeField_Len - (int)strlen(p); if (numSpaces > 0) p -= (unsigned)numSpaces; } _s += p; } else if (c == 'n') { AddSpacesBeforeName(); _s += path; } } *_so << _s; } HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) { if (_so) { AString s; if (_fileName.IsEmpty()) s = kEmptyFileAlias; else { UString temp (_fileName); _so->Normalize_UString_Path(temp); _so->Convert_UString_to_AString(temp, s); } PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash, s); /* PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); if (PrintName) { if (_fileName.IsEmpty()) *_so << kEmptyFileAlias; else _so->NormalizePrint_UString(_fileName); } */ // if (PrintNewLine) *_so << endl; } if (NeedPercents()) { _percent.Files++; _percent.Print(); } return CheckBreak2(); } static const char * const k_DigestTitles[] = { " : " , " for data: " , " for data and names: " , " for streams and names: " }; static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex) { so << h.Name; { AString temp; AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len()); so << temp; } so << k_DigestTitles[digestIndex]; char s[k_DigestStringSize]; // s[0] = 0; h.WriteToString(digestIndex, s); so << s << endl; } void PrintHashStat(CStdOutStream &so, const CHashBundle &hb) { FOR_VECTOR (i, hb.Hashers) { const CHasherState &h = hb.Hashers[i]; PrintSum(so, h, k_HashCalc_Index_DataSum); if (hb.NumFiles != 1 || hb.NumDirs != 0) PrintSum(so, h, k_HashCalc_Index_NamesSum); if (hb.NumAltStreams != 0) PrintSum(so, h, k_HashCalc_Index_StreamsSum); so << endl; } } void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value) { char s[32]; s[0] = ':'; s[1] = ' '; ConvertUInt64ToString(value, s + 2); *_so << name << s << endl; } HRESULT CHashCallbackConsole::AfterLastFile(CHashBundle &hb) { ClosePercents2(); if (PrintHeaders && _so) { PrintSeparatorLine(hb.Hashers); PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true, AString()); *_so << endl << endl; if (hb.NumFiles != 1 || hb.NumDirs != 0) { if (hb.NumDirs != 0) PrintProperty("Folders", hb.NumDirs); PrintProperty("Files", hb.NumFiles); } PrintProperty("Size", hb.FilesSize); if (hb.NumAltStreams != 0) { PrintProperty("Alternate streams", hb.NumAltStreams); PrintProperty("Alternate streams size", hb.AltStreamsSize); } *_so << endl; PrintHashStat(*_so, hb); } return S_OK; } tmp41wklro_/CPP/7zip/UI/Console/HashCon.h0000444000175000001440000000243514412474560021102 0ustar nabijaczleweliusers// HashCon.h #ifndef ZIP7_INC_HASH_CON_H #define ZIP7_INC_HASH_CON_H #include "../Common/HashCalc.h" #include "UpdateCallbackConsole.h" class CHashCallbackConsole Z7_final: public IHashCallbackUI, public CCallbackConsoleBase { Z7_IFACE_IMP(IDirItemsCallback) Z7_IFACE_IMP(IHashCallbackUI) UString _fileName; AString _s; void AddSpace() { _s.Add_Space_if_NotEmpty(); } void AddSpacesBeforeName() { if (!_s.IsEmpty()) { _s.Add_Space(); _s.Add_Space(); } } void PrintSeparatorLine(const CObjectVector &hashers); void PrintResultLine(UInt64 fileSize, const CObjectVector &hashers, unsigned digestIndex, bool showHash, const AString &path); void PrintProperty(const char *name, UInt64 value); public: bool PrintNameInPercents; bool PrintHeaders; // bool PrintSize; // bool PrintNewLine; // set it too (false), if you need only hash for single file without LF char. AString PrintFields; AString GetFields() const; CHashCallbackConsole(): PrintNameInPercents(true), PrintHeaders(false) // , PrintSize(true), // , PrintNewLine(true) {} }; void PrintHashStat(CStdOutStream &so, const CHashBundle &hb); #endif tmp41wklro_/CPP/7zip/UI/Console/List.cpp0000444000175000001440000010567514630250140021023 0ustar nabijaczleweliusers// List.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Common/MyCom.h" #include "../../../Common/StdOutStream.h" #include "../../../Common/StringConvert.h" #include "../../../Common/UTFConvert.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" #include "../Common/OpenArchive.h" #include "../Common/PropIDUtils.h" #include "ConsoleClose.h" #include "List.h" #include "OpenCallbackConsole.h" using namespace NWindows; using namespace NCOM; extern CStdOutStream *g_StdStream; extern CStdOutStream *g_ErrStream; static const char * const kPropIdToName[] = { "0" , "1" , "2" , "Path" , "Name" , "Extension" , "Folder" , "Size" , "Packed Size" , "Attributes" , "Created" , "Accessed" , "Modified" , "Solid" , "Commented" , "Encrypted" , "Split Before" , "Split After" , "Dictionary Size" , "CRC" , "Type" , "Anti" , "Method" , "Host OS" , "File System" , "User" , "Group" , "Block" , "Comment" , "Position" , "Path Prefix" , "Folders" , "Files" , "Version" , "Volume" , "Multivolume" , "Offset" , "Links" , "Blocks" , "Volumes" , "Time Type" , "64-bit" , "Big-endian" , "CPU" , "Physical Size" , "Headers Size" , "Checksum" , "Characteristics" , "Virtual Address" , "ID" , "Short Name" , "Creator Application" , "Sector Size" , "Mode" , "Symbolic Link" , "Error" , "Total Size" , "Free Space" , "Cluster Size" , "Label" , "Local Name" , "Provider" , "NT Security" , "Alternate Stream" , "Aux" , "Deleted" , "Tree" , "SHA-1" , "SHA-256" , "Error Type" , "Errors" , "Errors" , "Warnings" , "Warning" , "Streams" , "Alternate Streams" , "Alternate Streams Size" , "Virtual Size" , "Unpack Size" , "Total Physical Size" , "Volume Index" , "SubType" , "Short Comment" , "Code Page" , "Is not archive type" , "Physical Size can't be detected" , "Zeros Tail Is Allowed" , "Tail Size" , "Embedded Stub Size" , "Link" , "Hard Link" , "iNode" , "Stream ID" , "Read-only" , "Out Name" , "Copy Link" , "ArcFileName" , "IsHash" , "Metadata Changed" , "User ID" , "Group ID" , "Device Major" , "Device Minor" , "Dev Major" , "Dev Minor" }; static const char kEmptyAttribChar = '.'; static const char * const kListing = "Listing archive: "; static const char * const kString_Files = "files"; static const char * const kString_Dirs = "folders"; static const char * const kString_AltStreams = "alternate streams"; static const char * const kString_Streams = "streams"; static const char * const kError = "ERROR: "; static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s) { if (isDir) wa |= FILE_ATTRIBUTE_DIRECTORY; if (allAttribs) { ConvertWinAttribToString(s, wa); return; } s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = 0; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; bool IsRawProp; UString NameU; AString NameA; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; unsigned PrefixSpacesWidth; unsigned Width; }; struct CFieldInfoInit { PROPID PropID; const char *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; unsigned PrefixSpacesWidth; unsigned Width; }; static const CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, " Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, "Attr", kRight, kCenter, 1, 5 }, { kpidSize, "Size", kRight, kRight, 1, 12 }, { kpidPackSize, "Compressed", kRight, kRight, 1, 12 }, { kpidPath, "Name", kLeft, kLeft, 2, 24 } }; const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width static const char *g_Spaces = " " ; static void PrintSpaces(unsigned numSpaces) { if (numSpaces > 0 && numSpaces <= kNumSpacesMax) g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces); } static void PrintSpacesToString(char *dest, unsigned numSpaces) { unsigned i; for (i = 0; i < numSpaces; i++) dest[i] = ' '; dest[i] = 0; } // extern int g_CodePage; static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp) { /* // we don't need multibyte align. int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, temp); else UnicodeStringToMultiByte2(temp, s, (UINT)codePage); */ unsigned numSpaces = 0; if (width > s.Len()) { numSpaces = width - s.Len(); unsigned numLeftSpaces = 0; switch ((int)adj) { // case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; // case kLeft: default: break; } PrintSpaces(numLeftSpaces); numSpaces -= numLeftSpaces; } g_StdOut.PrintUString(s, temp); PrintSpaces(numSpaces); } static void PrintString(EAdjustment adj, unsigned width, const char *s) { unsigned numSpaces = 0; unsigned len = (unsigned)strlen(s); if (width > len) { numSpaces = width - len; unsigned numLeftSpaces = 0; switch ((int)adj) { // case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; // case kLeft: default: break; } PrintSpaces(numLeftSpaces); numSpaces -= numLeftSpaces; } g_StdOut << s; PrintSpaces(numSpaces); } static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString) { unsigned numSpaces = 0; unsigned len = (unsigned)strlen(textString); if (width > len) { numSpaces = width - len; unsigned numLeftSpaces = 0; switch ((int)adj) { // case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; // case kLeft: default: break; } PrintSpacesToString(dest, numLeftSpaces); dest += numLeftSpaces; numSpaces -= numLeftSpaces; } memcpy(dest, textString, len); dest += len; PrintSpacesToString(dest, numSpaces); } struct CListUInt64Def { UInt64 Val; bool Def; CListUInt64Def(): Val(0), Def(false) {} void Add(UInt64 v) { Val += v; Def = true; } void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); } }; struct CListFileTimeDef: public CArcTime { void Update(const CListFileTimeDef &t) { if (t.Def && (!Def || CompareWith(t) < 0)) (*this) = t; } }; struct CListStat { CListUInt64Def Size; CListUInt64Def PackSize; CListFileTimeDef MTime; UInt64 NumFiles; CListStat(): NumFiles(0) {} void Update(const CListStat &st) { Size.Add(st.Size); PackSize.Add(st.PackSize); MTime.Update(st.MTime); NumFiles += st.NumFiles; } void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; } }; struct CListStat2 { CListStat MainFiles; CListStat AltStreams; UInt64 NumDirs; CListStat2(): NumDirs(0) {} void Update(const CListStat2 &st) { MainFiles.Update(st.MainFiles); AltStreams.Update(st.AltStreams); NumDirs += st.NumDirs; } UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; } }; class CFieldPrinter { CObjectVector _fields; void AddProp(const wchar_t *name, PROPID propID, bool isRawProp); public: const CArc *Arc; bool TechMode; UString FilePath; AString TempAString; UString TempWString; bool IsDir; AString LinesString; void Clear() { _fields.Clear(); LinesString.Empty(); } void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems); HRESULT AddMainProps(IInArchive *archive); HRESULT AddRawProps(IArchiveGetRawProps *getRawProps); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(UInt32 index, const CListStat &st); void PrintSum(const CListStat &st, UInt64 numDirs, const char *str); void PrintSum(const CListStat2 &stat2); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems) { Clear(); for (unsigned i = 0; i < numItems; i++) { CFieldInfo &f = _fields.AddNew(); const CFieldInfoInit &fii = standardFieldTable[i]; f.PropID = fii.PropID; f.IsRawProp = false; f.NameA = fii.Name; f.TitleAdjustment = fii.TitleAdjustment; f.TextAdjustment = fii.TextAdjustment; f.PrefixSpacesWidth = fii.PrefixSpacesWidth; f.Width = fii.Width; unsigned k; for (k = 0; k < fii.PrefixSpacesWidth; k++) LinesString.Add_Space(); for (k = 0; k < fii.Width; k++) LinesString.Add_Minus(); } } static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU) { if (propID < Z7_ARRAY_SIZE(kPropIdToName)) { nameA = kPropIdToName[propID]; return; } if (name) nameU = name; else { nameA.Empty(); nameA.Add_UInt32(propID); } } void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp) { CFieldInfo f; f.PropID = propID; f.IsRawProp = isRawProp; GetPropName(propID, name, f.NameA, f.NameU); f.NameU += " = "; if (!f.NameA.IsEmpty()) f.NameA += " = "; else { const UString &s = f.NameU; AString sA; unsigned i; for (i = 0; i < s.Len(); i++) { const wchar_t c = s[i]; if (c >= 0x80) break; sA.Add_Char((char)c); } if (i == s.Len()) f.NameA = sA; } _fields.Add(f); } HRESULT CFieldPrinter::AddMainProps(IInArchive *archive) { UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)) for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)) AddProp(name, propID, false); } return S_OK; } HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps) { UInt32 numProps; RINOK(getRawProps->GetNumRawProps(&numProps)) for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; RINOK(getRawProps->GetRawPropInfo(i, &name, &propID)) AddProp(name, propID, true); } return S_OK; } void CFieldPrinter::PrintTitle() { FOR_VECTOR (i, _fields) { const CFieldInfo &f = _fields[i]; PrintSpaces(f.PrefixSpacesWidth); PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA); } } void CFieldPrinter::PrintTitleLines() { g_StdOut << LinesString; } static void PrintTime(char *dest, const CListFileTimeDef &t, bool showNS) { *dest = 0; if (t.IsZero()) return; int prec = kTimestampPrintLevel_SEC; unsigned flags = 0; if (showNS) // techmode { prec = kTimestampPrintLevel_NTFS; if (t.Prec != 0) { prec = t.GetNumDigits(); if (prec < kTimestampPrintLevel_DAY) prec = kTimestampPrintLevel_NTFS; } } else { // we want same default number of characters, so we disable 'Z' marker: flags = kTimestampPrintFlags_DisableZ; } ConvertUtcFileTimeToString2(t.FT, t.Ns100, dest, prec, flags); } #ifndef Z7_SFX #endif #define MY_ENDL endl inline bool IsPropId_for_PathString(UInt32 propId) { return (propId == kpidPath // || propId == kpidName || propId == kpidSymLink || propId == kpidHardLink || propId == kpidCopyLink); } HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) { char temp[128]; size_t tempPos = 0; bool techMode = this->TechMode; /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ FOR_VECTOR (i, _fields) { const CFieldInfo &f = _fields[i]; if (!techMode) { PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth); tempPos += f.PrefixSpacesWidth; } if (techMode) { if (!f.NameA.IsEmpty()) g_StdOut << f.NameA; else g_StdOut << f.NameU; } if (f.PropID == kpidPath) { if (!techMode) g_StdOut << temp; g_StdOut.NormalizePrint_UString_Path(FilePath, TempWString, TempAString); if (techMode) g_StdOut << MY_ENDL; continue; } const unsigned width = f.Width; if (f.IsRawProp) { #ifndef Z7_SFX const void *data; UInt32 dataSize; UInt32 propType; RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType)) if (dataSize != 0) { bool needPrint = true; if (f.PropID == kpidNtSecure) { if (propType != NPropDataType::kRaw) return E_FAIL; #ifndef Z7_SFX ConvertNtSecureToString((const Byte *)data, dataSize, TempAString); g_StdOut << TempAString; needPrint = false; #endif } else if (f.PropID == kpidNtReparse) { UString s; if (ConvertNtReparseToString((const Byte *)data, dataSize, s)) { needPrint = false; g_StdOut.PrintUString(s, TempAString); } } if (needPrint) { if (propType != NPropDataType::kRaw) return E_FAIL; const UInt32 kMaxDataSize = 64; if (dataSize > kMaxDataSize) { g_StdOut << "data:"; g_StdOut << dataSize; } else { char hexStr[kMaxDataSize * 2 + 4]; ConvertDataToHex_Lower(hexStr, (const Byte *)data, dataSize); g_StdOut << hexStr; } } } #endif } else { CPropVariant prop; switch (f.PropID) { case kpidSize: if (st.Size.Def) prop = st.Size.Val; break; case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break; case kpidMTime: { const CListFileTimeDef &mtime = st.MTime; if (mtime.Def) prop.SetAsTimeFrom_FT_Prec_Ns100(mtime.FT, mtime.Prec, mtime.Ns100); break; } default: RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)) } if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) { GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos); if (techMode) g_StdOut << temp + tempPos; else tempPos += strlen(temp + tempPos); } else if (prop.vt == VT_EMPTY) { if (!techMode) { PrintSpacesToString(temp + tempPos, width); tempPos += width; } } else if (prop.vt == VT_FILETIME) { CListFileTimeDef t; t.Set_From_Prop(prop); PrintTime(temp + tempPos, t, techMode); if (techMode) g_StdOut << temp + tempPos; else { size_t len = strlen(temp + tempPos); tempPos += len; if (len < (unsigned)f.Width) { len = f.Width - len; PrintSpacesToString(temp + tempPos, (unsigned)len); tempPos += len; } } } else if (prop.vt == VT_BSTR) { TempWString.SetFromBstr(prop.bstrVal); // do we need multi-line support here ? if (IsPropId_for_PathString(f.PropID)) g_StdOut.Normalize_UString_Path(TempWString); else g_StdOut.Normalize_UString(TempWString); if (techMode) g_StdOut.PrintUString(TempWString, TempAString); else PrintUString(f.TextAdjustment, width, TempWString, TempAString); } else { char s[64]; ConvertPropertyToShortString2(s, prop, f.PropID); if (techMode) g_StdOut << s; else { PrintStringToString(temp + tempPos, f.TextAdjustment, width, s); tempPos += strlen(temp + tempPos); } } } if (techMode) g_StdOut << MY_ENDL; } g_StdOut << MY_ENDL; return S_OK; } static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value) { char s[32]; s[0] = 0; if (value.Def) ConvertUInt64ToString(value.Val, s); PrintString(adj, width, s); } void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str) { FOR_VECTOR (i, _fields) { const CFieldInfo &f = _fields[i]; PrintSpaces(f.PrefixSpacesWidth); if (f.PropID == kpidSize) PrintNumber(f.TextAdjustment, f.Width, st.Size); else if (f.PropID == kpidPackSize) PrintNumber(f.TextAdjustment, f.Width, st.PackSize); else if (f.PropID == kpidMTime) { char s[64]; s[0] = 0; if (st.MTime.Def) PrintTime(s, st.MTime, false); // showNS PrintString(f.TextAdjustment, f.Width, s); } else if (f.PropID == kpidPath) { AString s; Print_UInt64_and_String(s, st.NumFiles, str); if (numDirs != 0) { s += ", "; Print_UInt64_and_String(s, numDirs, kString_Dirs); } PrintString(f.TextAdjustment, 0, s); } else PrintString(f.TextAdjustment, f.Width, ""); } g_StdOut << endl; } void CFieldPrinter::PrintSum(const CListStat2 &stat2) { PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files); if (stat2.AltStreams.NumFiles != 0) { PrintSum(stat2.AltStreams, 0, kString_AltStreams); CListStat st = stat2.MainFiles; st.Update(stat2.AltStreams); PrintSum(st, 0, kString_Streams); } } static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value) { value.Val = 0; value.Def = false; CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)) value.Def = ConvertPropVariantToUInt64(prop, value.Val); return S_OK; } static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t) { /* maybe we could call CArc::GetItemMTime(UInt32 index, CArcTime &ft, bool &defined) here that can set default timestamp, if not defined */ t.Clear(); // t.Def = false; CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)) if (prop.vt == VT_FILETIME) t.Set_From_Prop(prop); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val) { so << name << ": " << val << endl; } static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID) { const char *s; char temp[16]; if (propID < Z7_ARRAY_SIZE(kPropIdToName)) s = kPropIdToName[propID]; else { ConvertUInt32ToString(propID, temp); s = temp; } so << s << " = "; } static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val) { PrintPropName_and_Eq(so, propID); so << val << endl; } static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val) { PrintPropName_and_Eq(so, propID); so << val << endl; } static void UString_Replace_CRLF_to_LF(UString &s) { // s.Replace(L"\r\n", L"\n"); wchar_t *src = s.GetBuf(); wchar_t *dest = src; for (;;) { wchar_t c = *src++; if (c == 0) break; if (c == '\r' && *src == '\n') { src++; c = '\n'; } *dest++ = c; } s.ReleaseBuf_SetEnd((unsigned)(size_t)(dest - s.GetBuf())); } static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val) { UString s (val); if (s.Find(L'\n') >= 0) { so << endl; so << "{"; so << endl; UString_Replace_CRLF_to_LF(s); UString temp; unsigned start = 0; for (;;) { unsigned size = s.Len() - start; if (size == 0) break; const int next = s.Find(L'\n', start); if (next >= 0) size = (unsigned)next - start; temp.SetFrom(s.Ptr() + start, size); so.NormalizePrint_UString(temp); so << endl; if (next < 0) break; start = (unsigned)next + 1; } so << "}"; } else { so.NormalizePrint_UString(s); } so << endl; } static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine, bool isPath = false) { so << name << " = "; if (multiLine) { PrintPropVal_MultiLine(so, val); return; } UString s (val); if (isPath) so.Normalize_UString_Path(s); else so.Normalize_UString(s); so << s; so << endl; } static void PrintPropPair_Path(CStdOutStream &so, const wchar_t *path) { PrintPropPair(so, "Path", path, false, // multiLine true); // isPath } static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) { UString s; const int levelTopLimit = 9; // 1ns level ConvertPropertyToString2(s, prop, propID, levelTopLimit); if (!s.IsEmpty()) { AString nameA; UString nameU; GetPropName(propID, name, nameA, nameU); if (!nameA.IsEmpty()) so << nameA; else so << nameU; so << " = "; PrintPropVal_MultiLine(so, s); } } static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name) { CPropVariant prop; RINOK(archive->GetArchiveProperty(propID, &prop)) PrintPropertyPair2(so, propID, name, prop); return S_OK; } static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning) { so << "Open " << (isWarning ? "WARNING" : "ERROR") << ": Cannot open the file as [" << type << "] archive" << endl; } int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name); void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er) { PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags()); if (!er.ErrorMessage.IsEmpty()) PrintPropPair(so, "ERROR", er.ErrorMessage, true); PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags()); if (!er.WarningMessage.IsEmpty()) PrintPropPair(so, "WARNING", er.WarningMessage, true); } HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) { FOR_VECTOR (r, arcLink.Arcs) { const CArc &arc = arcLink.Arcs[r]; const CArcErrorInfo &er = arc.ErrorInfo; so << "--\n"; PrintPropPair_Path(so, arc.Path); if (er.ErrorFormatIndex >= 0) { if (er.ErrorFormatIndex == arc.FormatIndex) so << "Warning: The archive is open with offset" << endl; else PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true); } PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex), false); ErrorInfo_Print(so, er); Int64 offset = arc.GetGlobalOffset(); if (offset != 0) PrintPropNameAndNumber_Signed(so, kpidOffset, offset); IInArchive *archive = arc.Archive; RINOK(PrintArcProp(so, archive, kpidPhySize, NULL)) if (er.TailSize != 0) PrintPropNameAndNumber(so, kpidTailSize, er.TailSize); { UInt32 numProps; RINOK(archive->GetNumberOfArchiveProperties(&numProps)) for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)) RINOK(PrintArcProp(so, archive, propID, name)) } } if (r != arcLink.Arcs.Size() - 1) { UInt32 numProps; so << "----\n"; if (archive->GetNumberOfProperties(&numProps) == S_OK) { UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex; for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)) CPropVariant prop; RINOK(archive->GetProperty(mainIndex, propID, &prop)) PrintPropertyPair2(so, propID, name, prop); } } } } return S_OK; } HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) { #ifndef Z7_NO_CRYPTO if (arcLink.PasswordWasAsked) so << "Cannot open encrypted archive. Wrong password?"; else #endif { if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) { so.NormalizePrint_UString_Path(arcLink.NonOpen_ArcPath); so << endl; PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); } else so << "Cannot open the file as archive"; } so << endl; so << endl; ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo); return S_OK; } bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); HRESULT ListArchives( const CListOptions &listOptions, CCodecs *codecs, const CObjectVector &types, const CIntVector &excludedFormats, bool stdInMode, UStringVector &arcPaths, UStringVector &arcPathsFull, bool processAltStreams, bool showAltStreams, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef Z7_NO_CRYPTO bool &passwordEnabled, UString &password, #endif #ifndef Z7_SFX const CObjectVector *props, #endif UInt64 &numErrors, UInt64 &numWarnings) { bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); numErrors = 0; numWarnings = 0; CFieldPrinter fp; if (!techMode) fp.Init(kStandardFieldTable, Z7_ARRAY_SIZE(kStandardFieldTable)); CListStat2 stat2total; CBoolArr skipArcs(arcPaths.Size()); unsigned arcIndex; for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) skipArcs[arcIndex] = false; UInt64 numVolumes = 0; UInt64 numArcs = 0; UInt64 totalArcSizes = 0; HRESULT lastError = 0; for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) { if (skipArcs[arcIndex]) continue; const UString &arcPath = arcPaths[arcIndex]; UInt64 arcPackSize = 0; if (!stdInMode) { NFile::NFind::CFileInfo fi; if (!fi.Find_FollowLink(us2fs(arcPath))) { DWORD errorCode = GetLastError(); if (errorCode == 0) errorCode = ERROR_FILE_NOT_FOUND; lastError = HRESULT_FROM_WIN32(errorCode); g_StdOut.Flush(); if (g_ErrStream) { *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl; g_ErrStream->NormalizePrint_UString_Path(arcPath); *g_ErrStream << endl << endl; } numErrors++; continue; } if (fi.IsDir()) { g_StdOut.Flush(); if (g_ErrStream) { *g_ErrStream << endl << kError; g_ErrStream->NormalizePrint_UString_Path(arcPath); *g_ErrStream << " is not a file" << endl << endl; } numErrors++; continue; } arcPackSize = fi.Size; totalArcSizes += arcPackSize; } CArchiveLink arcLink; COpenCallbackConsole openCallback; openCallback.Init(&g_StdOut, g_ErrStream, NULL, listOptions.DisablePercents); #ifndef Z7_NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif /* CObjectVector optPropsVector; COptionalOpenProperties &optProps = optPropsVector.AddNew(); optProps.Props = *props; */ COpenOptions options; #ifndef Z7_SFX options.props = props; #endif options.codecs = codecs; options.types = &types; options.excludedFormats = &excludedFormats; options.stdInMode = stdInMode; options.stream = NULL; options.filePath = arcPath; if (enableHeaders) { g_StdOut << endl << kListing; g_StdOut.NormalizePrint_UString_Path(arcPath); g_StdOut << endl << endl; } HRESULT result = arcLink.Open_Strict(options, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; if (result != S_FALSE) lastError = result; g_StdOut.Flush(); if (g_ErrStream) { *g_ErrStream << endl << kError; g_ErrStream->NormalizePrint_UString_Path(arcPath); *g_ErrStream << " : "; if (result == S_FALSE) { Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink); } else { *g_ErrStream << "opening : "; if (result == E_OUTOFMEMORY) *g_ErrStream << "Can't allocate required memory"; else *g_ErrStream << NError::MyFormatMessage(result); } *g_ErrStream << endl; } numErrors++; continue; } { FOR_VECTOR (r, arcLink.Arcs) { const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo; if (!arc.WarningMessage.IsEmpty()) numWarnings++; if (arc.AreThereWarnings()) numWarnings++; if (arc.ErrorFormatIndex >= 0) numWarnings++; if (arc.AreThereErrors()) { numErrors++; // break; } if (!arc.ErrorMessage.IsEmpty()) numErrors++; } } numArcs++; numVolumes++; if (!stdInMode) { numVolumes += arcLink.VolumePaths.Size(); totalArcSizes += arcLink.VolumesSize; FOR_VECTOR (v, arcLink.VolumePaths) { int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); if (index >= 0 && (unsigned)index > arcIndex) skipArcs[(unsigned)index] = true; } } if (enableHeaders) { RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink)) g_StdOut << endl; if (techMode) g_StdOut << "----------\n"; } if (enableHeaders && !techMode) { fp.PrintTitle(); g_StdOut << endl; fp.PrintTitleLines(); g_StdOut << endl; } const CArc &arc = arcLink.Arcs.Back(); fp.Arc = &arc; fp.TechMode = techMode; IInArchive *archive = arc.Archive; if (techMode) { fp.Clear(); RINOK(fp.AddMainProps(archive)) if (arc.GetRawProps) { RINOK(fp.AddRawProps(arc.GetRawProps)) } } CListStat2 stat2; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) CReadArcItem item; UStringVector pathParts; for (UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; HRESULT res = arc.GetItem_Path2(i, fp.FilePath); if (stdInMode && res == E_INVALIDARG) break; RINOK(res) if (arc.Ask_Aux) { bool isAux; RINOK(Archive_IsItem_Aux(archive, i, isAux)) if (isAux) continue; } bool isAltStream = false; if (arc.Ask_AltStream) { RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)) if (isAltStream && !processAltStreams) continue; } RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir)) if (fp.IsDir ? listOptions.ExcludeDirItems : listOptions.ExcludeFileItems) continue; if (!allFilesAreAllowed) { if (isAltStream) { RINOK(arc.GetItem(i, item)) if (!CensorNode_CheckPath(wildcardCensor, item)) continue; } else { SplitPathToParts(fp.FilePath, pathParts); bool include; if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include)) continue; if (!include) continue; } } CListStat st; RINOK(GetUInt64Value(archive, i, kpidSize, st.Size)) RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize)) RINOK(GetItemMTime(archive, i, st.MTime)) if (fp.IsDir) stat2.NumDirs++; else st.NumFiles = 1; stat2.GetStat(isAltStream).Update(st); if (isAltStream && !showAltStreams) continue; RINOK(fp.PrintItemInfo(i, st)) } UInt64 numStreams = stat2.GetNumStreams(); if (!stdInMode && !stat2.MainFiles.PackSize.Def && !stat2.AltStreams.PackSize.Def) { if (arcLink.VolumePaths.Size() != 0) arcPackSize += arcLink.VolumesSize; stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize); } stat2.MainFiles.SetSizeDefIfNoFiles(); stat2.AltStreams.SetSizeDefIfNoFiles(); if (enableHeaders && !techMode) { fp.PrintTitleLines(); g_StdOut << endl; fp.PrintSum(stat2); } if (enableHeaders) { if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) { g_StdOut << "----------\n"; PrintPropPair_Path(g_StdOut, arcLink.NonOpen_ArcPath); PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); } } stat2total.Update(stat2); g_StdOut.Flush(); } if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1)) { g_StdOut << endl; fp.PrintTitleLines(); g_StdOut << endl; fp.PrintSum(stat2total); g_StdOut << endl; PrintPropNameAndNumber(g_StdOut, "Archives", numArcs); PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes); PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes); } if (numErrors == 1 && lastError != 0) return lastError; return S_OK; } tmp41wklro_/CPP/7zip/UI/Console/List.h0000444000175000001440000000171414630250140020455 0ustar nabijaczleweliusers// List.h #ifndef ZIP7_INC_LIST_H #define ZIP7_INC_LIST_H #include "../../../Common/Wildcard.h" #include "../Common/LoadCodecs.h" struct CListOptions { bool ExcludeDirItems; bool ExcludeFileItems; bool DisablePercents; CListOptions(): ExcludeDirItems(false), ExcludeFileItems(false), DisablePercents(false) {} }; HRESULT ListArchives( const CListOptions &listOptions, CCodecs *codecs, const CObjectVector &types, const CIntVector &excludedFormats, bool stdInMode, UStringVector &archivePaths, UStringVector &archivePathsFull, bool processAltStreams, bool showAltStreams, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef Z7_NO_CRYPTO bool &passwordEnabled, UString &password, #endif #ifndef Z7_SFX const CObjectVector *props, #endif UInt64 &errors, UInt64 &numWarnings); #endif tmp41wklro_/CPP/7zip/UI/Console/Main.cpp0000444000175000001440000012607514634013460020777 0ustar nabijaczleweliusers// Main.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #ifdef _WIN32 #ifndef Z7_OLD_WIN_SDK #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif #else // Z7_OLD_WIN_SDK typedef struct { DWORD cb; DWORD PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; } PROCESS_MEMORY_COUNTERS; typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS; #endif // Z7_OLD_WIN_SDK #else // _WIN32 #include #include #include #include #endif // _WIN32 #include "../../../../C/CpuArch.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/IntToString.h" #include "../../../Common/MyException.h" #include "../../../Common/StdInStream.h" #include "../../../Common/StdOutStream.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../../Common/UTFConvert.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/TimeUtils.h" #include "../../../Windows/FileDir.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/Bench.h" #include "../Common/ExitCode.h" #include "../Common/Extract.h" #ifdef Z7_EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Common/RegisterCodec.h" #include "BenchCon.h" #include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "HashCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "UpdateCallbackConsole.h" #ifdef Z7_PROG_VARIANT_R #include "../../../../C/7zVersion.h" #else #include "../../MyVersion.h" #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; #ifdef _WIN32 extern HINSTANCE g_hInstance; HINSTANCE g_hInstance = NULL; #endif extern CStdOutStream *g_StdStream; extern CStdOutStream *g_ErrStream; extern unsigned g_NumCodecs; extern const CCodecInfo *g_Codecs[]; extern unsigned g_NumHashers; extern const CHasherInfo *g_Hashers[]; #ifdef Z7_EXTERNAL_CODECS extern const CExternalCodecs *g_ExternalCodecs_Ptr; const CExternalCodecs *g_ExternalCodecs_Ptr; #endif DECLARE_AND_SET_CLIENT_VERSION_VAR #if defined(Z7_PROG_VARIANT_Z) #define PROG_POSTFIX "z" #define PROG_POSTFIX_2 " (z)" #elif defined(Z7_PROG_VARIANT_R) #define PROG_POSTFIX "r" #define PROG_POSTFIX_2 " (r)" #elif defined(Z7_PROG_VARIANT_A) || !defined(Z7_EXTERNAL_CODECS) #define PROG_POSTFIX "a" #define PROG_POSTFIX_2 " (a)" #else #define PROG_POSTFIX "" #define PROG_POSTFIX_2 "" #endif static const char * const kCopyrightString = "\n7-Zip" PROG_POSTFIX_2 " " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n"; static const char * const kHelpString = "Usage: 7z" PROG_POSTFIX " [...] [...] [@listfile]\n" "\n" "\n" " a : Add files to archive\n" " b : Benchmark\n" " d : Delete files from archive\n" " e : Extract files from archive (without using directory names)\n" " h : Calculate hash values for files\n" " i : Show information about supported formats\n" " l : List contents of archive\n" " rn : Rename files in archive\n" " t : Test integrity of archive\n" " u : Update files to archive\n" " x : eXtract files with full paths\n" "\n" "\n" " -- : Stop switches and @listfile parsing\n" " -ai[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include archives\n" " -ax[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude archives\n" " -ao{a|s|t|u} : set Overwrite mode\n" " -an : disable archive_name field\n" " -bb[0-3] : set output log level\n" " -bd : disable progress indicator\n" " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n" " -bt : show execution time statistics\n" " -i[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include filenames\n" " -m{Parameters} : set compression Method\n" " -mmt[N] : set number of CPU threads\n" " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n" " -o{Directory} : set Output directory\n" #ifndef Z7_NO_CRYPTO " -p{Password} : set Password\n" #endif " -r[-|0] : Recurse subdirectories for name search\n" " -sa{a|e|s} : set Archive name mode\n" " -scc{UTF-8|WIN|DOS} : set charset for console input/output\n" " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" " -scrc[CRC32|CRC64|SHA256" #ifndef Z7_PROG_VARIANT_R "|SHA1|XXH64" #ifdef Z7_PROG_VARIANT_Z "|BLAKE2SP" #endif #endif "|*] : set hash function for x, e, h commands\n" " -sdel : delete files after compression\n" " -seml[.] : send archive by email\n" " -sfx[{name}] : Create SFX archive\n" " -si[{name}] : read data from stdin\n" " -slp : set Large Pages mode\n" " -slt : show technical information for l (List) command\n" " -snh : store hard links as links\n" " -snl : store symbolic links as links\n" " -sni : store NT security information\n" " -sns[-] : store NTFS alternate streams\n" " -so : write data to stdout\n" " -spd : disable wildcard matching for file names\n" " -spe : eliminate duplication of root folder for extract command\n" " -spf[2] : use fully qualified file paths\n" " -ssc[-] : set sensitive case mode\n" " -sse : stop archive creating, if it can't open some input file\n" " -ssp : do not change Last Access Time of source files while archiving\n" " -ssw : compress shared files\n" " -stl : set archive timestamp from the most recently modified file\n" " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n" " -stx{Type} : exclude archive type\n" " -t{Type} : Set type of archive\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" " -v{Size}[b|k|m|g] : Create volumes\n" " -w[{path}] : assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude filenames\n" " -y : assume Yes on all queries\n"; // --------------------------- // exception messages static const char * const kEverythingIsOk = "Everything is Ok"; static const char * const kUserErrorMessage = "Incorrect command line"; static const char * const kNoFormats = "7-Zip cannot find the code that works with archives."; static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type"; // static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type"; #ifndef Z7_EXTRACT_ONLY #define kDefaultSfxModule "7zCon.sfx" #endif Z7_ATTR_NORETURN static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) { if (g_ErrStream) *g_ErrStream << endl << "ERROR: " << message << endl; throw code; } #ifdef _WIN32 #define ShowProgInfo(so) #else static void ShowProgInfo(CStdOutStream *so) { if (!so) return; *so /* #ifdef __DATE__ << " " << __DATE__ #endif #ifdef __TIME__ << " " << __TIME__ #endif */ << " " << (unsigned)(sizeof(void *)) * 8 << "-bit" #ifdef __ILP32__ << " ILP32" #endif #ifdef __ARM_ARCH << " arm_v:" << __ARM_ARCH #if (__ARM_ARCH == 8) // for macos: #if defined(__ARM_ARCH_8_9__) << ".9" #elif defined(__ARM_ARCH_8_8__) << ".8" #elif defined(__ARM_ARCH_8_7__) << ".7" #elif defined(__ARM_ARCH_8_6__) << ".6" #elif defined(__ARM_ARCH_8_5__) << ".5" #elif defined(__ARM_ARCH_8_4__) << ".4" #elif defined(__ARM_ARCH_8_3__) << ".3" #elif defined(__ARM_ARCH_8_2__) << ".2" #elif defined(__ARM_ARCH_8_1__) << ".1" #endif #endif #if defined(__ARM_ARCH_PROFILE) && \ ( __ARM_ARCH_PROFILE >= 'A' && __ARM_ARCH_PROFILE <= 'Z' \ || __ARM_ARCH_PROFILE >= 65 && __ARM_ARCH_PROFILE <= 65 + 25) << "-" << (char)__ARM_ARCH_PROFILE #endif #ifdef __ARM_ARCH_ISA_THUMB << " thumb:" << __ARM_ARCH_ISA_THUMB #endif #endif #ifdef _MIPS_ARCH << " mips_arch:" << _MIPS_ARCH #endif #ifdef __mips_isa_rev << " mips_isa_rev:" << __mips_isa_rev #endif #ifdef __iset__ << " e2k_v:" << __iset__ #endif ; #ifdef ENV_HAVE_LOCALE *so << " locale=" << GetLocale(); #endif #ifndef _WIN32 { const bool is_IsNativeUTF8 = IsNativeUTF8(); if (!is_IsNativeUTF8) *so << " UTF8=" << (is_IsNativeUTF8 ? "+" : "-"); } if (!g_ForceToUTF8) *so << " use-UTF8=" << (g_ForceToUTF8 ? "+" : "-"); { const unsigned wchar_t_size = (unsigned)sizeof(wchar_t); if (wchar_t_size != 4) *so << " wchar_t=" << wchar_t_size * 8 << "-bit"; } { const unsigned off_t_size = (unsigned)sizeof(off_t); if (off_t_size != 8) *so << " Files=" << off_t_size * 8 << "-bit"; } #endif { const UInt32 numCpus = NWindows::NSystem::GetNumberOfProcessors(); *so << " Threads:" << numCpus; const UInt64 openMAX= NWindows::NSystem::Get_File_OPEN_MAX(); *so << " OPEN_MAX:" << openMAX; { FString temp; NDir::MyGetTempPath(temp); if (!temp.IsEqualTo(STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR)) *so << " temp_path:" << temp; } } #ifdef Z7_7ZIP_ASM *so << ", ASM"; #endif /* { AString s; GetCpuName(s); s.Trim(); *so << ", " << s; } #ifdef __ARM_FEATURE_CRC32 << " CRC32" #endif #if (defined MY_CPU_X86_OR_AMD64 || defined(MY_CPU_ARM_OR_ARM64)) if (CPU_IsSupported_AES()) *so << ",AES"; #endif #ifdef MY_CPU_ARM_OR_ARM64 if (CPU_IsSupported_CRC32()) *so << ",CRC32"; #if defined(_WIN32) if (CPU_IsSupported_CRYPTO()) *so << ",CRYPTO"; #else if (CPU_IsSupported_SHA1()) *so << ",SHA1"; if (CPU_IsSupported_SHA2()) *so << ",SHA2"; #endif #endif */ *so << endl; } #endif static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp) { if (!so) return; *so << kCopyrightString; // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl; ShowProgInfo(so); *so << endl; if (needHelp) *so << kHelpString; } static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size) { unsigned len = MyStringLen(s); for (unsigned i = len; i < size; i++) so << ' '; so << s; } static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size) { char s[16]; ConvertUInt32ToString(val, s); PrintStringRight(so, s, size); } #ifdef Z7_EXTERNAL_CODECS static void PrintNumber(CStdOutStream &so, UInt32 val, unsigned numDigits) { AString s; s.Add_UInt32(val); while (s.Len() < numDigits) s.InsertAtFront('0'); so << s; } #endif static void PrintLibIndex(CStdOutStream &so, int libIndex) { if (libIndex >= 0) PrintUInt32(so, (UInt32)libIndex, 2); else so << " "; so << ' '; } static void PrintString(CStdOutStream &so, const UString &s, unsigned size) { unsigned len = s.Len(); so << s; for (unsigned i = len; i < size; i++) so << ' '; } static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so) { FOR_VECTOR(i, pc.Paths) { so.NormalizePrint_UString_Path(fs2us(pc.Paths[i])); so << " : "; so << NError::MyFormatMessage(pc.Codes[i]) << endl; } so << "----------------" << endl; } static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, const CUpdateErrorInfo &errorInfo, CStdOutStream *so, CStdOutStream *se, bool showHeaders) { int exitCode = NExitCode::kSuccess; if (callback.ScanErrors.Paths.Size() != 0) { if (se) { *se << endl; *se << "Scan WARNINGS for files and folders:" << endl << endl; PrintWarningsPaths(callback.ScanErrors, *se); *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size(); *se << endl; } exitCode = NExitCode::kWarning; } if (result != S_OK || errorInfo.ThereIsError()) { if (se) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message.Ptr(); message.Add_LF(); } { FOR_VECTOR(i, errorInfo.FileNames) { message += fs2us(errorInfo.FileNames[i]); message.Add_LF(); } } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessage(errorInfo.SystemError); message.Add_LF(); } if (!message.IsEmpty()) *se << L"\nError:\n" << message; } // we will work with (result) later // throw CSystemException(result); return NExitCode::kFatalError; } unsigned numErrors = callback.FailedFiles.Paths.Size(); if (numErrors == 0) { if (showHeaders) if (callback.ScanErrors.Paths.Size() == 0) if (so) { if (se) se->Flush(); *so << kEverythingIsOk << endl; } } else { if (se) { *se << endl; *se << "WARNINGS for files:" << endl << endl; PrintWarningsPaths(callback.FailedFiles, *se); *se << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) *se << 's'; *se << endl; } exitCode = NExitCode::kWarning; } return exitCode; } static void ThrowException_if_Error(HRESULT res) { if (res != S_OK) throw CSystemException(res); } static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') { char temp[64]; char *p = temp + 32; ConvertUInt64ToString(val, p); unsigned len = MyStringLen(p); for (; len < numDigits; len++) *--p = c; *g_StdStream << p; } #ifdef _WIN32 static void PrintTime(const char *s, UInt64 val, UInt64 total) { *g_StdStream << endl << s << " Time ="; const UInt32 kFreq = 10000000; UInt64 sec = val / kFreq; PrintNum(sec, 6); *g_StdStream << '.'; UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); PrintNum(ms, 3, '0'); while (val > ((UInt64)1 << 56)) { val >>= 1; total >>= 1; } UInt64 percent = 0; if (total != 0) percent = val * 100 / total; *g_StdStream << " ="; PrintNum(percent, 5); *g_StdStream << '%'; } #ifndef UNDER_CE #define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num)) static void PrintMemUsage(const char *s, UInt64 val) { *g_StdStream << " " << s << " Memory ="; PrintNum(SHIFT_SIZE_VALUE(val, 20), 7); *g_StdStream << " MB"; /* *g_StdStream << " ="; PrintNum(SHIFT_SIZE_VALUE(val, 10), 9); *g_StdStream << " KB"; */ #ifdef Z7_LARGE_PAGES AString lp; Add_LargePages_String(lp); if (!lp.IsEmpty()) *g_StdStream << lp; #endif } EXTERN_C_BEGIN typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime); EXTERN_C_END #endif static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } static void PrintStat() { FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; if (! #ifdef UNDER_CE ::GetThreadTimes(::GetCurrentThread() #else // NT 3.5 ::GetProcessTimes(::GetCurrentProcess() #endif , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) return; FILETIME curTimeFT; NTime::GetCurUtc_FiTime(curTimeFT); #ifndef UNDER_CE Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION PROCESS_MEMORY_COUNTERS m; memset(&m, 0, sizeof(m)); BOOL memDefined = FALSE; BOOL cycleDefined = FALSE; ULONG64 cycleTime = 0; { /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll Win7: new function K32GetProcessMemoryInfo() in kernel32.dll It's faster to call kernel32.dll code than Psapi.dll code GetProcessMemoryInfo() requires Psapi.lib Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll The program with K32GetProcessMemoryInfo will not work on systems before Win7 // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); */ const HMODULE kern = ::GetModuleHandleW(L"kernel32.dll"); Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = Z7_GET_PROC_ADDRESS( Func_GetProcessMemoryInfo, kern, "K32GetProcessMemoryInfo"); if (!my_GetProcessMemoryInfo) { const HMODULE lib = LoadLibraryW(L"Psapi.dll"); if (lib) my_GetProcessMemoryInfo = Z7_GET_PROC_ADDRESS( Func_GetProcessMemoryInfo, lib, "GetProcessMemoryInfo"); } if (my_GetProcessMemoryInfo) memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); // FreeLibrary(lib); const Func_QueryProcessCycleTime my_QueryProcessCycleTime = Z7_GET_PROC_ADDRESS( Func_QueryProcessCycleTime, kern, "QueryProcessCycleTime"); if (my_QueryProcessCycleTime) cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime); } #endif UInt64 curTime = GetTime64(curTimeFT); UInt64 creationTime = GetTime64(creationTimeFT); UInt64 kernelTime = GetTime64(kernelTimeFT); UInt64 userTime = GetTime64(userTimeFT); UInt64 totalTime = curTime - creationTime; PrintTime("Kernel ", kernelTime, totalTime); const UInt64 processTime = kernelTime + userTime; #ifndef UNDER_CE if (cycleDefined) { *g_StdStream << " Cnt:"; PrintNum(cycleTime / 1000000, 15); *g_StdStream << " MCycles"; } #endif PrintTime("User ", userTime, totalTime); #ifndef UNDER_CE if (cycleDefined) { *g_StdStream << " Freq (cnt/ptime):"; UInt64 us = processTime / 10; if (us == 0) us = 1; PrintNum(cycleTime / us, 6); *g_StdStream << " MHz"; } #endif PrintTime("Process", processTime, totalTime); #ifndef UNDER_CE if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); #endif PrintTime("Global ", totalTime, totalTime); #ifndef UNDER_CE if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); #endif *g_StdStream << endl; } #else // ! _WIN32 static UInt64 Get_timeofday_us() { struct timeval now; if (gettimeofday(&now, NULL) == 0) return (UInt64)now.tv_sec * 1000000 + (UInt64)now.tv_usec; return 0; } static void PrintTime(const char *s, UInt64 val, UInt64 total_us, UInt64 kFreq) { *g_StdStream << endl << s << " Time ="; { UInt64 sec, ms; if (kFreq == 0) { sec = val / 1000000; ms = val % 1000000 / 1000; } else { sec = val / kFreq; ms = (UInt32)((val - (sec * kFreq)) * 1000 / kFreq); } PrintNum(sec, 6); *g_StdStream << '.'; PrintNum(ms, 3, '0'); } if (total_us == 0) return; UInt64 percent = 0; if (kFreq == 0) percent = val * 100 / total_us; else { const UInt64 kMaxVal = (UInt64)(Int64)-1; UInt32 m = 100000000; for (;;) { if (m == 0 || kFreq == 0) break; if (kMaxVal / m > val && kMaxVal / kFreq > total_us) break; if (val > m) val >>= 1; else m >>= 1; if (kFreq > total_us) kFreq >>= 1; else total_us >>= 1; } const UInt64 total = kFreq * total_us; if (total != 0) percent = val * m / total; } *g_StdStream << " ="; PrintNum(percent, 5); *g_StdStream << '%'; } static void PrintStat(const UInt64 startTime) { tms t; /* clock_t res = */ times(&t); const UInt64 totalTime = Get_timeofday_us() - startTime; const UInt64 kFreq = (UInt64)sysconf(_SC_CLK_TCK); PrintTime("Kernel ", (UInt64)t.tms_stime, totalTime, kFreq); PrintTime("User ", (UInt64)t.tms_utime, totalTime, kFreq); PrintTime("Process", (UInt64)t.tms_utime + (UInt64)t.tms_stime, totalTime, kFreq); PrintTime("Global ", totalTime, totalTime, 0); *g_StdStream << endl; } #endif // ! _WIN32 static void PrintHexId(CStdOutStream &so, UInt64 id) { char s[32]; ConvertUInt64ToHex(id, s); PrintStringRight(so, s, 8); } #ifndef _WIN32 void Set_ModuleDirPrefix_From_ProgArg0(const char *s); #endif int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ); int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ) { #if defined(MY_CPU_SIZEOF_POINTER) { unsigned k = sizeof(void *); if (k != MY_CPU_SIZEOF_POINTER) throw "incorrect MY_CPU_PTR_SIZE"; } #endif #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif #ifdef ENV_HAVE_LOCALE // printf("\nBefore SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); MY_SetLocale(); // printf("\nAfter SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); #endif #ifndef _WIN32 const UInt64 startTime = Get_timeofday_us(); #endif /* { g_StdOut << "DWORD:" << (unsigned)sizeof(DWORD); g_StdOut << " LONG:" << (unsigned)sizeof(LONG); g_StdOut << " long:" << (unsigned)sizeof(long); #ifdef _WIN64 // g_StdOut << " long long:" << (unsigned)sizeof(long long); #endif g_StdOut << " int:" << (unsigned)sizeof(int); g_StdOut << " void*:" << (unsigned)sizeof(void *); g_StdOut << endl; } */ UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else { if (numArgs > 0) Set_ModuleDirPrefix_From_ProgArg0(args[0]); for (int i = 0; i < numArgs; i++) { AString a (args[i]); #if 0 printf("\n%d %s :", i, a.Ptr()); for (unsigned k = 0; k < a.Len(); k++) printf(" %2x", (unsigned)(Byte)a[k]); #endif const UString s = MultiByteToUnicodeString(a); commandStrings.Add(s); } // printf("\n"); } #endif #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif if (commandStrings.Size() == 0) { ShowCopyrightAndHelp(g_StdStream, true); return 0; } CArcCmdLineOptions options; CArcCmdLineParser parser; parser.Parse1(commandStrings, options); g_StdOut.IsTerminalMode = options.IsStdOutTerminal; g_StdErr.IsTerminalMode = options.IsStdErrTerminal; if (options.Number_for_Out != k_OutStream_stdout) g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL); if (options.Number_for_Errors != k_OutStream_stderr) g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL); CStdOutStream *percentsStream = NULL; if (options.Number_for_Percents != k_OutStream_disabled) percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut; if (options.HelpMode) { ShowCopyrightAndHelp(g_StdStream, true); return 0; } if (options.EnableHeaders) { ShowCopyrightAndHelp(g_StdStream, false); if (!parser.Parse1Log.IsEmpty()) *g_StdStream << parser.Parse1Log; } parser.Parse2(options); { int cp = options.ConsoleCodePage; int stdout_cp = cp; int stderr_cp = cp; int stdin_cp = cp; /* // these cases are complicated. // maybe we must use CRT functions instead of console WIN32. // different Windows/CRT versions also can work different ways. // so the following code was not enabled: if (cp == -1) { // we set CodePage only if stream is attached to terminal // maybe we should set CodePage even if is not terminal? #ifdef _WIN32 { UINT ccp = GetConsoleOutputCP(); if (ccp != 0) { if (options.IsStdOutTerminal) stdout_cp = ccp; if (options.IsStdErrTerminal) stderr_cp = ccp; } } if (options.IsInTerminal) { UINT ccp = GetConsoleCP(); if (ccp != 0) stdin_cp = ccp; } #endif } */ if (stdout_cp != -1) g_StdOut.CodePage = stdout_cp; if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp; if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp; } g_StdOut.ListPathSeparatorSlash = options.ListPathSeparatorSlash; g_StdErr.ListPathSeparatorSlash = options.ListPathSeparatorSlash; unsigned percentsNameLevel = 1; if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out) percentsNameLevel = 2; unsigned consoleWidth = 80; if (percentsStream) { #ifdef _WIN32 #if !defined(UNDER_CE) CONSOLE_SCREEN_BUFFER_INFO consoleInfo; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) consoleWidth = (USHORT)consoleInfo.dwSize.X; #endif #else #if !defined(__sun) struct winsize w; if (ioctl(0, TIOCGWINSZ, &w) == 0) consoleWidth = w.ws_col; #endif #endif } CREATE_CODECS_OBJECT codecs->CaseSensitive_Change = options.CaseSensitive_Change; codecs->CaseSensitive = options.CaseSensitive; ThrowException_if_Error(codecs->Load()); Codecs_AddHashArcHandler(codecs); #ifdef Z7_EXTERNAL_CODECS { g_ExternalCodecs_Ptr = &_externalCodecs; UString s; codecs->GetCodecsErrorMessage(s); if (!s.IsEmpty()) { CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); so << endl << s << endl; } } #endif const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) { #ifdef Z7_EXTERNAL_CODECS if (!codecs->MainDll_ErrorPath.IsEmpty()) { UString s ("Can't load module: "); s += fs2us(codecs->MainDll_ErrorPath); throw s; } #endif throw kNoFormats; } CObjectVector types; if (!ParseOpenTypes(*codecs, options.ArcType, types)) { throw kUnsupportedArcTypeMessage; } CIntVector excludedFormats; FOR_VECTOR (k, options.ExcludedArcTypes) { CIntVector tempIndices; if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) || tempIndices.Size() != 1) throw kUnsupportedArcTypeMessage; excludedFormats.AddToUniqueSorted(tempIndices[0]); // excludedFormats.Sort(); } #ifdef Z7_EXTERNAL_CODECS if (isExtractGroupCommand || options.Command.IsFromUpdateGroup() || options.Command.CommandType == NCommandType::kHash || options.Command.CommandType == NCommandType::kBenchmark) ThrowException_if_Error(_externalCodecs.Load()); #endif int retCode = NExitCode::kSuccess; HRESULT hresultMain = S_OK; // bool showStat = options.ShowTime; /* if (!options.EnableHeaders || options.TechMode) showStat = false; */ if (options.Command.CommandType == NCommandType::kInfo) { CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); unsigned i; #ifdef Z7_EXTERNAL_CODECS so << endl << "Libs:" << endl; for (i = 0; i < codecs->Libs.Size(); i++) { PrintLibIndex(so, (int)i); const CCodecLib &lib = codecs->Libs[i]; // if (lib.Version != 0) so << ": " << (lib.Version >> 16) << "."; PrintNumber(so, lib.Version & 0xffff, 2); so << " : " << lib.Path << endl; } #endif so << endl << "Formats:" << endl; const char * const kArcFlags = "KSNFMGOPBELHXCc+a+m+r+"; const char * const kArcTimeFlags = "wudn"; const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); const unsigned kNumArcTimeFlags = (unsigned)strlen(kArcTimeFlags); for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef Z7_EXTERNAL_CODECS PrintLibIndex(so, arc.LibIndex); #else so << " "; #endif so << (char)(arc.UpdateEnabled ? 'C' : ' '); { unsigned b; for (b = 0; b < kNumArcFlags; b++) so << (char)((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : '.'); so << ' '; } if (arc.TimeFlags != 0) { unsigned b; for (b = 0; b < kNumArcTimeFlags; b++) so << (char)((arc.TimeFlags & ((UInt32)1 << b)) != 0 ? kArcTimeFlags[b] : '.'); so << arc.Get_DefaultTimePrec(); so << ' '; } so << ' '; PrintString(so, arc.Name, 8); so << ' '; UString s; FOR_VECTOR (t, arc.Exts) { if (t != 0) s.Add_Space(); const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += " ("; s += ext.AddExt; s.Add_Char(')'); } } PrintString(so, s, 13); so << ' '; if (arc.SignatureOffset != 0) so << "offset=" << arc.SignatureOffset << ' '; // so << "numSignatures = " << arc.Signatures.Size() << " "; FOR_VECTOR(si, arc.Signatures) { if (si != 0) so << " || "; const CByteBuffer &sig = arc.Signatures[si]; for (size_t j = 0; j < sig.Size(); j++) { if (j != 0) so << ' '; const unsigned b = sig.ConstData()[j]; if (b > 0x20 && b < 0x80) { so << (char)b; } else { so << GET_HEX_CHAR_UPPER(b >> 4); so << GET_HEX_CHAR_UPPER(b & 15); } } } so << endl; } so << endl << "Codecs:" << endl; // << "Lib ID Name" << endl; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &cod = *g_Codecs[i]; PrintLibIndex(so, -1); if (cod.NumStreams == 1) so << ' '; else so << cod.NumStreams; so << (char)(cod.CreateEncoder ? 'E' : ' '); so << (char)(cod.CreateDecoder ? 'D' : ' '); so << (char)(cod.IsFilter ? 'F' : ' '); so << ' '; PrintHexId(so, cod.Id); so << ' ' << cod.Name << endl; } #ifdef Z7_EXTERNAL_CODECS UInt32 numMethods; if (_externalCodecs.GetCodecs->GetNumMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { PrintLibIndex(so, codecs->GetCodec_LibIndex(j)); UInt32 numStreams = codecs->GetCodec_NumStreams(j); if (numStreams == 1) so << ' '; else so << numStreams; so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' '); so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' '); { bool isFilter_Assigned; const bool isFilter = codecs->GetCodec_IsFilter(j, isFilter_Assigned); so << (char)(isFilter ? 'F' : isFilter_Assigned ? ' ' : '*'); } so << ' '; UInt64 id; HRESULT res = codecs->GetCodec_Id(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; PrintHexId(so, id); so << ' ' << codecs->GetCodec_Name(j) << endl; } #endif so << endl << "Hashers:" << endl; // << " L Size ID Name" << endl; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; PrintLibIndex(so, -1); PrintUInt32(so, codec.DigestSize, 4); so << ' '; PrintHexId(so, codec.Id); so << ' ' << codec.Name << endl; } #ifdef Z7_EXTERNAL_CODECS numMethods = _externalCodecs.GetHashers->GetNumHashers(); for (UInt32 j = 0; j < numMethods; j++) { PrintLibIndex(so, codecs->GetHasherLibIndex(j)); PrintUInt32(so, codecs->GetHasherDigestSize(j), 4); so << ' '; PrintHexId(so, codecs->GetHasherId(j)); so << ' ' << codecs->GetHasherName(j) << endl; } #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L options.Properties, options.NumIterations, (FILE *)so); if (hresultMain == S_FALSE) { so << endl; if (g_ErrStream) *g_ErrStream << "\nDecoding ERROR\n"; retCode = NExitCode::kFatalError; hresultMain = S_OK; } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; if (options.StdInMode) { ArchivePathsSorted.Add(options.ArcName_for_StdInMode); ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode); } else { CExtractScanConsole scan; scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream, options.DisablePercents); scan.SetWindowWidth(consoleWidth); if (g_StdStream && options.EnableHeaders) *g_StdStream << "Scanning the drive for archives:" << endl; CDirItemsStat st; scan.StartScanning(); hresultMain = EnumerateDirItemsAndSort( options.arcCensor, NWildcard::k_RelatPath, UString(), // addPathPrefix ArchivePathsSorted, ArchivePathsFullSorted, st, &scan); scan.CloseScanning(); if (hresultMain == S_OK) { if (options.EnableHeaders) scan.PrintStat(st); } else { /* if (res != E_ABORT) { throw CSystemException(res); // errorInfo.Message = "Scanning error"; } return res; */ } } if (hresultMain == S_OK) { if (isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr extractCallback = ecs; #ifndef Z7_NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents); ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1); ecs->LogLevel = options.LogLevel; ecs->PercentsNameLevel = percentsNameLevel; if (percentsStream) ecs->SetWindowWidth(consoleWidth); /* COpenCallbackConsole openCallback; openCallback.Init(g_StdStream, g_ErrStream); #ifndef Z7_NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif */ CExtractOptions eo; (CExtractOptionsBase &)eo = options.ExtractOptions; eo.StdInMode = options.StdInMode; eo.StdOutMode = options.StdOutMode; eo.YesToAll = options.YesToAll; eo.TestMode = options.Command.IsTestCommand(); #ifndef Z7_SFX eo.Properties = options.Properties; #endif UString errorMessage; CDecompressStat stat; CHashBundle hb; IHashCalc *hashCalc = NULL; if (!options.HashMethods.IsEmpty()) { hashCalc = &hb; ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods)); // hb.Init(); } hresultMain = Extract( // EXTERNAL_CODECS_VARS_L codecs, types, excludedFormats, ArchivePathsSorted, ArchivePathsFullSorted, options.Censor.Pairs.Front().Head, eo, ecs, ecs, ecs, hashCalc, errorMessage, stat); ecs->ClosePercents(); if (!errorMessage.IsEmpty()) { if (g_ErrStream) *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl; if (hresultMain == S_OK) hresultMain = E_FAIL; } CStdOutStream *so = g_StdStream; bool isError = false; if (so) { *so << endl; if (ecs->NumTryArcs > 1) { *so << "Archives: " << ecs->NumTryArcs << endl; *so << "OK archives: " << ecs->NumOkArcs << endl; } } if (ecs->NumCantOpenArcs != 0) { isError = true; if (so) *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; } if (ecs->NumArcsWithError != 0) { isError = true; if (so) *so << "Archives with Errors: " << ecs->NumArcsWithError << endl; } if (so) { if (ecs->NumArcsWithWarnings != 0) *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; if (ecs->NumOpenArcWarnings != 0) { *so << endl; if (ecs->NumOpenArcWarnings != 0) *so << "Warnings: " << ecs->NumOpenArcWarnings << endl; } } if (ecs->NumOpenArcErrors != 0) { isError = true; if (so) { *so << endl; if (ecs->NumOpenArcErrors != 0) *so << "Open Errors: " << ecs->NumOpenArcErrors << endl; } } if (isError) retCode = NExitCode::kFatalError; if (so) { if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) { // if (ecs->NumArchives > 1) { *so << endl; if (ecs->NumFileErrors != 0) *so << "Sub items Errors: " << ecs->NumFileErrors << endl; } } else if (hresultMain == S_OK) { if (stat.NumFolders != 0) *so << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) *so << "Files: " << stat.NumFiles << endl; if (stat.NumAltStreams != 0) { *so << "Alternate Streams: " << stat.NumAltStreams << endl; *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; } *so << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; if (hashCalc) { *so << endl; PrintHashStat(*so, hb); } } } // if (so) } else // if_(!isExtractGroupCommand) { UInt64 numErrors = 0; UInt64 numWarnings = 0; // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed CListOptions lo; lo.ExcludeDirItems = options.Censor.ExcludeDirItems; lo.ExcludeFileItems = options.Censor.ExcludeFileItems; lo.DisablePercents = options.DisablePercents; hresultMain = ListArchives( lo, codecs, types, excludedFormats, options.StdInMode, ArchivePathsSorted, ArchivePathsFullSorted, options.ExtractOptions.NtOptions.AltStreams.Val, options.AltStreams.Val, // we don't want to show AltStreams by default options.Censor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef Z7_NO_CRYPTO options.PasswordEnabled, options.Password, #endif &options.Properties, numErrors, numWarnings); if (options.EnableHeaders) if (numWarnings > 0) g_StdOut << endl << "Warnings: " << numWarnings << endl; if (numErrors > 0) { if (options.EnableHeaders) g_StdOut << endl << "Errors: " << numErrors << endl; retCode = NExitCode::kFatalError; } } // if_(isExtractGroupCommand) } // if_(hresultMain == S_OK) } else if (options.Command.IsFromUpdateGroup()) { #ifdef Z7_EXTRACT_ONLY throw "update commands are not implemented"; #else CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents); #ifndef Z7_NO_CRYPTO bool passwordIsDefined = (options.PasswordEnabled && !options.Password.IsEmpty()); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.LogLevel = options.LogLevel; callback.PercentsNameLevel = percentsNameLevel; if (percentsStream) callback.SetWindowWidth(consoleWidth); #ifndef Z7_NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty()); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init( // NULL, g_StdStream, g_ErrStream, percentsStream, options.DisablePercents); CUpdateErrorInfo errorInfo; /* if (!uo.Init(codecs, types, options.ArchiveName)) throw kUnsupportedUpdateArcType; */ hresultMain = UpdateArchive(codecs, types, options.ArchiveName, options.Censor, uo, errorInfo, &openCallback, &callback, true); callback.ClosePercents2(); CStdOutStream *se = g_StdStream; if (!se) se = g_ErrStream; retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, true // options.EnableHeaders ); #endif } else if (options.Command.CommandType == NCommandType::kHash) { const CHashOptions &uo = options.HashOptions; CHashCallbackConsole callback; if (percentsStream) callback.SetWindowWidth(consoleWidth); callback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents); callback.PrintHeaders = options.EnableHeaders; callback.PrintFields = options.ListFields; AString errorInfoString; hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L options.Censor, uo, errorInfoString, &callback); CUpdateErrorInfo errorInfo; errorInfo.Message = errorInfoString; CStdOutStream *se = g_StdStream; if (!se) se = g_ErrStream; retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders); } else ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); if (options.ShowTime && g_StdStream) PrintStat( #ifndef _WIN32 startTime #endif ); ThrowException_if_Error(hresultMain); return retCode; } tmp41wklro_/CPP/7zip/UI/Console/MainAr.cpp0000444000175000001440000001255414624575020021262 0ustar nabijaczleweliusers// MainAr.cpp #include "StdAfx.h" #ifdef _WIN32 #include "../../../../C/DllSecur.h" #endif #include "../../../../C/CpuArch.h" #include "../../../Common/MyException.h" #include "../../../Common/StdOutStream.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/NtCheck.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #include "ConsoleClose.h" using namespace NWindows; extern CStdOutStream *g_StdStream; CStdOutStream *g_StdStream = NULL; extern CStdOutStream *g_ErrStream; CStdOutStream *g_ErrStream = NULL; extern int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ); static const char * const kException_CmdLine_Error_Message = "Command Line Error:"; static const char * const kExceptionErrorMessage = "ERROR:"; static const char * const kUserBreakMessage = "Break signaled"; static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!"; static const char * const kUnknownExceptionMessage = "Unknown Error"; static const char * const kInternalExceptionMessage = "\n\nInternal Error #"; static void FlushStreams() { if (g_StdStream) g_StdStream->Flush(); } static void PrintError(const char *message) { FlushStreams(); if (g_ErrStream) *g_ErrStream << "\n\n" << message << endl; } #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError; #endif static inline bool CheckIsa() { // __try { // some compilers (e2k) support SSE/AVX, but cpuid() can be unavailable or return lower isa support #ifdef MY_CPU_X86_OR_AMD64 #if 0 && (defined(__AVX512F__) && defined(__AVX512VL__)) if (!CPU_IsSupported_AVX512F_AVX512VL()) return false; #elif defined(__AVX2__) if (!CPU_IsSupported_AVX2()) return false; #elif defined(__AVX__) if (!CPU_IsSupported_AVX()) return false; #elif defined(__SSE2__) && !defined(MY_CPU_AMD64) || defined(_M_IX86_FP) && (_M_IX86_FP >= 2) if (!CPU_IsSupported_SSE2()) return false; #elif defined(__SSE__) && !defined(MY_CPU_AMD64) || defined(_M_IX86_FP) && (_M_IX86_FP >= 1) if (!CPU_IsSupported_SSE() || !CPU_IsSupported_CMOV()) return false; #endif #endif /* __asm { _emit 0fH _emit 038H _emit 0cbH _emit (0c0H + 0 * 8 + 0) } */ return true; } /* __except (EXCEPTION_EXECUTE_HANDLER) { return false; } */ } int Z7_CDECL main ( #ifndef _WIN32 int numArgs, char *args[] #endif ) { g_ErrStream = &g_StdErr; g_StdStream = &g_StdOut; // #if (defined(_MSC_VER) && defined(_M_IX86)) if (!CheckIsa()) { PrintError("ERROR: processor doesn't support required ISA extension"); return NExitCode::kFatalError; } // #endif NT_CHECK NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { #ifdef _WIN32 My_SetDefaultDllDirectories(); #endif res = Main2( #ifndef _WIN32 numArgs, args #endif ); } catch(const CNewException &) { PrintError(kMemoryExceptionMessage); return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { PrintError(kUserBreakMessage); return (NExitCode::kUserBreak); } catch(const CMessagePathException &e) { PrintError(kException_CmdLine_Error_Message); if (g_ErrStream) *g_ErrStream << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { PrintError(kMemoryExceptionMessage); return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { PrintError(kUserBreakMessage); return (NExitCode::kUserBreak); } if (g_ErrStream) { PrintError("System ERROR:"); *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl; } return (NExitCode::kFatalError); } catch(NExitCode::EEnum exitCode) { FlushStreams(); if (g_ErrStream) *g_ErrStream << kInternalExceptionMessage << exitCode << endl; return (exitCode); } catch(const UString &s) { if (g_ErrStream) { PrintError(kExceptionErrorMessage); *g_ErrStream << s << endl; } return (NExitCode::kFatalError); } catch(const AString &s) { if (g_ErrStream) { PrintError(kExceptionErrorMessage); *g_ErrStream << s << endl; } return (NExitCode::kFatalError); } catch(const char *s) { if (g_ErrStream) { PrintError(kExceptionErrorMessage); *g_ErrStream << s << endl; } return (NExitCode::kFatalError); } catch(const wchar_t *s) { if (g_ErrStream) { PrintError(kExceptionErrorMessage); *g_ErrStream << s << endl; } return (NExitCode::kFatalError); } catch(int t) { if (g_ErrStream) { FlushStreams(); *g_ErrStream << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } } catch(...) { PrintError(kUnknownExceptionMessage); return (NExitCode::kFatalError); } return res; } tmp41wklro_/CPP/7zip/UI/Console/makefile0000444000175000001440000000253214365523020021075 0ustar nabijaczleweliusersPROG = 7z.exe CFLAGS = $(CFLAGS) \ -DZ7_EXTERNAL_CODECS \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\DynLimBuf.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\ErrorMsg.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileLink.obj \ $O\FileName.obj \ $O\FileSystem.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\Registry.obj \ $O\System.obj \ $O\SystemInfo.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\MethodProps.obj \ $O\MultiOutStream.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\UniqBlocks.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ COMPRESS_OBJS = \ $O\CopyCoder.obj \ C_OBJS = $(C_OBJS) \ $O\Alloc.obj \ $O\CpuArch.obj \ $O\Sort.obj \ $O\Threads.obj \ !include "../../Crc.mak" !include "Console.mak" !include "../../7zip.mak" tmp41wklro_/CPP/7zip/UI/Console/makefile.gcc0000444000175000001440000000564214555655400021646 0ustar nabijaczleweliusersPROG = 7z IS_NOT_STANDALONE = 1 # IS_X64 = 1 # USE_ASM = 1 # ST_MODE = 1 LOCAL_FLAGS_ST = MT_OBJS = ifdef SystemDrive IS_MINGW = 1 else ifdef SYSTEMDRIVE # ifdef OS IS_MINGW = 1 endif endif ifdef ST_MODE LOCAL_FLAGS_ST = -DZ7_ST ifdef IS_MINGW MT_OBJS = \ $O/Threads.o \ endif else MT_OBJS = \ $O/Synchronization.o \ $O/Threads.o \ endif LOCAL_FLAGS_SYS= ifdef IS_MINGW LOCAL_FLAGS_SYS = \ -DZ7_DEVICE_FILE \ # -DZ7_LARGE_PAGES # -DZ7_LONG_PATH SYS_OBJS = \ $O/FileSystem.o \ $O/Registry.o \ $O/MemoryLock.o \ $O/DllSecur.o \ $O/resource.o \ else SYS_OBJS = \ $O/MyWindows.o \ endif LOCAL_FLAGS = \ $(LOCAL_FLAGS_SYS) \ $(LOCAL_FLAGS_ST) \ -DZ7_EXTERNAL_CODECS \ CONSOLE_OBJS = \ $O/BenchCon.o \ $O/ConsoleClose.o \ $O/ExtractCallbackConsole.o \ $O/HashCon.o \ $O/List.o \ $O/Main.o \ $O/MainAr.o \ $O/OpenCallbackConsole.o \ $O/PercentPrinter.o \ $O/UpdateCallbackConsole.o \ $O/UserInputUtils.o \ UI_COMMON_OBJS = \ $O/ArchiveCommandLine.o \ $O/ArchiveExtractCallback.o \ $O/ArchiveOpenCallback.o \ $O/Bench.o \ $O/DefaultName.o \ $O/EnumDirItems.o \ $O/Extract.o \ $O/ExtractingFilePath.o \ $O/HashCalc.o \ $O/LoadCodecs.o \ $O/OpenArchive.o \ $O/PropIDUtils.o \ $O/SetProperties.o \ $O/SortUtils.o \ $O/TempFiles.o \ $O/Update.o \ $O/UpdateAction.o \ $O/UpdateCallback.o \ $O/UpdatePair.o \ $O/UpdateProduce.o \ COMMON_OBJS = \ $O/CommandLineParser.o \ $O/CRC.o \ $O/CrcReg.o \ $O/DynLimBuf.o \ $O/IntToString.o \ $O/ListFileUtils.o \ $O/NewHandler.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/MyString.o \ $O/StringConvert.o \ $O/StringToInt.o \ $O/UTFConvert.o \ $O/MyVector.o \ $O/Wildcard.o \ WIN_OBJS = \ $O/DLL.o \ $O/ErrorMsg.o \ $O/FileDir.o \ $O/FileFind.o \ $O/FileIO.o \ $O/FileLink.o \ $O/FileName.o \ $O/PropVariant.o \ $O/PropVariantConv.o \ $O/System.o \ $O/SystemInfo.o \ $O/TimeUtils.o \ 7ZIP_COMMON_OBJS = \ $O/CreateCoder.o \ $O/CWrappers.o \ $O/FilePathAutoRename.o \ $O/FileStreams.o \ $O/InBuffer.o \ $O/InOutTempBuffer.o \ $O/FilterCoder.o \ $O/LimitedStreams.o \ $O/MethodId.o \ $O/MethodProps.o \ $O/MultiOutStream.o \ $O/OffsetStream.o \ $O/OutBuffer.o \ $O/ProgressUtils.o \ $O/PropId.o \ $O/StreamObjects.o \ $O/StreamUtils.o \ $O/UniqBlocks.o \ COMPRESS_OBJS = \ $O/CopyCoder.o \ AR_COMMON_OBJS = \ $O/ItemNameUtils.o \ C_OBJS = \ $O/Alloc.o \ $O/CpuArch.o \ $O/Sort.o \ $O/7zCrc.o \ $O/7zCrcOpt.o \ OBJS = \ $(C_OBJS) \ $(MT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(SYS_OBJS) \ $(COMPRESS_OBJS) \ $(AR_COMMON_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(CONSOLE_OBJS) \ include ../../7zip_gcc.mak tmp41wklro_/CPP/7zip/UI/Console/OpenCallbackConsole.cpp0000444000175000001440000000422314365514000023737 0ustar nabijaczleweliusers// OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" static HRESULT CheckBreak2() { return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } HRESULT COpenCallbackConsole::Open_CheckBreak() { return CheckBreak2(); } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes) { if (!MultiArcMode && NeedPercents()) { if (files) { _totalFilesDefined = true; // _totalFiles = *files; _percent.Total = *files; } else _totalFilesDefined = false; if (bytes) { // _totalBytesDefined = true; _totalBytes = *bytes; if (!files) _percent.Total = *bytes; } else { // _totalBytesDefined = false; if (!files) _percent.Total = _totalBytes; } } return CheckBreak2(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) { if (!MultiArcMode && NeedPercents()) { if (files) { _percent.Files = *files; if (_totalFilesDefined) _percent.Completed = *files; } if (bytes) { if (!_totalFilesDefined) _percent.Completed = *bytes; } _percent.Print(); } return CheckBreak2(); } HRESULT COpenCallbackConsole::Open_Finished() { ClosePercents(); return S_OK; } #ifndef Z7_NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { *password = NULL; RINOK(CheckBreak2()) if (!PasswordIsDefined) { ClosePercents(); RINOK(GetPassword_HRESULT(_so, Password)) PasswordIsDefined = true; } return StringToBstr(Password, password); } /* HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { passwordIsDefined = PasswordIsDefined; password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag () { PasswordWasAsked = false; } */ #endif tmp41wklro_/CPP/7zip/UI/Console/OpenCallbackConsole.h0000444000175000001440000000271314630250140023403 0ustar nabijaczleweliusers// OpenCallbackConsole.h #ifndef ZIP7_INC_OPEN_CALLBACK_CONSOLE_H #define ZIP7_INC_OPEN_CALLBACK_CONSOLE_H #include "../../../Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" #include "PercentPrinter.h" class COpenCallbackConsole: public IOpenCallbackUI { protected: CPercentPrinter _percent; CStdOutStream *_so; CStdOutStream *_se; // UInt64 _totalFiles; UInt64 _totalBytes; bool _totalFilesDefined; // bool _totalBytesDefined; bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; } public: bool MultiArcMode; void ClosePercents() { if (NeedPercents()) _percent.ClosePrint(true); } COpenCallbackConsole(): _totalBytes(0), _totalFilesDefined(false), // _totalBytesDefined(false), MultiArcMode(false) #ifndef Z7_NO_CRYPTO , PasswordIsDefined(false) // , PasswordWasAsked(false) #endif {} virtual ~COpenCallbackConsole() {} void Init( CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream, bool disablePercents) { _so = outStream; _se = errorStream; _percent._so = percentStream; _percent.DisablePrint = disablePercents; } Z7_IFACE_IMP(IOpenCallbackUI) #ifndef Z7_NO_CRYPTO bool PasswordIsDefined; // bool PasswordWasAsked; UString Password; #endif }; #endif tmp41wklro_/CPP/7zip/UI/Console/PercentPrinter.cpp0000444000175000001440000000736014634013460023052 0ustar nabijaczleweliusers// PercentPrinter.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "PercentPrinter.h" static const unsigned kPercentsSize = 4; CPercentPrinter::~CPercentPrinter() { ClosePrint(false); } void CPercentPrinterState::ClearCurState() { Completed = 0; Total = ((UInt64)(Int64)-1); Files = 0; Command.Empty(); FileName.Empty(); } void CPercentPrinter::ClosePrint(bool needFlush) { unsigned num = _printedString.Len(); if (num != 0) { unsigned i; /* '\r' in old MAC OS means "new line". So we can't use '\r' in some systems */ #ifdef _WIN32 char *start = _temp.GetBuf(num + 2); char *p = start; *p++ = '\r'; for (i = 0; i < num; i++) *p++ = ' '; *p++ = '\r'; #else char *start = _temp.GetBuf(num * 3); char *p = start; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; #endif *p = 0; _temp.ReleaseBuf_SetLen((unsigned)(p - start)); *_so << _temp; } if (needFlush) _so->Flush(); _printedString.Empty(); } void CPercentPrinter::GetPercents() { char s[32]; unsigned size; { char c = '%'; UInt64 val = 0; if (Total == (UInt64)(Int64)-1 || (Total == 0 && Completed != 0)) { val = Completed >> 20; c = 'M'; } else if (Total != 0) val = Completed * 100 / Total; ConvertUInt64ToString(val, s); size = (unsigned)strlen(s); s[size++] = c; s[size] = 0; } while (size < kPercentsSize) { _s.Add_Space(); size++; } _s += s; } void CPercentPrinter::Print() { if (DisablePrint) return; DWORD tick = 0; if (_tickStep != 0) tick = GetTickCount(); bool onlyPercentsChanged = false; if (!_printedString.IsEmpty()) { if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep) return; CPercentPrinterState &st = *this; if (_printedState.Command == st.Command && _printedState.FileName == st.FileName && _printedState.Files == st.Files) { if (_printedState.Total == st.Total && _printedState.Completed == st.Completed) return; onlyPercentsChanged = true; } } _s.Empty(); GetPercents(); if (onlyPercentsChanged && _s == _printedPercents) return; _printedPercents = _s; if (Files != 0) { char s[32]; ConvertUInt64ToString(Files, s); // unsigned size = (unsigned)strlen(s); // for (; size < 3; size++) _s.Add_Space(); _s.Add_Space(); _s += s; // _s += "f"; } if (!Command.IsEmpty()) { _s.Add_Space(); _s += Command; } if (!FileName.IsEmpty() && _s.Len() < MaxLen) { _s.Add_Space(); _tempU = FileName; _so->Normalize_UString_Path(_tempU); _so->Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() > MaxLen) { unsigned len = FileName.Len(); for (; len != 0;) { unsigned delta = len / 8; if (delta == 0) delta = 1; len -= delta; _tempU = FileName; _tempU.Delete(len / 2, _tempU.Len() - len); _tempU.Insert(len / 2, L" . "); _so->Normalize_UString_Path(_tempU); _so->Convert_UString_to_AString(_tempU, _temp); if (_s.Len() + _temp.Len() <= MaxLen) break; } if (len == 0) _temp.Empty(); } _s += _temp; } if (_printedString != _s) { ClosePrint(false); *_so << _s; if (NeedFlush) _so->Flush(); _printedString = _s; } _printedState = *this; if (_tickStep != 0) _prevTick = tick; } tmp41wklro_/CPP/7zip/UI/Console/PercentPrinter.h0000444000175000001440000000204114630241120022476 0ustar nabijaczleweliusers// PercentPrinter.h #ifndef ZIP7_INC_PERCENT_PRINTER_H #define ZIP7_INC_PERCENT_PRINTER_H #include "../../../Common/StdOutStream.h" struct CPercentPrinterState { UInt64 Completed; UInt64 Total; UInt64 Files; AString Command; UString FileName; void ClearCurState(); CPercentPrinterState(): Completed(0), Total((UInt64)(Int64)-1), Files(0) {} }; class CPercentPrinter: public CPercentPrinterState { UInt32 _tickStep; DWORD _prevTick; AString _s; AString _printedString; AString _temp; UString _tempU; CPercentPrinterState _printedState; AString _printedPercents; void GetPercents(); public: CStdOutStream *_so; bool DisablePrint; bool NeedFlush; unsigned MaxLen; CPercentPrinter(UInt32 tickStep = 200): _tickStep(tickStep), _prevTick(0), DisablePrint(false), NeedFlush(true), MaxLen(80 - 1) {} ~CPercentPrinter(); void ClosePrint(bool needFlush); void Print(); }; #endif tmp41wklro_/CPP/7zip/UI/Console/resource.rc0000444000175000001440000000023113261146341021545 0ustar nabijaczleweliusers#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Console" , "7z") #ifndef UNDER_CE 1 24 MOVEABLE PURE "Console.manifest" #endif tmp41wklro_/CPP/7zip/UI/Console/StdAfx.cpp0000444000175000001440000000004610144137330021264 0ustar nabijaczleweliusers// StdAfx.cpp #include "StdAfx.h" tmp41wklro_/CPP/7zip/UI/Console/StdAfx.h0000444000175000001440000000036114360505460020740 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif tmp41wklro_/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp0000444000175000001440000004565014561364620024302 0ustar nabijaczleweliusers// UpdateCallbackConsole.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileName.h" #ifndef Z7_ST #include "../../../Windows/Synchronization.h" #endif // #include "../Common/PropIDUtils.h" #include "ConsoleClose.h" #include "UserInputUtils.h" #include "UpdateCallbackConsole.h" using namespace NWindows; #ifndef Z7_ST static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t * const kEmptyFileAlias = L"[Content]"; static const char * const kOpenArchiveMessage = "Open archive: "; static const char * const kCreatingArchiveMessage = "Creating archive: "; static const char * const kUpdatingArchiveMessage = "Updating archive: "; static const char * const kScanningMessage = "Scanning the drive:"; static const char * const kError = "ERROR: "; static const char * const kWarning = "WARNING: "; static HRESULT CheckBreak2() { return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); HRESULT CUpdateCallbackConsole::OpenResult( const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { ClosePercents2(); FOR_VECTOR (level, arcLink.Arcs) { const CArc &arc = arcLink.Arcs[level]; const CArcErrorInfo &er = arc.ErrorInfo; UInt32 errorFlags = er.GetErrorFlags(); if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) { if (_se) { *_se << endl; if (level != 0) *_se << arc.Path << endl; } if (errorFlags != 0) { if (_se) PrintErrorFlags(*_se, "ERRORS:", errorFlags); } if (!er.ErrorMessage.IsEmpty()) { if (_se) *_se << "ERRORS:" << endl << er.ErrorMessage << endl; } if (_se) { *_se << endl; _se->Flush(); } } UInt32 warningFlags = er.GetWarningFlags(); if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) { if (_so) { *_so << endl; if (level != 0) *_so << arc.Path << endl; } if (warningFlags != 0) { if (_so) PrintErrorFlags(*_so, "WARNINGS:", warningFlags); } if (!er.WarningMessage.IsEmpty()) { if (_so) *_so << "WARNINGS:" << endl << er.WarningMessage << endl; } if (_so) { *_so << endl; if (NeedFlush) _so->Flush(); } } if (er.ErrorFormatIndex >= 0) { if (_so) { Print_ErrorFormatIndex_Warning(_so, codecs, arc); if (NeedFlush) _so->Flush(); } } } if (result == S_OK) { if (_so) { RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)) *_so << endl; } } else { if (_so) _so->Flush(); if (_se) { *_se << kError; _se->NormalizePrint_wstr_Path(name); *_se << endl; HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); RINOK(res) _se->Flush(); } } return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { if (_so) *_so << kScanningMessage << endl; _percent.Command = "Scan "; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) { if (NeedPercents()) { _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; _percent.Completed = st.GetTotalBytes(); _percent.FileName = fs2us(path); _percent.Print(); } return CheckBreak(); } void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning) { ClosePercents2(); if (_se) { if (_so) _so->Flush(); *_se << endl << (isWarning ? kWarning : kError) << NError::MyFormatMessage(systemError) << endl; _se->NormalizePrint_UString_Path(fs2us(path)); *_se << endl << endl; _se->Flush(); } } /* void CCallbackConsoleBase::CommonError(const char *message) { ClosePercents2(); if (_se) { if (_so) _so->Flush(); *_se << endl << kError << message << endl; _se->Flush(); } } */ HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) { MT_LOCK ScanErrors.AddError(path, systemError); CommonError(path, systemError, true); return S_OK; } HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError) { MT_LOCK FailedFiles.AddError(path, systemError); NumNonOpenFiles++; /* if (systemError == ERROR_SHARING_VIOLATION) { */ CommonError(path, systemError, true); return S_FALSE; /* } return systemError; */ } HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError) { MT_LOCK CommonError(path, systemError, false); return HRESULT_FROM_WIN32(systemError); } HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError) { return ScanError_Base(path, systemError); } static void PrintPropPair(AString &s, const char *name, UInt64 val) { char temp[32]; ConvertUInt64ToString(val, temp); s += name; s += ": "; s += temp; } void PrintSize_bytes_Smart(AString &s, UInt64 val); void Print_DirItemsStat(AString &s, const CDirItemsStat &st); void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) { if (NeedPercents()) { _percent.ClosePrint(true); _percent.ClearCurState(); } if (_so) { AString s; Print_DirItemsStat(s, st); *_so << s << endl << endl; } return S_OK; } static const char * const k_StdOut_ArcName = "StdOut"; HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) { if (_so) { *_so << kOpenArchiveMessage; if (name) *_so << name; else *_so << k_StdOut_ArcName; *_so << endl; } return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if (NeedPercents()) _percent.ClosePrint(true); _percent.ClearCurState(); NumNonOpenFiles = 0; if (_so) { *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); if (name) _so->NormalizePrint_wstr_Path(name); else *_so << k_StdOut_ArcName; *_so << endl << endl; } return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) { ClosePercents2(); if (_so) { AString s; // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); PrintPropPair(s, "Files read from disk", _percent.Files - NumNonOpenFiles); s.Add_LF(); s += "Archive size: "; PrintSize_bytes_Smart(s, st.OutArcFileSize); s.Add_LF(); if (st.IsMultiVolMode) { s += "Volumes: "; s.Add_UInt32(st.NumVolumes); s.Add_LF(); } *_so << endl; *_so << s; // *_so << endl; } return S_OK; } HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) { if (_so) { *_so << "Write SFX: "; *_so << name; AString s (" : "); PrintSize_bytes_Smart(s, size); *_so << s << endl; } return S_OK; } HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) { if (LogLevel > 0 && _so) { ClosePercents_for_so(); if (!DeleteMessageWasShown) { if (_so) *_so << endl << ": Removing files after including to archive" << endl; } { { _tempA = "Removing"; _tempA.Add_Space(); *_so << _tempA; _tempU = fs2us(path); _so->Normalize_UString_Path(_tempU); _so->PrintUString(_tempU, _tempA); *_so << endl; if (NeedFlush) _so->Flush(); } } } if (!DeleteMessageWasShown) { if (NeedPercents()) { _percent.ClearCurState(); } DeleteMessageWasShown = true; } else { _percent.Files++; } if (NeedPercents()) { // if (!FullLog) { _percent.Command = "Removing"; _percent.FileName = fs2us(path); } _percent.Print(); } return S_OK; } HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving() { ClosePercents2(); if (_so && DeleteMessageWasShown) *_so << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { return CheckBreak2(); } /* HRESULT CUpdateCallbackConsole::Finalize() { // MT_LOCK return S_OK; } */ void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name) { AString s; Print_DirItemsStat2(s, stat); *_so << name << ": " << s << endl; } HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat) { if (_so) { ClosePercents_for_so(); if (!stat.DeleteData.IsEmpty()) { *_so << endl; PrintToDoStat(_so, stat.DeleteData, "Delete data from archive"); } if (!stat.OldData.IsEmpty()) PrintToDoStat(_so, stat.OldData, "Keep old data in archive"); // if (!stat.NewData.IsEmpty()) { PrintToDoStat(_so, stat.NewData, "Add new data to archive"); } *_so << endl; } return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (NeedPercents()) { _percent.Total = size; _percent.Print(); } return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue) { if (NeedPercents()) { _percent.Completed = *completeValue; _percent.Print(); } } return CheckBreak2(); } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { return CheckBreak2(); } HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog) { MT_LOCK bool show2 = (showInLog && _so); if (show2) { ClosePercents_for_so(); _tempA = command; if (name) _tempA.Add_Space(); *_so << _tempA; _tempU.Empty(); if (name) { _tempU = name; if (isDir) NWindows::NFile::NName::NormalizeDirPathPrefix(_tempU); _so->Normalize_UString_Path(_tempU); } _so->PrintUString(_tempU, _tempA); *_so << endl; if (NeedFlush) _so->Flush(); } if (NeedPercents()) { if (PercentsNameLevel >= 1) { _percent.FileName.Empty(); _percent.Command.Empty(); if (PercentsNameLevel > 1 || !show2) { _percent.Command = command; if (name) _percent.FileName = name; } } _percent.Print(); } return CheckBreak2(); } /* void CCallbackConsoleBase::PrintInfoLine(const UString &s) { if (LogLevel < 1000) return; MT_LOCK const bool show2 = (_so != NULL); if (show2) { ClosePercents_for_so(); _so->PrintUString(s, _tempA); *_so << endl; if (NeedFlush) _so->Flush(); } } */ HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) { if (StdOutMode) return S_OK; if (!name || name[0] == 0) name = kEmptyFileAlias; unsigned requiredLevel = 1; const char *s; if (mode == NUpdateNotifyOp::kAdd || mode == NUpdateNotifyOp::kUpdate) { if (isAnti) s = "Anti"; else if (mode == NUpdateNotifyOp::kAdd) s = "+"; else s = "U"; } else { requiredLevel = 3; if (mode == NUpdateNotifyOp::kAnalyze) s = "A"; else s = "Reading"; } return PrintProgress(name, isDir, s, LogLevel >= requiredLevel); } HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError) { return OpenFileError_Base(path, systemError); } HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError) { return ReadingFileError_Base(path, systemError); } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 /* opRes */) { MT_LOCK _percent.Files++; /* if (opRes != NArchive::NUpdate::NOperationResult::kOK) { if (opRes == NArchive::NUpdate::NOperationResult::kError_FileChanged) { CommonError("Input file changed"); } } */ return S_OK; } void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) { // if (StdOutMode) return S_OK; if (opRes != NArchive::NExtract::NOperationResult::kOK) { ClosePercents2(); if (_se) { if (_so) _so->Flush(); AString s; SetExtractErrorMessage(opRes, isEncrypted, s); *_se << s << " : " << endl; _se->NormalizePrint_wstr_Path(name); *_se << endl << endl; _se->Flush(); } return S_OK; } return S_OK; } HRESULT CUpdateCallbackConsole::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir) { // if (StdOutMode) return S_OK; char temp[16]; const char *s; unsigned requiredLevel = 1; switch (op) { case NUpdateNotifyOp::kAdd: s = "+"; break; case NUpdateNotifyOp::kUpdate: s = "U"; break; case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break; case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break; case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break; case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; case NUpdateNotifyOp::kInFileChanged: s = "Size of input file was changed:"; requiredLevel = 10; break; // case NUpdateNotifyOp::kOpFinished: s = "Finished"; requiredLevel = 100; break; default: { temp[0] = 'o'; temp[1] = 'p'; ConvertUInt64ToString(op, temp + 2); s = temp; } } return PrintProgress(name, isDir, s, LogLevel >= requiredLevel); } /* HRESULT CUpdateCallbackConsole::SetPassword(const UString & #ifndef Z7_NO_CRYPTO password #endif ) { #ifndef Z7_NO_CRYPTO PasswordIsDefined = true; Password = password; #endif return S_OK; } */ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN *password = NULL; #ifdef Z7_NO_CRYPTO *passwordIsDefined = false; return S_OK; #else if (!PasswordIsDefined) { if (AskPassword) { RINOK(GetPassword_HRESULT(_so, Password)) PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif COM_TRY_END } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN *password = NULL; #ifdef Z7_NO_CRYPTO return E_NOTIMPL; #else if (!PasswordIsDefined) { { RINOK(GetPassword_HRESULT(_so, Password)) PasswordIsDefined = true; } } return StringToBstr(Password, password); #endif COM_TRY_END } HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool isDir) { if (StdOutMode) return S_OK; if (LogLevel > 7) { if (!name || name[0] == 0) name = kEmptyFileAlias; return PrintProgress(name, isDir, "D", true); } return S_OK; } /* void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU); static void GetPropName(PROPID propID, UString &nameU) { AString nameA; GetPropName(propID, NULL, nameA, nameU); // if (!nameA.IsEmpty()) nameU = nameA; } static void AddPropNamePrefix(UString &s, PROPID propID) { UString name; GetPropName(propID, name); s += name; s += " = "; } void CCallbackConsoleBase::PrintPropInfo(UString &s, PROPID propID, const PROPVARIANT *value) { AddPropNamePrefix(s, propID); { UString dest; const int level = 9; // we show up to ns precision level ConvertPropertyToString2(dest, *value, propID, level); s += dest; } PrintInfoLine(s); } static void Add_IndexType_Index(UString &s, UInt32 indexType, UInt32 index) { if (indexType == NArchive::NEventIndexType::kArcProp) { } else { if (indexType == NArchive::NEventIndexType::kBlockIndex) { s += "#"; } else if (indexType == NArchive::NEventIndexType::kOutArcIndex) { } else { s += "indexType_"; s.Add_UInt32(indexType); s.Add_Space(); } s.Add_UInt32(index); } s += ": "; } HRESULT CUpdateCallbackConsole::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) { UString s; Add_IndexType_Index(s, indexType, index); PrintPropInfo(s, propID, value); return S_OK; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('a' + (value - 10))); } static void AddHexToString(UString &dest, const Byte *data, UInt32 size) { for (UInt32 i = 0; i < size; i++) { Byte b = data[i]; dest += GetHex((Byte)((b >> 4) & 0xF)); dest += GetHex((Byte)(b & 0xF)); } } void HashHexToString(char *dest, const Byte *data, UInt32 size); HRESULT CUpdateCallbackConsole::ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) { UString s; propType = propType; Add_IndexType_Index(s, indexType, index); AddPropNamePrefix(s, propID); if (propID == kpidChecksum) { char temp[k_HashCalc_DigestSize_Max + 8]; HashHexToString(temp, (const Byte *)data, dataSize); s += temp; } else AddHexToString(s, (const Byte *)data, dataSize); PrintInfoLine(s); return S_OK; } HRESULT CUpdateCallbackConsole::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) { UString s; Add_IndexType_Index(s, indexType, index); s += "finished"; if (opRes != NArchive::NUpdate::NOperationResult::kOK) { s += ": "; s.Add_UInt32(opRes); } PrintInfoLine(s); return S_OK; } */ tmp41wklro_/CPP/7zip/UI/Console/UpdateCallbackConsole.h0000444000175000001440000000600114630250140023716 0ustar nabijaczleweliusers// UpdateCallbackConsole.h #ifndef ZIP7_INC_UPDATE_CALLBACK_CONSOLE_H #define ZIP7_INC_UPDATE_CALLBACK_CONSOLE_H #include "../../../Common/StdOutStream.h" #include "../Common/Update.h" #include "PercentPrinter.h" struct CErrorPathCodes { FStringVector Paths; CRecordVector Codes; void AddError(const FString &path, DWORD systemError) { Paths.Add(path); Codes.Add(systemError); } void Clear() { Paths.Clear(); Codes.Clear(); } }; class CCallbackConsoleBase { protected: CPercentPrinter _percent; CStdOutStream *_so; CStdOutStream *_se; void CommonError(const FString &path, DWORD systemError, bool isWarning); // void CommonError(const char *message); HRESULT ScanError_Base(const FString &path, DWORD systemError); HRESULT OpenFileError_Base(const FString &name, DWORD systemError); HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); public: bool NeedPercents() const { return _percent._so != NULL; } bool StdOutMode; bool NeedFlush; unsigned PercentsNameLevel; unsigned LogLevel; AString _tempA; UString _tempU; CCallbackConsoleBase(): StdOutMode(false), NeedFlush(false), PercentsNameLevel(1), LogLevel(0), NumNonOpenFiles(0) {} void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } void Init( CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream, bool disablePercents) { FailedFiles.Clear(); _so = outStream; _se = errorStream; _percent._so = percentStream; _percent.DisablePrint = disablePercents; } void ClosePercents2() { if (NeedPercents()) _percent.ClosePrint(true); } void ClosePercents_for_so() { if (NeedPercents() && _so == _percent._so) _percent.ClosePrint(false); } CErrorPathCodes FailedFiles; CErrorPathCodes ScanErrors; UInt64 NumNonOpenFiles; HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog); // void PrintInfoLine(const UString &s); // void PrintPropInfo(UString &s, PROPID propID, const PROPVARIANT *value); }; class CUpdateCallbackConsole Z7_final: public IUpdateCallbackUI2, public CCallbackConsoleBase { // void PrintPropPair(const char *name, const wchar_t *val); Z7_IFACE_IMP(IUpdateCallbackUI) Z7_IFACE_IMP(IDirItemsCallback) Z7_IFACE_IMP(IUpdateCallbackUI2) public: bool DeleteMessageWasShown; #ifndef Z7_NO_CRYPTO bool PasswordIsDefined; bool AskPassword; UString Password; #endif CUpdateCallbackConsole(): DeleteMessageWasShown(false) #ifndef Z7_NO_CRYPTO , PasswordIsDefined(false) , AskPassword(false) #endif {} /* void Init(CStdOutStream *outStream) { CCallbackConsoleBase::Init(outStream); } */ // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); } }; #endif tmp41wklro_/CPP/7zip/UI/Console/UserInputUtils.cpp0000444000175000001440000000604214567051420023064 0ustar nabijaczleweliusers// UserInputUtils.cpp #include "StdAfx.h" #include "../../../Common/StdInStream.h" #include "../../../Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'y'; static const char kNo = 'n'; static const char kYesAll = 'a'; static const char kNoAll = 's'; static const char kAutoRenameAll = 'u'; static const char kQuit = 'q'; static const char * const kFirstQuestionMessage = "? "; static const char * const kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { if (outStream) *outStream << kFirstQuestionMessage; for (;;) { if (outStream) { *outStream << kHelpQuestionMessage; outStream->Flush(); } AString scannedString; if (!g_StdIn.ScanAStringUntilNewLine(scannedString)) return NUserAnswerMode::kError; if (g_StdIn.Error()) return NUserAnswerMode::kError; scannedString.Trim(); if (scannedString.IsEmpty() && g_StdIn.Eof()) return NUserAnswerMode::kEof; if (scannedString.Len() == 1) switch (::MyCharLower_Ascii(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; default: break; } } } #ifdef _WIN32 #ifndef UNDER_CE #define MY_DISABLE_ECHO #endif #endif static bool GetPassword(CStdOutStream *outStream, UString &psw) { if (outStream) { *outStream << "\nEnter password" #ifdef MY_DISABLE_ECHO " (will not be echoed)" #endif ":"; outStream->Flush(); } #ifdef MY_DISABLE_ECHO const HANDLE console = GetStdHandle(STD_INPUT_HANDLE); /* GetStdHandle() returns INVALID_HANDLE_VALUE: If the function fails. NULL : If an application does not have associated standard handles, such as a service running on an interactive desktop, and has not redirected them. */ bool wasChanged = false; DWORD mode = 0; if (console != INVALID_HANDLE_VALUE && console != NULL) if (GetConsoleMode(console, &mode)) wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0); const bool res = g_StdIn.ScanUStringUntilNewLine(psw); if (wasChanged) SetConsoleMode(console, mode); #else const bool res = g_StdIn.ScanUStringUntilNewLine(psw); #endif if (outStream) { *outStream << endl; outStream->Flush(); } return res; } HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) { if (!GetPassword(outStream, psw)) return E_INVALIDARG; if (g_StdIn.Error()) return E_FAIL; if (g_StdIn.Eof() && psw.IsEmpty()) return E_ABORT; return S_OK; } tmp41wklro_/CPP/7zip/UI/Console/UserInputUtils.h0000444000175000001440000000076514357314620022540 0ustar nabijaczleweliusers// UserInputUtils.h #ifndef ZIP7_INC_USER_INPUT_UTILS_H #define ZIP7_INC_USER_INPUT_UTILS_H #include "../../../Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit, kEof, kError }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); // bool GetPassword(CStdOutStream *outStream, UString &psw); HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw); #endif tmp41wklro_/CPP/7zip/UI/Explorer/0000700000175000001440000000000014706260545017572 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/Explorer/MyMessages.cpp0000444000175000001440000000164314573273220022363 0ustar nabijaczleweliusers// MyMessages.cpp #include "StdAfx.h" #include "MyMessages.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/ResourceString.h" #include "../FileManager/LangUtils.h" using namespace NWindows; extern bool g_DisableUserQuestions; void ShowErrorMessage(HWND window, LPCWSTR message) { if (!g_DisableUserQuestions) ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP); } void ShowErrorMessageHwndRes(HWND window, UInt32 resID) { UString s = LangString(resID); if (s.IsEmpty()) s.Add_UInt32(resID); ShowErrorMessage(window, s); } void ShowErrorMessageRes(UInt32 resID) { ShowErrorMessageHwndRes(NULL, resID); } static void ShowErrorMessageDWORD(HWND window, DWORD errorCode) { ShowErrorMessage(window, NError::MyFormatMessage(errorCode)); } void ShowLastErrorMessage(HWND window) { ShowErrorMessageDWORD(window, ::GetLastError()); } tmp41wklro_/CPP/7zip/UI/Explorer/MyMessages.h0000444000175000001440000000065314357314620022030 0ustar nabijaczleweliusers// MyMessages.h #ifndef ZIP7_INC_MY_MESSAGES_H #define ZIP7_INC_MY_MESSAGES_H #include "../../../Common/MyString.h" void ShowErrorMessage(HWND window, LPCWSTR message); inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(NULL, message); } void ShowErrorMessageHwndRes(HWND window, UInt32 langID); void ShowErrorMessageRes(UInt32 langID); void ShowLastErrorMessage(HWND window = NULL); #endif tmp41wklro_/CPP/7zip/UI/FileManager/0000700000175000001440000000000014706260545020144 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/FileManager/BrowseDialog.cpp0000444000175000001440000006633014643214060023240 0ustar nabijaczleweliusers// BrowseDialog.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/IntToString.h" #ifndef UNDER_CE #include "../../../Windows/CommonDialog.h" #include "../../../Windows/Shell.h" #endif #include "../../../Windows/FileName.h" #include "../../../Windows/FileFind.h" #ifdef UNDER_CE #include #endif #include "BrowseDialog.h" #define USE_MY_BROWSE_DIALOG #ifdef USE_MY_BROWSE_DIALOG #include "../../../Common/Defs.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/PropVariantConv.h" #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Dialog.h" #include "../../../Windows/Control/Edit.h" #include "../../../Windows/Control/ListView.h" #include "BrowseDialogRes.h" #include "PropertyNameRes.h" #include "SysIconUtils.h" #ifndef Z7_SFX #include "RegistryUtils.h" #endif #endif // USE_MY_BROWSE_DIALOG #include "ComboDialog.h" #include "LangUtils.h" #include "resource.h" using namespace NWindows; using namespace NFile; using namespace NName; using namespace NFind; static void MessageBox_Error_Global(HWND wnd, const wchar_t *message) { ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR); } #ifdef USE_MY_BROWSE_DIALOG #if 0 extern HINSTANCE g_hInstance; #endif extern bool g_LVN_ITEMACTIVATE_Support; static const int kParentIndex = -1; static const UINT k_Message_RefreshPathEdit = WM_APP + 1; extern UString HResultToMessage(HRESULT errorCode); static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name) { UString s = HResultToMessage(errorCode); if (name) { s.Add_LF(); s += name; } MessageBox_Error_Global(wnd, s); } class CBrowseDialog: public NControl::CModalDialog { NControl::CListView _list; NControl::CEdit _pathEdit; NControl::CComboBox _filterCombo; CObjectVector _files; CExtToIconMap _extToIconMap; int _sortIndex; bool _ascending; #ifndef Z7_SFX bool _showDots; #endif UString _topDirPrefix; // we don't open parent of that folder UString DirPrefix; virtual bool OnInit() Z7_override; virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override; virtual bool OnNotify(UINT controlID, LPNMHDR header) Z7_override; virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam) Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; virtual void OnOK() Z7_override; bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo); void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); } bool GetParentPath(const UString &path, UString &parentPrefix, UString &name); // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter HRESULT Reload(const UString &pathPrefix, const UString &selectedName); HRESULT Reload(); void OpenParentFolder(); void SetPathEditText(); void OnCreateDir(); void OnItemEnter(); void FinishOnOK(); int GetRealItemIndex(int indexInListView) const { LPARAM param; if (!_list.GetItemParam((unsigned)indexInListView, param)) return (int)-1; return (int)param; } public: bool SaveMode; bool FolderMode; int FilterIndex; // [in / out] CObjectVector Filters; UString FilePath; // [in / out] UString Title; CBrowseDialog(): #ifndef Z7_SFX _showDots(false), #endif SaveMode(false) , FolderMode(false) , FilterIndex(-1) {} INT_PTR Create(HWND parent = NULL) { return CModalDialog::Create(IDD_BROWSE, parent); } int CompareItems(LPARAM lParam1, LPARAM lParam2) const; }; bool CBrowseDialog::OnInit() { #ifdef Z7_LANG LangSetDlgItems(*this, NULL, 0); #endif if (!Title.IsEmpty()) SetText(Title); _list.Attach(GetItem(IDL_BROWSE)); _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER)); _pathEdit.Attach(GetItem(IDE_BROWSE_PATH)); #ifndef UNDER_CE _list.SetUnicodeFormat(); #endif #ifndef Z7_SFX CFmSettings st; st.Load(); if (st.SingleClick) _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); _showDots = st.ShowDots; #endif { /* Filters.Clear(); // for debug if (Filters.IsEmpty() && !FolderMode) { CBrowseFilterInfo &f = Filters.AddNew(); const UString mask("*.*"); f.Masks.Add(mask); // f.Description = "("; f.Description += mask; // f.Description += ")"; } */ FOR_VECTOR (i, Filters) { _filterCombo.AddString(Filters[i].Description); } if (Filters.Size() <= 1) { if (FolderMode) HideItem(IDC_BROWSE_FILTER); else EnableItem(IDC_BROWSE_FILTER, false); } if (/* FilterIndex >= 0 && */ (unsigned)FilterIndex < Filters.Size()) _filterCombo.SetCurSel(FilterIndex); } _list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL); _list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL); _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100); _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100); { LV_COLUMNW column; column.iSubItem = 2; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_RIGHT; column.cx = 100; const UString s = LangString(IDS_PROP_SIZE); column.pszText = s.Ptr_non_const(); _list.InsertColumn(2, &column); } _list.InsertItem(0, L"12345678901234567" #ifndef UNDER_CE L"1234567890" #endif ); _list.SetSubItem(0, 1, L"2009-09-09" #ifndef UNDER_CE L" 09:09" #endif ); _list.SetSubItem(0, 2, L"9999 MB"); for (int i = 0; i < 3; i++) _list.SetColumnWidthAuto(i); _list.DeleteAllItems(); _ascending = true; _sortIndex = 0; NormalizeSize(); _topDirPrefix.Empty(); { unsigned rootSize = GetRootPrefixSize(FilePath); #if defined(_WIN32) && !defined(UNDER_CE) // We can go up from root folder to drives list if (IsDrivePath(FilePath)) rootSize = 0; else if (IsSuperPath(FilePath)) { if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize))) rootSize = kSuperPathPrefixSize; } #endif _topDirPrefix.SetFrom(FilePath, rootSize); } UString name; if (!GetParentPath(FilePath, DirPrefix, name)) DirPrefix = _topDirPrefix; for (;;) { UString baseFolder = DirPrefix; if (Reload(baseFolder, name) == S_OK) break; name.Empty(); if (DirPrefix.IsEmpty()) break; UString parent, name2; GetParentPath(DirPrefix, parent, name2); DirPrefix = parent; } if (name.IsEmpty()) name = FilePath; if (FolderMode) NormalizeDirPathPrefix(name); _pathEdit.SetText(name); #ifndef UNDER_CE /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible, even if we use mouse for pressing the button to open this dialog. */ PostMsg(Z7_WIN_WM_UPDATEUISTATE, MAKEWPARAM(Z7_WIN_UIS_CLEAR, Z7_WIN_UISF_HIDEFOCUS)); #endif #if 0 { const HWND hwndTool = GetItem(IDB_BROWSE_CREATE_DIR); if (hwndTool) { // Create the tooltip: const HWND hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP // | TTS_BALLOON , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, *this, NULL, g_hInstance, NULL); if (hwndTip) { // Associate the tooltip with the tool: TOOLINFOW toolInfo; memset(&toolInfo, 0, sizeof(toolInfo)); toolInfo.cbSize = sizeof(toolInfo); toolInfo.hwnd = *this; toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS; toolInfo.uId = (UINT_PTR)hwndTool; UString s; #ifdef Z7_LANG LangString_OnlyFromLangFile(IDM_CREATE_FOLDER, s); s.RemoveChar(L'&'); if (s.IsEmpty()) #endif s = "Create Folder"; toolInfo.lpszText = s.Ptr_non_const(); SendMessage(hwndTip, TTM_ADDTOOLW, 0, (LPARAM)&toolInfo); } } } #endif return CModalDialog::OnInit(); } bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int mx, my; { RECT r; GetClientRectOfItem(IDB_BROWSE_PARENT, r); mx = r.left; my = r.top; } InvalidateRect(NULL); int xLim = xSize - mx; { RECT r; GetClientRectOfItem(IDT_BROWSE_FOLDER, r); MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r)); } int bx1, bx2, by; GetItemSizes(IDCANCEL, bx1, by); GetItemSizes(IDOK, bx2, by); int y = ySize - my - by; int x = xLim - bx1; MoveItem(IDCANCEL, x, y, bx1, by); MoveItem(IDOK, x - mx - bx2, y, bx2, by); // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead int yPathSize; { RECT r; GetClientRectOfItem(IDE_BROWSE_PATH, r); yPathSize = RECT_SIZE_Y(r); _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize); } { RECT r; GetClientRectOfItem(IDC_BROWSE_FILTER, r); _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r)); } { RECT r; GetClientRectOfItem(IDL_BROWSE, r); _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top); } return false; } bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { if (message == k_Message_RefreshPathEdit) { SetPathEditText(); return true; } return CModalDialog::OnMessage(message, wParam, lParam); } bool CBrowseDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam) { if (code == CBN_SELCHANGE) { switch (itemID) { case IDC_BROWSE_FILTER: { Reload(); return true; } } } return CModalDialog::OnCommand(code, itemID, lParam); } bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header) { if (header->hwndFrom != _list) return false; switch (header->code) { case LVN_ITEMACTIVATE: if (g_LVN_ITEMACTIVATE_Support) OnItemEnter(); break; case NM_DBLCLK: case NM_RETURN: // probably it's unused if (!g_LVN_ITEMACTIVATE_Support) OnItemEnter(); break; case LVN_COLUMNCLICK: { const int index = LPNMLISTVIEW(header)->iSubItem; if (index == _sortIndex) _ascending = !_ascending; else { _ascending = (index == 0); _sortIndex = index; } Reload(); return false; } case LVN_KEYDOWN: { bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header)); Post_RefreshPathEdit(); return boolResult; } case NM_RCLICK: case NM_CLICK: case LVN_BEGINDRAG: Post_RefreshPathEdit(); break; } return false; } bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo) { const bool ctrl = IsKeyDown(VK_CONTROL); switch (keyDownInfo->wVKey) { case VK_BACK: OpenParentFolder(); return true; case 'R': if (ctrl) { Reload(); return true; } return false; case VK_F7: OnCreateDir(); return true; } return false; } bool CBrowseDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { case IDB_BROWSE_PARENT: OpenParentFolder(); break; case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break; default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } _list.SetFocus(); return true; } void CBrowseDialog::OnOK() { /* When we press "Enter" in listview, Windows sends message to first Button. We check that message was from ListView; */ if (GetFocus() == _list) { OnItemEnter(); return; } FinishOnOK(); } bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name) { parentPrefix.Empty(); name.Empty(); if (path.IsEmpty()) return false; if (_topDirPrefix == path) return false; UString s = path; if (IS_PATH_SEPAR(s.Back())) s.DeleteBack(); if (s.IsEmpty()) return false; if (IS_PATH_SEPAR(s.Back())) return false; const unsigned pos1 = (unsigned)(s.ReverseFind_PathSepar() + 1); parentPrefix.SetFrom(s, pos1); name = s.Ptr(pos1); return true; } int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) const { if (lParam1 == lParam2) return 0; if (lParam1 == kParentIndex) return -1; if (lParam2 == kParentIndex) return 1; const CFileInfo &f1 = _files[(int)lParam1]; const CFileInfo &f2 = _files[(int)lParam2]; const bool isDir2 = f2.IsDir(); if (f1.IsDir()) { if (!isDir2) return -1; } else if (isDir2) return 1; int res = 0; switch (_sortIndex) { case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break; case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break; case 2: res = MyCompare(f1.Size, f2.Size); break; } return _ascending ? res: -res; } static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2); } wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s); wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s) { char c = 0; if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; } else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; } else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; } s = ConvertUInt64ToString(v, s); if (c != 0) { *s++ = ' '; *s++ = (wchar_t)c; *s++ = 'B'; *s = 0; } return s; } // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) { CObjectVector files; #ifndef UNDER_CE bool isDrive = false; if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix)) { isDrive = true; FStringVector drives; if (!MyGetLogicalDriveStrings(drives)) return GetLastError_noZero_HRESULT(); FOR_VECTOR (i, drives) { const FString &d = drives[i]; if (d.Len() < 2 || d.Back() != '\\') return E_FAIL; CFileInfo &fi = files.AddNew(); fi.SetAsDir(); fi.Name = d; fi.Name.DeleteBack(); } } else #endif { const UStringVector *masks = NULL; if (!Filters.IsEmpty() && _filterCombo.GetCount() > 0) { const int selected = _filterCombo.GetCurSel(); // GetItemData_of_CurSel(); // we don't use data field if (/* selected >= 0 && */ (unsigned)selected < Filters.Size()) { const UStringVector &m = Filters[selected].Masks; if (m.Size() > 1 || (m.Size() == 1 && !m[0].IsEqualTo("*.*") && !m[0].IsEqualTo("*"))) masks = &m; } } CEnumerator enumerator; enumerator.SetDirPrefix(us2fs(pathPrefix)); CFileInfo fi; for (;;) { bool found; if (!enumerator.Next(fi, found)) return GetLastError_noZero_HRESULT(); if (!found) break; if (!fi.IsDir()) { if (FolderMode) continue; if (masks) { unsigned i; const unsigned numMasks = masks->Size(); for (i = 0; i < numMasks; i++) if (DoesWildcardMatchName((*masks)[i], fs2us(fi.Name))) break; if (i == numMasks) continue; } } files.Add(fi); } } DirPrefix = pathPrefix; _files = files; SetItemText(IDT_BROWSE_FOLDER, DirPrefix); _list.SetRedraw(false); _list.DeleteAllItems(); LVITEMW item; unsigned index = 0; int cursorIndex = -1; #ifndef Z7_SFX if (_showDots && _topDirPrefix != DirPrefix) { item.iItem = (int)index; const UString itemName (".."); if (selectedName.IsEmpty()) cursorIndex = (int)index; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; unsigned subItem = 0; item.iSubItem = (int)(subItem++); item.lParam = kParentIndex; item.pszText = itemName.Ptr_non_const(); item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix); if (item.iImage < 0) item.iImage = 0; _list.InsertItem(&item); _list.SetSubItem(index, subItem++, L""); _list.SetSubItem(index, subItem++, L""); index++; } #endif for (unsigned i = 0; i < _files.Size(); i++, index++) { item.iItem = (int)index; const CFileInfo &fi = _files[i]; const UString name = fs2us(fi.Name); if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0) cursorIndex = (int)index; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; unsigned subItem = 0; item.iSubItem = (int)(subItem++); item.lParam = (LPARAM)i; item.pszText = name.Ptr_non_const(); const UString fullPath = DirPrefix + name; #ifndef UNDER_CE if (isDrive) { item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path( fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY); } else #endif item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); if (item.iImage < 0) item.iImage = 0; _list.InsertItem(&item); wchar_t s[64]; { s[0] = 0; if (!FILETIME_IsZero(fi.MTime)) ConvertUtcFileTimeToString(fi.MTime, s, #ifndef UNDER_CE kTimestampPrintLevel_MIN #else kTimestampPrintLevel_DAY #endif ); _list.SetSubItem(index, subItem++, s); } { s[0] = 0; if (!fi.IsDir()) Browse_ConvertSizeToString(fi.Size, s); _list.SetSubItem(index, subItem++, s); } } if (_list.GetItemCount() > 0 && cursorIndex >= 0) _list.SetItemState_FocusedSelected(cursorIndex); _list.SortItems(CompareItems2, (LPARAM)this); if (_list.GetItemCount() > 0 && cursorIndex < 0) _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); _list.EnsureVisible(_list.GetFocusedItem(), false); _list.SetRedraw(true); _list.InvalidateRect(NULL, true); return S_OK; } HRESULT CBrowseDialog::Reload() { UString selected; const int index = _list.GetNextSelectedItem(-1); if (index >= 0) { const int fileIndex = GetRealItemIndex(index); if (fileIndex != kParentIndex) selected = fs2us(_files[fileIndex].Name); } const UString dirPathTemp = DirPrefix; return Reload(dirPathTemp, selected); } void CBrowseDialog::OpenParentFolder() { UString parent, selected; if (GetParentPath(DirPrefix, parent, selected)) { Reload(parent, selected); SetPathEditText(); } } void CBrowseDialog::SetPathEditText() { const int index = _list.GetNextSelectedItem(-1); if (index < 0) { if (FolderMode) _pathEdit.SetText(DirPrefix); return; } const int fileIndex = GetRealItemIndex(index); if (fileIndex == kParentIndex) { if (FolderMode) _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR); return; } const CFileInfo &file = _files[fileIndex]; if (file.IsDir()) { if (!FolderMode) return; _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR); } else _pathEdit.SetText(fs2us(file.Name)); } void CBrowseDialog::OnCreateDir() { UString name; { UString enteredName; Dlg_CreateFolder((HWND)*this, enteredName); if (enteredName.IsEmpty()) return; if (!CorrectFsPath(DirPrefix, enteredName, name)) { MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name); return; } } if (name.IsEmpty()) return; FString destPath; if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath)) { if (!NDir::CreateComplexDir(destPath)) { MessageBox_HResError((HWND)*this, GetLastError_noZero_HRESULT(), fs2us(destPath)); } else { UString tempPath = DirPrefix; Reload(tempPath, name); SetPathEditText(); } _list.SetFocus(); } } void CBrowseDialog::OnItemEnter() { const int index = _list.GetNextSelectedItem(-1); if (index < 0) return; const int fileIndex = GetRealItemIndex(index); if (fileIndex == kParentIndex) OpenParentFolder(); else { const CFileInfo &file = _files[fileIndex]; if (!file.IsDir()) { if (!FolderMode) FinishOnOK(); /* MessageBox_Error_Global(*this, FolderMode ? L"You must select some folder": L"You must select some file"); */ return; } UString s = DirPrefix; s += fs2us(file.Name); s.Add_PathSepar(); const HRESULT res = Reload(s, UString()); if (res != S_OK) MessageBox_HResError(*this, res, s); SetPathEditText(); } } void CBrowseDialog::FinishOnOK() { UString s; _pathEdit.GetText(s); FString destPath; if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath)) { MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s); return; } FilePath = fs2us(destPath); if (FolderMode) NormalizeDirPathPrefix(FilePath); FilterIndex = _filterCombo.GetCurSel(); End(IDOK); } #endif // USE_MY_BROWSE_DIALOG bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath) { resultPath.Empty(); #ifndef UNDER_CE #ifdef USE_MY_BROWSE_DIALOG if (!IsSuperOrDevicePath(path)) if (MyStringLen(path) < MAX_PATH) #endif return NShell::BrowseForFolder(owner, title, path, resultPath); #endif // UNDER_CE #ifdef USE_MY_BROWSE_DIALOG CBrowseDialog dialog; dialog.FolderMode = true; if (title) dialog.Title = title; if (path) dialog.FilePath = path; if (dialog.Create(owner) != IDOK) return false; resultPath = dialog.FilePath; return true; #endif } // LPCWSTR filterDescription, LPCWSTR filter, bool CBrowseInfo::BrowseForFile(const CObjectVector &filters) { #ifndef UNDER_CE #ifdef USE_MY_BROWSE_DIALOG /* win10: GetOpenFileName() for FilePath doesn't support super prefix "\\\\?\\" GetOpenFileName() for FilePath doesn't support long path */ if (!IsSuperOrDevicePath(FilePath)) // if (filters.Size() > 100) // for debug #endif { const UString filePath_Store = FilePath; UString dirPrefix; { FString prefix, name; if (NDir::GetFullPathAndSplit(us2fs(FilePath), prefix, name)) { dirPrefix = fs2us(prefix); FilePath = fs2us(name); } } UStringVector filters2; FOR_VECTOR (i, filters) { const CBrowseFilterInfo &fi = filters[i]; filters2.Add(fi.Description); UString s; FOR_VECTOR (k, fi.Masks) { if (k != 0) s += ";"; s += fi.Masks[k]; } filters2.Add(s); } if (CommonDlg_BrowseForFile(!dirPrefix.IsEmpty() ? dirPrefix.Ptr(): NULL, filters2)) return true; FilePath = filePath_Store; #ifdef UNDER_CE return false; #else // maybe we must use GetLastError in WinCE. const DWORD errorCode = CommDlgExtendedError(); #ifdef USE_MY_BROWSE_DIALOG // FNERR_INVALIDFILENAME is expected error, if long path was used if (errorCode != FNERR_INVALIDFILENAME || FilePath.Len() < MAX_PATH) #endif { if (errorCode == 0) // cancel or close on dialog return false; const char *message = NULL; if (errorCode == FNERR_INVALIDFILENAME) message = "Invalid file name"; UString s ("Open Dialog Error:"); s.Add_LF(); if (message) s += message; else { char temp[16]; ConvertUInt32ToHex8Digits(errorCode, temp); s += "Error #"; s += temp; } s.Add_LF(); s += FilePath; MessageBox_Error_Global(hwndOwner, s); } #endif // UNDER_CE } #endif // UNDER_CE #ifdef USE_MY_BROWSE_DIALOG CBrowseDialog dialog; dialog.FolderMode = false; dialog.SaveMode = SaveMode; dialog.FilterIndex = FilterIndex; dialog.Filters = filters; if (lpstrTitle) dialog.Title = lpstrTitle; dialog.FilePath = FilePath; if (dialog.Create(hwndOwner) != IDOK) return false; FilePath = dialog.FilePath; FilterIndex = dialog.FilterIndex; #endif return true; } #ifdef _WIN32 static void RemoveDotsAndSpaces(UString &path) { while (!path.IsEmpty()) { wchar_t c = path.Back(); if (c != ' ' && c != '.') return; path.DeleteBack(); } } bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result) { result.Empty(); UString path = path2; #ifdef _WIN32 path.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif unsigned start = 0; UString base; if (IsAbsolutePath(path)) { #if defined(_WIN32) && !defined(UNDER_CE) if (IsSuperOrDevicePath(path)) { result = path; return true; } #endif start = GetRootPrefixSize(path); } else { #if defined(_WIN32) && !defined(UNDER_CE) if (IsSuperOrDevicePath(relBase)) { result = path; return true; } #endif base = relBase; } /* We can't use backward, since we must change only disk paths */ /* for (;;) { if (path.Len() <= start) break; if (DoesFileOrDirExist(us2fs(path))) break; if (path.Back() == WCHAR_PATH_SEPARATOR) { path.DeleteBack(); result.Insert(0, WCHAR_PATH_SEPARATOR); } int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1; UString cur = path.Ptr(pos); RemoveDotsAndSpaces(cur); result.Insert(0, cur); path.DeleteFrom(pos); } result.Insert(0, path); return true; */ result += path.Left(start); bool checkExist = true; UString cur; for (;;) { if (start == path.Len()) break; const int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start); cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : (unsigned)slashPos) - start); if (checkExist) { CFileInfo fi; if (fi.Find(us2fs(base + result + cur))) { if (!fi.IsDir()) { result = path; break; } } else checkExist = false; } if (!checkExist) RemoveDotsAndSpaces(cur); result += cur; if (slashPos < 0) break; start = (unsigned)(slashPos + 1); result.Add_PathSepar(); } return true; } #else bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result) { result = path; return true; } #endif bool Dlg_CreateFolder(HWND wnd, UString &destName) { destName.Empty(); CComboDialog dlg; LangString(IDS_CREATE_FOLDER, dlg.Title); LangString(IDS_CREATE_FOLDER_NAME, dlg.Static); LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value); if (dlg.Create(wnd) != IDOK) return false; destName = dlg.Value; return true; } tmp41wklro_/CPP/7zip/UI/FileManager/BrowseDialog.h0000444000175000001440000000164214357314620022705 0ustar nabijaczleweliusers// BrowseDialog.h #ifndef ZIP7_INC_BROWSE_DIALOG_H #define ZIP7_INC_BROWSE_DIALOG_H #include "../../../Windows/CommonDialog.h" bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath); struct CBrowseFilterInfo { UStringVector Masks; UString Description; }; struct CBrowseInfo: public NWindows::CCommonDialogInfo { bool BrowseForFile(const CObjectVector &filters); }; /* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file) But it doesn't change "bad" name in any of the following cases: - path is Super Path (with \\?\ prefix) - path is relative and relBase is Super Path - there is file or dir in filesystem with specified "bad" name */ bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); bool Dlg_CreateFolder(HWND wnd, UString &destName); #endif tmp41wklro_/CPP/7zip/UI/FileManager/BrowseDialogRes.h0000444000175000001440000000034212111115261023335 0ustar nabijaczleweliusers#define IDD_BROWSE 95 #define IDL_BROWSE 100 #define IDT_BROWSE_FOLDER 101 #define IDE_BROWSE_PATH 102 #define IDC_BROWSE_FILTER 103 #define IDB_BROWSE_PARENT 110 #define IDB_BROWSE_CREATE_DIR 112 tmp41wklro_/CPP/7zip/UI/FileManager/ComboDialog.cpp0000444000175000001440000000247314365550100023033 0ustar nabijaczleweliusers// ComboDialog.cpp #include "StdAfx.h" #include "ComboDialog.h" #include "../../../Windows/Control/Static.h" #ifdef Z7_LANG #include "LangUtils.h" #endif using namespace NWindows; bool CComboDialog::OnInit() { #ifdef Z7_LANG LangSetDlgItems(*this, NULL, 0); #endif _comboBox.Attach(GetItem(IDC_COMBO)); /* // why it doesn't work ? DWORD style = _comboBox.GetStyle(); if (Sorted) style |= CBS_SORT; else style &= ~CBS_SORT; _comboBox.SetStyle(style); */ SetText(Title); NControl::CStatic staticContol; staticContol.Attach(GetItem(IDT_COMBO)); staticContol.SetText(Static); _comboBox.SetText(Value); FOR_VECTOR (i, Strings) _comboBox.AddString(Strings[i]); NormalizeSize(); return CModalDialog::OnInit(); } bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int mx, my; GetMargins(8, mx, my); int bx1, bx2, by; GetItemSizes(IDCANCEL, bx1, by); GetItemSizes(IDOK, bx2, by); int y = ySize - my - by; int x = xSize - mx - bx1; InvalidateRect(NULL); MoveItem(IDCANCEL, x, y, bx1, by); MoveItem(IDOK, x - mx - bx2, y, bx2, by); ChangeSubWindowSizeX(_comboBox, xSize - mx * 2); return false; } void CComboDialog::OnOK() { _comboBox.GetText(Value); CModalDialog::OnOK(); } tmp41wklro_/CPP/7zip/UI/FileManager/ComboDialog.h0000444000175000001440000000134314365270260022501 0ustar nabijaczleweliusers// ComboDialog.h #ifndef ZIP7_INC_COMBO_DIALOG_H #define ZIP7_INC_COMBO_DIALOG_H #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Dialog.h" #include "ComboDialogRes.h" class CComboDialog: public NWindows::NControl::CModalDialog { NWindows::NControl::CComboBox _comboBox; virtual void OnOK() Z7_override; virtual bool OnInit() Z7_override; virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; public: // bool Sorted; UString Title; UString Static; UString Value; UStringVector Strings; // CComboDialog(): Sorted(false) {}; INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_COMBO, parentWindow); } }; #endif tmp41wklro_/CPP/7zip/UI/FileManager/ComboDialogRes.h0000444000175000001440000000011211573137361023146 0ustar nabijaczleweliusers#define IDD_COMBO 98 #define IDT_COMBO 100 #define IDC_COMBO 101 tmp41wklro_/CPP/7zip/UI/FileManager/DialogSize.h0000444000175000001440000000057014357323640022357 0ustar nabijaczleweliusers// DialogSize.h #ifndef ZIP7_INC_DIALOG_SIZE_H #define ZIP7_INC_DIALOG_SIZE_H #include "../../../Windows/Control/Dialog.h" #ifdef UNDER_CE #define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y); #define SIZED_DIALOG(big) (isBig ? big : big ## _2) #else #define BIG_DIALOG_SIZE(x, y) #define SIZED_DIALOG(big) big #endif #endif tmp41wklro_/CPP/7zip/UI/FileManager/ExtractCallback.cpp0000444000175000001440000007467214641676720023733 0ustar nabijaczleweliusers// ExtractCallback.cpp #include "StdAfx.h" #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/Lang.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/PropVariantConv.h" #include "../../Common/FilePathAutoRename.h" #include "../../Common/StreamUtils.h" #include "../Common/ExtractingFilePath.h" #ifndef Z7_SFX #include "../Common/ZipRegistry.h" #endif #include "../GUI/ExtractRes.h" #include "resourceGui.h" #include "ExtractCallback.h" #include "FormatUtils.h" #include "LangUtils.h" #include "OverwriteDialog.h" #ifndef Z7_NO_CRYPTO #include "PasswordDialog.h" #endif #include "MemDialog.h" #include "PropertyName.h" using namespace NWindows; using namespace NFile; using namespace NFind; extern bool g_DisableUserQuestions; CExtractCallbackImp::~CExtractCallbackImp() {} void CExtractCallbackImp::Init() { _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING); _lang_Testing = LangString(IDS_PROGRESS_TESTING); _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING); _lang_Reading = "Reading"; NumArchiveErrors = 0; ThereAreMessageErrors = false; #ifndef Z7_SFX NumFolders = NumFiles = 0; NeedAddFile = false; #endif } void CExtractCallbackImp::AddError_Message(LPCWSTR s) { ThereAreMessageErrors = true; ProgressDialog->Sync.AddError_Message(s); } void CExtractCallbackImp::AddError_Message_ShowArcPath(LPCWSTR s) { Add_ArchiveName_Error(); AddError_Message(s); } #ifndef Z7_SFX Z7_COM7F_IMF(CExtractCallbackImp::SetNumFiles(UInt64 numFiles)) { #ifdef Z7_SFX UNUSED_VAR(numFiles) #else ProgressDialog->Sync.Set_NumFilesTotal(numFiles); #endif return S_OK; } #endif Z7_COM7F_IMF(CExtractCallbackImp::SetTotal(UInt64 total)) { ProgressDialog->Sync.Set_NumBytesTotal(total); return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::SetCompleted(const UInt64 *value)) { return ProgressDialog->Sync.Set_NumBytesCur(value); } HRESULT CExtractCallbackImp::Open_CheckBreak() { return ProgressDialog->Sync.CheckStop(); } HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes) { HRESULT res = S_OK; if (!MultiArcMode) { if (files) { _totalFilesDefined = true; // res = ProgressDialog->Sync.Set_NumFilesTotal(*files); } else _totalFilesDefined = false; if (bytes) { _totalBytesDefined = true; ProgressDialog->Sync.Set_NumBytesTotal(*bytes); } else _totalBytesDefined = false; } return res; } HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) { if (!MultiArcMode) { if (files) { ProgressDialog->Sync.Set_NumFilesCur(*files); } if (bytes) { } } return ProgressDialog->Sync.CheckStop(); } HRESULT CExtractCallbackImp::Open_Finished() { return ProgressDialog->Sync.CheckStop(); } #ifndef Z7_NO_CRYPTO HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) { return CryptoGetTextPassword(password); } /* HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { passwordIsDefined = PasswordIsDefined; password = Password; return S_OK; } bool CExtractCallbackImp::Open_WasPasswordAsked() { return PasswordWasAsked; } void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag() { PasswordWasAsked = false; } */ #endif #ifndef Z7_SFX Z7_COM7F_IMF(CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) { ProgressDialog->Sync.Set_Ratio(inSize, outSize); return S_OK; } #endif /* Z7_COM7F_IMF(CExtractCallbackImp::SetTotalFiles(UInt64 total) { ProgressDialog->Sync.SetNumFilesTotal(total); return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::SetCompletedFiles(const UInt64 *value) { if (value != NULL) ProgressDialog->Sync.SetNumFilesCur(*value); return S_OK; } */ Z7_COM7F_IMF(CExtractCallbackImp::AskOverwrite( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer)) { COverwriteDialog dialog; dialog.OldFileInfo.SetTime2(existTime); dialog.OldFileInfo.SetSize2(existSize); dialog.OldFileInfo.Path = existName; dialog.OldFileInfo.Is_FileSystemFile = true; dialog.NewFileInfo.SetTime2(newTime); dialog.NewFileInfo.SetSize2(newSize); dialog.NewFileInfo.Path = newName; dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder; ProgressDialog->WaitCreating(); INT_PTR writeAnswer = dialog.Create(*ProgressDialog); switch (writeAnswer) { case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT; case IDYES: *answer = NOverwriteAnswer::kYes; break; case IDNO: *answer = NOverwriteAnswer::kNo; break; case IDB_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break; case IDB_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break; case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)) { _isFolder = IntToBool(isFolder); _currentFilePath = name; const UString *msg = &_lang_Empty; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break; case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break; case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break; case NArchive::NExtract::NAskMode::kReadExternal: msg = &_lang_Reading; break; // default: s = "Unknown operation"; } return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder)); } Z7_COM7F_IMF(CExtractCallbackImp::MessageError(const wchar_t *s)) { AddError_Message(s); return S_OK; } HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path) { ThereAreMessageErrors = true; ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path)); return S_OK; } #ifndef Z7_SFX Z7_COM7F_IMF(CExtractCallbackImp::ShowMessage(const wchar_t *s)) { AddError_Message(s); return S_OK; } #endif void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s) { s.Empty(); if (opRes == NArchive::NExtract::NOperationResult::kOK) return; #ifndef Z7_SFX UINT messageID = 0; #endif UINT id = 0; switch (opRes) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: #ifndef Z7_SFX messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; #endif id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD; break; case NArchive::NExtract::NOperationResult::kDataError: #ifndef Z7_SFX messageID = encrypted ? IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: IDS_EXTRACT_MESSAGE_DATA_ERROR; #endif id = IDS_EXTRACT_MSG_DATA_ERROR; break; case NArchive::NExtract::NOperationResult::kCRCError: #ifndef Z7_SFX messageID = encrypted ? IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED: IDS_EXTRACT_MESSAGE_CRC_ERROR; #endif id = IDS_EXTRACT_MSG_CRC_ERROR; break; case NArchive::NExtract::NOperationResult::kUnavailable: id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA; break; case NArchive::NExtract::NOperationResult::kUnexpectedEnd: id = IDS_EXTRACT_MSG_UEXPECTED_END; break; case NArchive::NExtract::NOperationResult::kDataAfterEnd: id = IDS_EXTRACT_MSG_DATA_AFTER_END; break; case NArchive::NExtract::NOperationResult::kIsNotArc: id = IDS_EXTRACT_MSG_IS_NOT_ARC; break; case NArchive::NExtract::NOperationResult::kHeadersError: id = IDS_EXTRACT_MSG_HEADERS_ERROR; break; case NArchive::NExtract::NOperationResult::kWrongPassword: id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM; break; /* default: messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; break; */ } UString msg; #ifndef Z7_SFX UString msgOld; #ifdef Z7_LANG if (id != 0) LangString_OnlyFromLangFile(id, msg); if (messageID != 0 && msg.IsEmpty()) LangString_OnlyFromLangFile(messageID, msgOld); #endif if (msg.IsEmpty() && !msgOld.IsEmpty()) s = MyFormatNew(msgOld, fileName); else #endif { if (msg.IsEmpty() && id != 0) LangString(id, msg); if (!msg.IsEmpty()) s += msg; else { s += "Error #"; s.Add_UInt32((UInt32)opRes); } if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword) { // s += " : "; // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED); s += " : "; AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); } s += " : "; s += fileName; } } Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)) { switch (opRes) { case NArchive::NExtract::NOperationResult::kOK: break; default: { UString s; SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s); AddError_Message_ShowArcPath(s); } } _currentFilePath.Empty(); #ifndef Z7_SFX if (_isFolder) NumFolders++; else NumFiles++; ProgressDialog->Sync.Set_NumFilesCur(NumFiles); #endif return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)) { if (opRes != NArchive::NExtract::NOperationResult::kOK) { UString s; SetExtractErrorMessage(opRes, encrypted, name, s); AddError_Message_ShowArcPath(s); } return S_OK; } //////////////////////////////////////// // IExtractCallbackUI HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */) { _currentArchivePath = name; _needWriteArchivePath = true; #ifndef Z7_SFX RINOK(ProgressDialog->Sync.CheckStop()) ProgressDialog->Sync.Set_TitleFileName(name); #endif return S_OK; } HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path) { _currentFilePath = path; #ifndef Z7_SFX ProgressDialog->Sync.Set_FilePath(path); #endif return S_OK; } #ifndef Z7_SFX Z7_COM7F_IMF(CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)) { #ifndef Z7_SFX if (NeedAddFile) NumFiles++; NeedAddFile = true; ProgressDialog->Sync.Set_NumFilesCur(NumFiles); #endif return SetCurrentFilePath2(path); } #endif UString HResultToMessage(HRESULT errorCode); static const UInt32 k_ErrorFlagsIds[] = { IDS_EXTRACT_MSG_IS_NOT_ARC, IDS_EXTRACT_MSG_HEADERS_ERROR, IDS_EXTRACT_MSG_HEADERS_ERROR, IDS_OPEN_MSG_UNAVAILABLE_START, IDS_OPEN_MSG_UNCONFIRMED_START, IDS_EXTRACT_MSG_UEXPECTED_END, IDS_EXTRACT_MSG_DATA_AFTER_END, IDS_EXTRACT_MSG_UNSUPPORTED_METHOD, IDS_OPEN_MSG_UNSUPPORTED_FEATURE, IDS_EXTRACT_MSG_DATA_ERROR, IDS_EXTRACT_MSG_CRC_ERROR }; static void AddNewLineString(UString &s, const UString &m) { s += m; s.Add_LF(); } UString GetOpenArcErrorMessage(UInt32 errorFlags); UString GetOpenArcErrorMessage(UInt32 errorFlags) { UString s; for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsIds); i++) { UInt32 f = ((UInt32)1 << i); if ((errorFlags & f) == 0) continue; UInt32 id = k_ErrorFlagsIds[i]; UString m = LangString(id); if (m.IsEmpty()) continue; if (f == kpv_ErrorFlags_EncryptedHeadersError) { m += " : "; AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); } if (!s.IsEmpty()) s.Add_LF(); s += m; errorFlags &= ~f; } if (errorFlags != 0) { char sz[16]; sz[0] = '0'; sz[1] = 'x'; ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) s.Add_LF(); s += sz; } return s; } static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) { UInt32 errorFlags = er.GetErrorFlags(); UInt32 warningFlags = er.GetWarningFlags(); if (errorFlags != 0) AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); if (!er.ErrorMessage.IsEmpty()) AddNewLineString(s, er.ErrorMessage); if (warningFlags != 0) { s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); s += ":"; s.Add_LF(); AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); } if (!er.WarningMessage.IsEmpty()) { s += GetNameOfProperty(kpidWarning, L"Warning"); s += ": "; s += er.WarningMessage; s.Add_LF(); } } static UString GetBracedType(const wchar_t *type) { UString s ('['); s += type; s.Add_Char(']'); return s; } void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result); void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { FOR_VECTOR (level, arcLink.Arcs) { const CArc &arc = arcLink.Arcs[level]; const CArcErrorInfo &er = arc.ErrorInfo; if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0) continue; if (s.IsEmpty()) { s += name; s.Add_LF(); } if (level != 0) { AddNewLineString(s, arc.Path); } ErrorInfo_Print(s, er); if (er.ErrorFormatIndex >= 0) { AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning")); if (arc.FormatIndex == er.ErrorFormatIndex) { AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET)); } else { AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex)))); AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex)))); } } } if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK) { s += name; s.Add_LF(); if (!arcLink.Arcs.IsEmpty()) AddNewLineString(s, arcLink.NonOpen_ArcPath); if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE) { UINT id = IDS_CANT_OPEN_ARCHIVE; UString param; if (arcLink.PasswordWasAsked) id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE; else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) { id = IDS_CANT_OPEN_AS_TYPE; param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex)); } UString s2 = MyFormatNew(id, param); s2.Replace(L" ''", L""); s2.Replace(L"''", L""); s += s2; } else s += HResultToMessage(result); s.Add_LF(); ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo); } if (!s.IsEmpty() && s.Back() == '\n') s.DeleteBack(); } HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { _currentArchivePath = name; _needWriteArchivePath = true; UString s; OpenResult_GUI(s, codecs, arcLink, name, result); if (!s.IsEmpty()) { NumArchiveErrors++; AddError_Message(s); _needWriteArchivePath = false; } return S_OK; } HRESULT CExtractCallbackImp::ThereAreNoFiles() { return S_OK; } void CExtractCallbackImp::Add_ArchiveName_Error() { if (_needWriteArchivePath) { if (!_currentArchivePath.IsEmpty()) AddError_Message(_currentArchivePath); _needWriteArchivePath = false; } } HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) { #ifndef Z7_SFX ProgressDialog->Sync.Set_FilePath(L""); #endif if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) ) return result; Add_ArchiveName_Error(); if (!_currentFilePath.IsEmpty()) MessageError(_currentFilePath); MessageError(NError::MyFormatMessage(result)); return S_OK; } #ifndef Z7_NO_CRYPTO HRESULT CExtractCallbackImp::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)) { PasswordWasAsked = true; if (!PasswordIsDefined) { CPasswordDialog dialog; #ifndef Z7_SFX const bool showPassword = NExtract::Read_ShowPassword(); dialog.ShowPassword = showPassword; #endif ProgressDialog->WaitCreating(); if (dialog.Create(*ProgressDialog) != IDOK) return E_ABORT; Password = dialog.Password; PasswordIsDefined = true; #ifndef Z7_SFX if (dialog.ShowPassword != showPassword) NExtract::Save_ShowPassword(dialog.ShowPassword); #endif } return StringToBstr(Password, password); } #endif #ifndef Z7_SFX Z7_COM7F_IMF(CExtractCallbackImp::AskWrite( const wchar_t *srcPath, Int32 srcIsFolder, const FILETIME *srcTime, const UInt64 *srcSize, const wchar_t *destPath, BSTR *destPathResult, Int32 *writeAnswer)) { UString destPathResultTemp = destPath; // RINOK(StringToBstr(destPath, destPathResult)); *destPathResult = NULL; *writeAnswer = BoolToInt(false); FString destPathSys = us2fs(destPath); const bool srcIsFolderSpec = IntToBool(srcIsFolder); CFileInfo destFileInfo; if (destFileInfo.Find(destPathSys)) { if (srcIsFolderSpec) { if (!destFileInfo.IsDir()) { RINOK(MessageError("Cannot replace file with folder with same name", destPathSys)) return E_ABORT; } *writeAnswer = BoolToInt(false); return S_OK; } if (destFileInfo.IsDir()) { RINOK(MessageError("Cannot replace folder with file with same name", destPathSys)) *writeAnswer = BoolToInt(false); return S_OK; } switch ((int)OverwriteMode) { case NExtract::NOverwriteMode::kSkip: return S_OK; case NExtract::NOverwriteMode::kAsk: { Int32 overwriteResult; UString destPathSpec = destPath; const int slashPos = destPathSpec.ReverseFind_PathSepar(); destPathSpec.DeleteFrom((unsigned)(slashPos + 1)); destPathSpec += fs2us(destFileInfo.Name); RINOK(AskOverwrite( destPathSpec, &destFileInfo.MTime, &destFileInfo.Size, srcPath, srcTime, srcSize, &overwriteResult)) switch (overwriteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break; case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break; default: return E_FAIL; } break; } default: break; } if (OverwriteMode == NExtract::NOverwriteMode::kRename) { if (!AutoRenamePath(destPathSys)) { RINOK(MessageError("Cannot create name for file", destPathSys)) return E_ABORT; } destPathResultTemp = fs2us(destPathSys); } else { if (NFind::DoesFileExist_Raw(destPathSys)) if (!NDir::DeleteFileAlways(destPathSys)) if (GetLastError() != ERROR_FILE_NOT_FOUND) { RINOK(MessageError("Cannot delete output file", destPathSys)) return E_ABORT; } } } *writeAnswer = BoolToInt(true); return StringToBstr(destPathResultTemp, destPathResult); } Z7_COM7F_IMF(CExtractCallbackImp::UseExtractToStream(Int32 *res)) { *res = BoolToInt(StreamMode); return S_OK; } static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined) { ftDefined = false; NCOM::CPropVariant prop; RINOK(getProp->GetProp(propID, &prop)) if (prop.vt == VT_FILETIME) { ft = prop.filetime; ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result) { NCOM::CPropVariant prop; result = false; RINOK(getProp->GetProp(propID, &prop)) if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } Z7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp)) { COM_TRY_BEGIN *outStream = NULL; _newVirtFileWasAdded = false; _hashStream_WasUsed = false; _needUpdateStat = false; if (_hashStream) _hashStream->ReleaseStream(); GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); if (!ProcessAltStreams && _isAltStream) return S_OK; _filePath = name; _isFolder = IntToBool(isDir); _curSize = 0; _curSize_Defined = false; UInt64 size = 0; bool sizeDefined; { NCOM::CPropVariant prop; RINOK(getProp->GetProp(kpidSize, &prop)) sizeDefined = ConvertPropVariantToUInt64(prop, size); } if (sizeDefined) { _curSize = size; _curSize_Defined = true; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract && askExtractMode != NArchive::NExtract::NAskMode::kTest) return S_OK; _needUpdateStat = true; CMyComPtr outStreamLoc; if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract) { CVirtFile &file = VirtFileSystemSpec->AddNewFile(); _newVirtFileWasAdded = true; file.Name = name; file.IsDir = IntToBool(isDir); file.IsAltStream = _isAltStream; file.Size = 0; RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined)) RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined)) RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined)) NCOM::CPropVariant prop; RINOK(getProp->GetProp(kpidAttrib, &prop)) if (prop.vt == VT_UI4) { file.Attrib = prop.ulVal; file.AttribDefined = true; } // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY; file.ExpectedSize = 0; if (sizeDefined) file.ExpectedSize = size; outStreamLoc = VirtFileSystem; } if (_hashStream) { { _hashStream->SetStream(outStreamLoc); outStreamLoc = _hashStream; _hashStream->Init(true); _hashStream_WasUsed = true; } } if (outStreamLoc) *outStream = outStreamLoc.Detach(); return S_OK; COM_TRY_END } Z7_COM7F_IMF(CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)) { COM_TRY_BEGIN _needUpdateStat = ( askExtractMode == NArchive::NExtract::NAskMode::kExtract || askExtractMode == NArchive::NExtract::NAskMode::kTest || askExtractMode == NArchive::NExtract::NAskMode::kReadExternal ); /* _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: if (_testMode) askExtractMode = NArchive::NExtract::NAskMode::kTest; else _extractMode = true; break; }; */ return SetCurrentFilePath2(_filePath); COM_TRY_END } Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypted, UInt64 size)) { COM_TRY_BEGIN if (VirtFileSystem && _newVirtFileWasAdded) { // FIXME: probably we must request file size from VirtFileSystem // _curSize = VirtFileSystem->GetLastFileSize() // _curSize_Defined = true; RINOK(VirtFileSystemSpec->CloseMemFile()) } if (_hashStream && _hashStream_WasUsed) { _hashStream->_hash->Final(_isFolder, _isAltStream, _filePath); _curSize = _hashStream->GetSize(); _curSize_Defined = true; _hashStream->ReleaseStream(); _hashStream_WasUsed = false; } else if (_hashCalc && _needUpdateStat) { _hashCalc->SetSize(size); // (_curSize) before 21.04 _hashCalc->Final(_isFolder, _isAltStream, _filePath); } return SetOperationResult(opRes, encrypted); COM_TRY_END } Z7_COM7F_IMF(CExtractCallbackImp::RequestMemoryUse( UInt32 flags, UInt32 indexType, UInt32 /* index */, const wchar_t *path, UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags)) { UInt32 limit_GB = (UInt32)((*allowedSize + ((1u << 30) - 1)) >> 30); if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0) { UInt64 limit_bytes = *allowedSize; const UInt32 limit_GB_Registry = NExtract::Read_LimitGB(); if (limit_GB_Registry != 0 && limit_GB_Registry != (UInt32)(Int32)-1) { const UInt64 limit_bytes_Registry = (UInt64)limit_GB_Registry << 30; // registry_WasForced = true; if ((flags & NRequestMemoryUseFlags::k_AllowedSize_WasForced) == 0 || limit_bytes < limit_bytes_Registry) { limit_bytes = limit_bytes_Registry; limit_GB = limit_GB_Registry; } } *allowedSize = limit_bytes; if (requiredSize <= limit_bytes) { *answerFlags = NRequestMemoryAnswerFlags::k_Allow; return S_OK; } // default answer can be k_Allow, if limit was not forced, // so we change answer to non-allowed here, // because user has chance to change limit in GUI. *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded; if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc; } const UInt32 required_GB = (UInt32)((requiredSize + ((1u << 30) - 1)) >> 30); CMemDialog dialog; dialog.Limit_GB = limit_GB; dialog.Required_GB = required_GB; dialog.TestMode = TestMode; if (MultiArcMode) dialog.ArcPath = _currentArchivePath; if (path) dialog.FilePath = path; if (!g_DisableUserQuestions && (flags & NRequestMemoryUseFlags::k_IsReport) == 0) { if (_remember) dialog.SkipArc = _skipArc; else { dialog.ShowRemember = (MultiArcMode || indexType != NArchive::NEventIndexType::kNoIndex || path); ProgressDialog->WaitCreating(); if (dialog.Create(*ProgressDialog) != IDCONTINUE) { *answerFlags = NRequestMemoryAnswerFlags::k_Stop; return E_ABORT; } if (dialog.NeedSave) NExtract::Save_LimitGB(dialog.Limit_GB); if (dialog.Remember) { _remember = true; _skipArc = dialog.SkipArc; } } *allowedSize = (UInt64)dialog.Limit_GB << 30; if (!dialog.SkipArc) { *answerFlags = NRequestMemoryAnswerFlags::k_Allow; return S_OK; } *answerFlags = NRequestMemoryAnswerFlags::k_SkipArc | NRequestMemoryAnswerFlags::k_Limit_Exceeded; flags |= NRequestMemoryUseFlags::k_Report_SkipArc; } if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0) { UString s ("ERROR: "); dialog.AddInfoMessage_To_String(s); s.Add_LF(); // if (indexType == NArchive::NEventIndexType::kNoIndex) if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) || (flags & NRequestMemoryUseFlags::k_Report_SkipArc)) s += LangString(IDS_MSG_ARC_UNPACKING_WAS_SKIPPED); /* else s += LangString(IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED); */ AddError_Message_ShowArcPath(s); } /* if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0) *answerFlags |= NRequestMemoryAnswerFlags::k_Limit_Exceeded; */ return S_OK; } // static const UInt32 kBlockSize = ((UInt32)1 << 31); Z7_COM7F_IMF(CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (!_fileMode) { CVirtFile &file = Files.Back(); size_t rem = file.Data.Size() - (size_t)file.Size; bool useMem = true; if (rem < size) { UInt64 b = 0; if (file.Data.Size() == 0) b = file.ExpectedSize; UInt64 a = file.Size + size; if (b < a) b = a; a = (UInt64)file.Data.Size() * 2; if (b < a) b = a; useMem = false; const size_t b_sizet = (size_t)b; if (b == b_sizet && b <= MaxTotalAllocSize) useMem = file.Data.ReAlloc_KeepData(b_sizet, (size_t)file.Size); } if (useMem) { memcpy(file.Data + file.Size, data, size); file.Size += size; if (processedSize) *processedSize = (UInt32)size; return S_OK; } _fileMode = true; } RINOK(FlushToDisk(false)) return _outFileStream.Interface()->Write(data, size, processedSize); } HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) { _outFileStream.Create_if_Empty(); while (_numFlushed < Files.Size()) { const CVirtFile &file = Files[_numFlushed]; const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name)); if (!_fileIsOpen) { if (!_outFileStream->Create_NEW(path)) { // do we need to release stream here? // _outFileStream.Release(); return E_FAIL; // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); } _fileIsOpen = true; RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size)) } if (_numFlushed == Files.Size() - 1 && !closeLast) break; if (file.CTimeDefined || file.ATimeDefined || file.MTimeDefined) _outFileStream->SetTime( file.CTimeDefined ? &file.CTime : NULL, file.ATimeDefined ? &file.ATime : NULL, file.MTimeDefined ? &file.MTime : NULL); _outFileStream->Close(); _numFlushed++; _fileIsOpen = false; if (ZoneBuf.Size() != 0) WriteZoneFile_To_BaseFile(path, ZoneBuf); if (file.AttribDefined) NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib); } return S_OK; } #endif tmp41wklro_/CPP/7zip/UI/FileManager/ExtractCallback.h0000444000175000001440000001634714641705740023366 0ustar nabijaczleweliusers// ExtractCallback.h #ifndef ZIP7_INC_EXTRACT_CALLBACK_H #define ZIP7_INC_EXTRACT_CALLBACK_H #include "../../../../C/Alloc.h" #include "../../../Common/MyCom.h" #include "../../../Common/StringConvert.h" #ifndef Z7_SFX #include "../Agent/IFolderArchive.h" #endif #include "../Common/ArchiveExtractCallback.h" #include "../Common/ArchiveOpenCallback.h" #ifndef Z7_NO_CRYPTO #include "../../IPassword.h" #endif #ifndef Z7_SFX #include "IFolder.h" #endif #include "ProgressDialog2.h" #ifdef Z7_LANG // #include "LangUtils.h" #endif #ifndef Z7_SFX class CGrowBuf { Byte *_items; size_t _size; Z7_CLASS_NO_COPY(CGrowBuf) public: bool ReAlloc_KeepData(size_t newSize, size_t keepSize) { void *buf = MyAlloc(newSize); if (!buf) return false; if (keepSize != 0) memcpy(buf, _items, keepSize); MyFree(_items); _items = (Byte *)buf; _size = newSize; return true; } CGrowBuf(): _items(NULL), _size(0) {} ~CGrowBuf() { MyFree(_items); } operator Byte *() { return _items; } operator const Byte *() const { return _items; } size_t Size() const { return _size; } }; struct CVirtFile { CGrowBuf Data; UInt64 Size; // real size UInt64 ExpectedSize; // the size from props request. 0 if unknown UString Name; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool AttribDefined; bool IsDir; bool IsAltStream; DWORD Attrib; FILETIME CTime; FILETIME ATime; FILETIME MTime; CVirtFile(): CTimeDefined(false), ATimeDefined(false), MTimeDefined(false), AttribDefined(false), IsDir(false), IsAltStream(false) {} }; Z7_CLASS_IMP_NOQIB_1( CVirtFileSystem, ISequentialOutStream ) UInt64 _totalAllocSize; size_t _pos; unsigned _numFlushed; bool _fileIsOpen; bool _fileMode; CMyComPtr2 _outFileStream; public: CObjectVector Files; UInt64 MaxTotalAllocSize; FString DirPrefix; CByteBuffer ZoneBuf; CVirtFile &AddNewFile() { if (!Files.IsEmpty()) { MaxTotalAllocSize -= Files.Back().Data.Size(); } return Files.AddNew(); } HRESULT CloseMemFile() { if (_fileMode) { return FlushToDisk(true); } CVirtFile &file = Files.Back(); if (file.Data.Size() != file.Size) { file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size); } return S_OK; } bool IsStreamInMem() const { if (_fileMode) return false; if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir) return false; return true; } size_t GetMemStreamWrittenSize() const { return _pos; } CVirtFileSystem(): MaxTotalAllocSize((UInt64)0 - 1) {} void Init() { _totalAllocSize = 0; _fileMode = false; _pos = 0; _numFlushed = 0; _fileIsOpen = false; } HRESULT CloseFile(const FString &path); HRESULT FlushToDisk(bool closeLast); size_t GetPos() const { return _pos; } }; #endif class CExtractCallbackImp Z7_final: public IFolderArchiveExtractCallback, /* IExtractCallbackUI: before v23.00 : it included IFolderArchiveExtractCallback since v23.00 : it doesn't include IFolderArchiveExtractCallback */ public IExtractCallbackUI, // NON-COM interface since 23.00 public IOpenCallbackUI, // NON-COM interface public IFolderArchiveExtractCallback2, #ifndef Z7_SFX public IFolderOperationsExtractCallback, public IFolderExtractToStreamCallback, public ICompressProgressInfo, public IArchiveRequestMemoryUseCallback, #endif #ifndef Z7_NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback) Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2) #ifndef Z7_SFX Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback) Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback) Z7_COM_QI_ENTRY(ICompressProgressInfo) Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback) #endif #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY(ICryptoGetTextPassword) #endif Z7_COM_QI_END Z7_COM_ADDREF_RELEASE Z7_IFACE_IMP(IExtractCallbackUI) Z7_IFACE_IMP(IOpenCallbackUI) Z7_IFACE_COM7_IMP(IProgress) Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback) Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2) #ifndef Z7_SFX Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback) Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback) Z7_IFACE_COM7_IMP(ICompressProgressInfo) Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) #endif #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) #endif bool _needWriteArchivePath; bool _isFolder; bool _totalFilesDefined; bool _totalBytesDefined; public: bool MultiArcMode; bool ProcessAltStreams; bool StreamMode; bool ThereAreMessageErrors; bool Src_Is_IO_FS_Folder; #ifndef Z7_NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; #endif private: #ifndef Z7_SFX bool _needUpdateStat; bool _newVirtFileWasAdded; bool _isAltStream; // bool _extractMode; // bool _testMode; bool _hashStream_WasUsed; bool _curSize_Defined; bool NeedAddFile; bool _remember; bool _skipArc; #endif UString _currentArchivePath; UString _currentFilePath; UString _filePath; #ifndef Z7_SFX UInt64 _curSize; CMyComPtr2 _hashStream; IHashCalc *_hashCalc; // it's for stat in Test operation #endif public: CProgressDialog *ProgressDialog; #ifndef Z7_SFX CVirtFileSystem *VirtFileSystemSpec; CMyComPtr VirtFileSystem; UInt64 NumFolders; UInt64 NumFiles; #endif UInt32 NumArchiveErrors; NExtract::NOverwriteMode::EEnum OverwriteMode; bool YesToAll; bool TestMode; #ifndef Z7_NO_CRYPTO UString Password; #endif UString _lang_Extracting; UString _lang_Testing; UString _lang_Skipping; UString _lang_Reading; UString _lang_Empty; CExtractCallbackImp(): _totalFilesDefined(false) , _totalBytesDefined(false) , MultiArcMode(false) , ProcessAltStreams(true) , StreamMode(false) , ThereAreMessageErrors(false) , Src_Is_IO_FS_Folder(false) #ifndef Z7_NO_CRYPTO , PasswordIsDefined(false) , PasswordWasAsked(false) #endif #ifndef Z7_SFX , _remember(false) , _skipArc(false) , _hashCalc(NULL) #endif , OverwriteMode(NExtract::NOverwriteMode::kAsk) , YesToAll(false) , TestMode(false) {} ~CExtractCallbackImp(); void Init(); HRESULT SetCurrentFilePath2(const wchar_t *filePath); void AddError_Message(LPCWSTR message); void AddError_Message_ShowArcPath(LPCWSTR message); HRESULT MessageError(const char *message, const FString &path); void Add_ArchiveName_Error(); #ifndef Z7_SFX void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; } void SetHashMethods(IHashCalc *hash) { if (!hash) return; _hashStream.Create_if_Empty(); _hashStream->_hash = hash; } #endif bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; } }; #endif tmp41wklro_/CPP/7zip/UI/FileManager/FormatUtils.cpp0000444000175000001440000000110112075750565023125 0ustar nabijaczleweliusers// FormatUtils.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "FormatUtils.h" #include "LangUtils.h" UString NumberToString(UInt64 number) { wchar_t numberString[32]; ConvertUInt64ToString(number, numberString); return numberString; } UString MyFormatNew(const UString &format, const UString &argument) { UString result = format; result.Replace(L"{0}", argument); return result; } UString MyFormatNew(UINT resourceID, const UString &argument) { return MyFormatNew(LangString(resourceID), argument); } tmp41wklro_/CPP/7zip/UI/FileManager/FormatUtils.h0000444000175000001440000000054114357314620022572 0ustar nabijaczleweliusers// FormatUtils.h #ifndef ZIP7_INC_FORMAT_UTILS_H #define ZIP7_INC_FORMAT_UTILS_H #include "../../../Common/MyTypes.h" #include "../../../Common/MyString.h" UString NumberToString(UInt64 number); UString MyFormatNew(const UString &format, const UString &argument); UString MyFormatNew(UINT resourceID, const UString &argument); #endif tmp41wklro_/CPP/7zip/UI/FileManager/LangUtils.h0000444000175000001440000000255214443534600022225 0ustar nabijaczleweliusers// LangUtils.h #ifndef ZIP7_INC_LANG_UTILS_H #define ZIP7_INC_LANG_UTILS_H #include "../../../Common/Lang.h" #include "../../../Windows/ResourceString.h" extern UString g_LangID; extern CLang g_Lang; #ifdef Z7_LANG struct CIDLangPair { UInt32 ControlID; UInt32 LangID; }; void ReloadLang(); void LoadLangOneTime(); void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID); void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems); void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems); void LangSetDlgItems_RemoveColon(HWND dialog, const UInt32 *ids, unsigned numItems); void LangSetWindowText(HWND window, UInt32 langID); UString LangString(UInt32 langID); void AddLangString(UString &s, UInt32 langID); void LangString(UInt32 langID, UString &dest); void LangString_OnlyFromLangFile(UInt32 langID, UString &dest); #else inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); } inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); } inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); } #endif FString GetLangDirPrefix(); // bool LangOpen(CLang &lang, CFSTR fileName); void Lang_GetShortNames_for_DefaultLang(AStringVector &names, unsigned &subLang); #endif tmp41wklro_/CPP/7zip/UI/FileManager/MyWindowsNew.h0000444000175000001440000000672214415751240022740 0ustar nabijaczleweliusers// MyWindowsNew.h #ifndef ZIP7_INC_MY_WINDOWS_NEW_H #define ZIP7_INC_MY_WINDOWS_NEW_H #if defined(__MINGW32__) || defined(__MINGW64__) || defined(__MINGW32_VERSION) #include #if defined(__MINGW32_VERSION) && !defined(__ITaskbarList3_INTERFACE_DEFINED__) // for old mingw extern "C" { DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF); DEFINE_GUID(CLSID_TaskbarList, 0x56fdf344, 0xfd6d, 0x11d0, 0x95,0x8a, 0x00,0x60,0x97,0xc9,0xa0,0x90); } #endif #else // is not __MINGW* #ifndef Z7_OLD_WIN_SDK #include #else #ifndef HIMAGELIST struct _IMAGELIST; typedef struct _IMAGELIST* HIMAGELIST; #endif #ifndef __ITaskbarList_INTERFACE_DEFINED__ #define __ITaskbarList_INTERFACE_DEFINED__ DEFINE_GUID(IID_ITaskbarList, 0x56FDF342, 0xFD6D, 0x11d0, 0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90); struct ITaskbarList: public IUnknown { STDMETHOD(HrInit)(void) = 0; STDMETHOD(AddTab)(HWND hwnd) = 0; STDMETHOD(DeleteTab)(HWND hwnd) = 0; STDMETHOD(ActivateTab)(HWND hwnd) = 0; STDMETHOD(SetActiveAlt)(HWND hwnd) = 0; }; #endif // __ITaskbarList_INTERFACE_DEFINED__ #ifndef __ITaskbarList2_INTERFACE_DEFINED__ #define __ITaskbarList2_INTERFACE_DEFINED__ DEFINE_GUID(IID_ITaskbarList2, 0x602D4995, 0xB13A, 0x429b, 0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17); struct ITaskbarList2: public ITaskbarList { STDMETHOD(MarkFullscreenWindow)(HWND hwnd, BOOL fFullscreen) = 0; }; #endif // __ITaskbarList2_INTERFACE_DEFINED__ #endif // Z7_OLD_WIN_SDK #ifndef __ITaskbarList3_INTERFACE_DEFINED__ #define __ITaskbarList3_INTERFACE_DEFINED__ typedef enum THUMBBUTTONFLAGS { THBF_ENABLED = 0, THBF_DISABLED = 0x1, THBF_DISMISSONCLICK = 0x2, THBF_NOBACKGROUND = 0x4, THBF_HIDDEN = 0x8, THBF_NONINTERACTIVE = 0x10 } THUMBBUTTONFLAGS; typedef enum THUMBBUTTONMASK { THB_BITMAP = 0x1, THB_ICON = 0x2, THB_TOOLTIP = 0x4, THB_FLAGS = 0x8 } THUMBBUTTONMASK; // #include typedef struct THUMBBUTTON { THUMBBUTTONMASK dwMask; UINT iId; UINT iBitmap; HICON hIcon; WCHAR szTip[260]; THUMBBUTTONFLAGS dwFlags; } THUMBBUTTON; typedef struct THUMBBUTTON *LPTHUMBBUTTON; typedef enum TBPFLAG { TBPF_NOPROGRESS = 0, TBPF_INDETERMINATE = 0x1, TBPF_NORMAL = 0x2, TBPF_ERROR = 0x4, TBPF_PAUSED = 0x8 } TBPFLAG; DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF); struct ITaskbarList3: public ITaskbarList2 { STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0; STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0; STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0; STDMETHOD(UnregisterTab)(HWND hwndTab) = 0; STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0; STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0; STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0; STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0; STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0; STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0; STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0; STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0; }; #endif // __ITaskbarList3_INTERFACE_DEFINED__ #endif // __MINGW* #endif tmp41wklro_/CPP/7zip/UI/FileManager/OverwriteDialog.cpp0000444000175000001440000002006714642671120023765 0ustar nabijaczleweliusers// OverwriteDialog.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/PropVariantConv.h" #include "../../../Windows/ResourceString.h" #include "../../../Windows/Control/Static.h" #include "FormatUtils.h" #include "LangUtils.h" #include "OverwriteDialog.h" #include "PropertyNameRes.h" using namespace NWindows; #ifdef Z7_LANG static const UInt32 kLangIDs[] = { IDT_OVERWRITE_HEADER, IDT_OVERWRITE_QUESTION_BEGIN, IDT_OVERWRITE_QUESTION_END, IDB_YES_TO_ALL, IDB_NO_TO_ALL, IDB_AUTO_RENAME }; #endif static const unsigned kCurrentFileNameSizeLimit = 72; void COverwriteDialog::ReduceString(UString &s) { const unsigned size = #ifdef UNDER_CE !_isBig ? 30 : // kCurrentFileNameSizeLimit2 #endif kCurrentFileNameSizeLimit; if (s.Len() > size) { s.Delete(size / 2, s.Len() - size); s.Insert(size / 2, L" ... "); } if (!s.IsEmpty() && s.Back() == ' ') { // s += (wchar_t)(0x2423); // visible space s.InsertAtFront(L'\"'); s.Add_Char('\"'); } } void COverwriteDialog::SetItemIcon(unsigned iconID, HICON hIcon) { NControl::CStatic staticContol; staticContol.Attach(GetItem(iconID)); hIcon = staticContol.SetIcon(hIcon); if (hIcon) DestroyIcon(hIcon); } void AddSizeValue(UString &s, UInt64 value); void AddSizeValue(UString &s, UInt64 value) { { wchar_t sz[32]; ConvertUInt64ToString(value, sz); s += MyFormatNew(IDS_FILE_SIZE, sz); } if (value >= (1 << 10)) { char c; if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; } else if (value >= (10 << 20)) { value >>= 20; c = 'M'; } else { value >>= 10; c = 'K'; } s += " : "; s.Add_UInt64(value); s.Add_Space(); s.Add_Char(c); s += "iB"; } } void COverwriteDialog::SetFileInfoControl( const NOverwriteDialog::CFileInfo &fileInfo, unsigned textID, unsigned iconID, unsigned iconID_2) { { const UString &path = fileInfo.Path; const int slashPos = path.ReverseFind_PathSepar(); UString s = path.Left((unsigned)(slashPos + 1)); ReduceString(s); s.Add_LF(); { UString s2 = path.Ptr((unsigned)(slashPos + 1)); ReduceString(s2); s += s2; } s.Add_LF(); if (fileInfo.Size_IsDefined) AddSizeValue(s, fileInfo.Size); s.Add_LF(); if (fileInfo.Time_IsDefined) { AddLangString(s, IDS_PROP_MTIME); s += ": "; char t[64]; ConvertUtcFileTimeToString(fileInfo.Time, t); s += t; } SetItemText(textID, s); } /* SHGetFileInfo(): DOCs: If uFlags does not contain SHGFI_EXETYPE or SHGFI_SYSICONINDEX, the return value is nonzero if successful, or zero otherwise. We don't use SHGFI_EXETYPE or SHGFI_SYSICONINDEX here. win10: we call with SHGFI_ICON flag set. it returns 0: if error : (shFileInfo::*) members are not set. it returns non_0, if successful, and retrieve: { shFileInfo.hIcon != NULL : the handle to icon (must be destroyed by our code) shFileInfo.iIcon is index of the icon image within the system image list. } Note: If we send path to ".exe" file, SHGFI_USEFILEATTRIBUTES flag is ignored, and it tries to open file. and return icon from that exe file. So we still need to reduce path, if want to get raw icon of exe file. if (name.Len() >= MAX_PATH)) { it can return: return 0. return 1 and: { shFileInfo.hIcon != NULL : is some default icon for file shFileInfo.iIcon == 0 } return results (0 or 1) can depend from: - unicode/non-unicode - (SHGFI_USEFILEATTRIBUTES) flag - exact file extension (.exe). } */ int iconIndex = -1; for (unsigned i = 0; i < 2; i++) { CSysString name = GetSystemString(fileInfo.Path); if (i != 0) { if (!fileInfo.Is_FileSystemFile) break; if (name.Len() < 4 || (!StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".exe") && !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".ico"))) break; // if path for ".exe" file is long, it returns default icon (shFileInfo.iIcon == 0). // We don't want to show that default icon. // But we will check for default icon later instead of MAX_PATH check here. // if (name.Len() >= MAX_PATH) break; // optional } else { // we need only file extension with dot const int separ = name.ReverseFind_PathSepar(); name.DeleteFrontal((unsigned)(separ + 1)); // if (name.Len() >= MAX_PATH) { const int dot = name.ReverseFind_Dot(); if (dot >= 0) name.DeleteFrontal((unsigned)dot); // else name.Empty(); to set default name below } // name.Empty(); // for debug } if (name.IsEmpty()) { // If we send empty name, SHGetFileInfo() returns some strange icon. // So we use common dummy name without extension, // and SHGetFileInfo() will return default icon (iIcon == 0) name = "__file__"; } DWORD attrib = FILE_ATTRIBUTE_ARCHIVE; if (fileInfo.Is_FileSystemFile) { NFile::NFind::CFileInfo fi; if (fi.Find(us2fs(fileInfo.Path)) && !fi.IsAltStream && !fi.IsDir()) attrib = fi.Attrib; } SHFILEINFO shFileInfo; // ZeroMemory(&shFileInfo, sizeof(shFileInfo)); // optional shFileInfo.hIcon = NULL; // optional shFileInfo.iIcon = -1; // optional // memset(&shFileInfo, 1, sizeof(shFileInfo)); // for debug const DWORD_PTR res = ::SHGetFileInfo(name, attrib, &shFileInfo, sizeof(shFileInfo), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SHELLICONSIZE | // (i == 0 ? SHGFI_USEFILEATTRIBUTES : 0) SHGFI_USEFILEATTRIBUTES // we use SHGFI_USEFILEATTRIBUTES for second icon, because // it still returns real icon from exe files ); if (res && shFileInfo.hIcon) { // we don't show second icon, if icon index (iIcon) is same // as first icon index of first shown icon (exe file without icon) if ( shFileInfo.iIcon >= 0 && shFileInfo.iIcon != iconIndex && (shFileInfo.iIcon != 0 || i == 0)) // we don't want default icon for second icon { iconIndex = shFileInfo.iIcon; SetItemIcon(i == 0 ? iconID : iconID_2, shFileInfo.hIcon); } else DestroyIcon(shFileInfo.hIcon); } } } bool COverwriteDialog::OnInit() { #ifdef Z7_LANG LangSetWindowText(*this, IDD_OVERWRITE); LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs)); #endif SetFileInfoControl(OldFileInfo, IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, IDI_OVERWRITE_OLD_FILE_2); SetFileInfoControl(NewFileInfo, IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, IDI_OVERWRITE_NEW_FILE_2); NormalizePosition(); if (!ShowExtraButtons) { HideItem(IDB_YES_TO_ALL); HideItem(IDB_NO_TO_ALL); HideItem(IDB_AUTO_RENAME); } if (DefaultButton_is_NO) { PostMsg(DM_SETDEFID, IDNO); HWND h = GetItem(IDNO); PostMsg(WM_NEXTDLGCTL, (WPARAM)h, TRUE); // ::SetFocus(h); } return CModalDialog::OnInit(); } bool COverwriteDialog::OnDestroy() { SetItemIcon(IDI_OVERWRITE_OLD_FILE, NULL); SetItemIcon(IDI_OVERWRITE_OLD_FILE_2, NULL); SetItemIcon(IDI_OVERWRITE_NEW_FILE, NULL); SetItemIcon(IDI_OVERWRITE_NEW_FILE_2, NULL); return false; // we return (false) to perform default dialog operation } bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { case IDYES: case IDNO: case IDB_YES_TO_ALL: case IDB_NO_TO_ALL: case IDB_AUTO_RENAME: End((INT_PTR)buttonID); return true; } return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } tmp41wklro_/CPP/7zip/UI/FileManager/OverwriteDialog.h0000444000175000001440000000362714641676720023447 0ustar nabijaczleweliusers// OverwriteDialog.h #ifndef ZIP7_INC_OVERWRITE_DIALOG_H #define ZIP7_INC_OVERWRITE_DIALOG_H #include "../../../Windows/Control/Dialog.h" #include "DialogSize.h" #include "OverwriteDialogRes.h" namespace NOverwriteDialog { struct CFileInfo { bool Size_IsDefined; bool Time_IsDefined; bool Is_FileSystemFile; UInt64 Size; FILETIME Time; UString Path; void SetTime(const FILETIME &t) { Time = t; Time_IsDefined = true; } void SetTime2(const FILETIME *t) { if (!t) Time_IsDefined = false; else SetTime(*t); } void SetSize(UInt64 size) { Size = size; Size_IsDefined = true; } void SetSize2(const UInt64 *size) { if (!size) Size_IsDefined = false; else SetSize(*size); } CFileInfo(): Size_IsDefined(false), Time_IsDefined(false), Is_FileSystemFile(false) {} }; } class COverwriteDialog: public NWindows::NControl::CModalDialog { #ifdef UNDER_CE bool _isBig; #endif void SetItemIcon(unsigned iconID, HICON hIcon); void SetFileInfoControl(const NOverwriteDialog::CFileInfo &fileInfo, unsigned textID, unsigned iconID, unsigned iconID_2); virtual bool OnInit() Z7_override; virtual bool OnDestroy() Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; void ReduceString(UString &s); public: bool ShowExtraButtons; bool DefaultButton_is_NO; NOverwriteDialog::CFileInfo OldFileInfo; NOverwriteDialog::CFileInfo NewFileInfo; COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {} INT_PTR Create(HWND parent = NULL) { #ifdef UNDER_CE BIG_DIALOG_SIZE(280, 200); _isBig = isBig; #endif return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent); } }; #endif tmp41wklro_/CPP/7zip/UI/FileManager/OverwriteDialog.rc0000444000175000001440000000554714641705740023622 0ustar nabijaczleweliusers#include "OverwriteDialogRes.h" #include "../../GuiCommon.rc" #define xc 340 #define yc 200 #undef iconSize #define iconSize 24 #undef x #undef fx #undef fy #define x (m + iconSize + m) #define fx (xc - iconSize - m) #define fy 50 #define bSizeBig 104 #undef bx1 #define bx1 (xs - m - bSizeBig) IDD_OVERWRITE DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Confirm File Replace" BEGIN LTEXT "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8 LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8 ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize ICON "", IDI_OVERWRITE_OLD_FILE_2, m, 44 + iconSize, iconSize, iconSize LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8 ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize ICON "", IDI_OVERWRITE_NEW_FILE_2, m, 114 + iconSize, iconSize, iconSize LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bSizeBig, bys PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys PUSHBUTTON "&Cancel", IDCANCEL, xs - m - bxs, by1, bxs, bys END #ifdef UNDER_CE #undef m #undef xc #undef yc #define m 4 #define xc 152 #define yc 144 #undef fy #define fy 40 #undef bxs #define bxs 48 #undef bx1 #define bx1 (xs - m - bxs) IDD_OVERWRITE_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Confirm File Replace" BEGIN LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8 ICON "", IDI_OVERWRITE_OLD_FILE, m, 20, iconSize, iconSize LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 60, xc, 8 ICON "", IDI_OVERWRITE_NEW_FILE, m, 72, iconSize, iconSize LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bxs, bys PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys END #endif STRINGTABLE BEGIN IDS_FILE_SIZE "{0} bytes" END tmp41wklro_/CPP/7zip/UI/FileManager/OverwriteDialogRes.h0000444000175000001440000000123414641525340024100 0ustar nabijaczleweliusers#define IDD_OVERWRITE 3500 #define IDD_OVERWRITE_2 13500 #define IDT_OVERWRITE_HEADER 3501 #define IDT_OVERWRITE_QUESTION_BEGIN 3502 #define IDT_OVERWRITE_QUESTION_END 3503 #define IDS_FILE_SIZE 3504 #define IDB_AUTO_RENAME 3505 #define IDB_YES_TO_ALL 440 #define IDB_NO_TO_ALL 441 #define IDI_OVERWRITE_OLD_FILE 100 #define IDI_OVERWRITE_OLD_FILE_2 101 #define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102 #define IDI_OVERWRITE_NEW_FILE 110 #define IDI_OVERWRITE_NEW_FILE_2 111 #define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 112 tmp41wklro_/CPP/7zip/UI/FileManager/PasswordDialog.cpp0000444000175000001440000000223714401407000023563 0ustar nabijaczleweliusers// PasswordDialog.cpp #include "StdAfx.h" #include "PasswordDialog.h" #ifdef Z7_LANG #include "LangUtils.h" #endif #ifdef Z7_LANG static const UInt32 kLangIDs[] = { IDT_PASSWORD_ENTER, IDX_PASSWORD_SHOW }; #endif void CPasswordDialog::ReadControls() { _passwordEdit.GetText(Password); ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW); } void CPasswordDialog::SetTextSpec() { _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*')); _passwordEdit.SetText(Password); } bool CPasswordDialog::OnInit() { #ifdef Z7_LANG LangSetWindowText(*this, IDD_PASSWORD); LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs)); #endif _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD)); CheckButton(IDX_PASSWORD_SHOW, ShowPassword); SetTextSpec(); return CModalDialog::OnInit(); } bool CPasswordDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { if (buttonID == IDX_PASSWORD_SHOW) { ReadControls(); SetTextSpec(); return true; } return CDialog::OnButtonClicked(buttonID, buttonHWND); } void CPasswordDialog::OnOK() { ReadControls(); CModalDialog::OnOK(); } tmp41wklro_/CPP/7zip/UI/FileManager/PasswordDialog.h0000444000175000001440000000136614365270260023251 0ustar nabijaczleweliusers// PasswordDialog.h #ifndef ZIP7_INC_PASSWORD_DIALOG_H #define ZIP7_INC_PASSWORD_DIALOG_H #include "../../../Windows/Control/Dialog.h" #include "../../../Windows/Control/Edit.h" #include "PasswordDialogRes.h" class CPasswordDialog: public NWindows::NControl::CModalDialog { NWindows::NControl::CEdit _passwordEdit; virtual void OnOK() Z7_override; virtual bool OnInit() Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; void SetTextSpec(); void ReadControls(); public: UString Password; bool ShowPassword; CPasswordDialog(): ShowPassword(false) {} INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); } }; #endif tmp41wklro_/CPP/7zip/UI/FileManager/PasswordDialog.rc0000444000175000001440000000074514572012160023417 0ustar nabijaczleweliusers#include "PasswordDialogRes.h" #include "../../GuiCommon.rc" #ifdef UNDER_CE #define xc 140 #else #define xc 200 #endif #define yc 72 IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Enter password" BEGIN LTEXT "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8 EDITTEXT IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10 OK_CANCEL END tmp41wklro_/CPP/7zip/UI/FileManager/PasswordDialogRes.h0000444000175000001440000000021411561141372023706 0ustar nabijaczleweliusers#define IDD_PASSWORD 3800 #define IDT_PASSWORD_ENTER 3801 #define IDX_PASSWORD_SHOW 3803 #define IDE_PASSWORD_PASSWORD 120 tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog.cpp0000444000175000001440000001002314406036260023570 0ustar nabijaczleweliusers// ProgressDialog.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "resource.h" #include "ProgressDialog.h" using namespace NWindows; extern HINSTANCE g_hInstance; static const UINT_PTR kTimerID = 3; static const UINT kTimerElapse = 100; #ifdef Z7_LANG #include "LangUtils.h" #endif HRESULT CProgressSync::ProcessStopAndPause() { for (;;) { if (GetStopped()) return E_ABORT; if (!GetPaused()) break; ::Sleep(100); } return S_OK; } #ifndef Z7_SFX CProgressDialog::~CProgressDialog() { AddToTitle(L""); } void CProgressDialog::AddToTitle(LPCWSTR s) { if (MainWindow != 0) MySetWindowText(MainWindow, UString(s) + MainTitle); } #endif #define UNDEFINED_VAL ((UInt64)(Int64)-1) bool CProgressDialog::OnInit() { _range = UNDEFINED_VAL; _prevPercentValue = UNDEFINED_VAL; _wasCreated = true; _dialogCreatedEvent.Set(); #ifdef Z7_LANG LangSetDlgItems(*this, NULL, 0); #endif m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); if (IconID >= 0) { HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID)); SetIcon(ICON_BIG, icon); } _timer = SetTimer(kTimerID, kTimerElapse); SetText(_title); CheckNeedClose(); return CModalDialog::OnInit(); } void CProgressDialog::OnCancel() { Sync.SetStopped(true); } void CProgressDialog::OnOK() { } void CProgressDialog::SetRange(UInt64 range) { _range = range; _peviousPos = (UInt64)(Int64)-1; _converter.Init(range); m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100% } void CProgressDialog::SetPos(UInt64 pos) { bool redraw = true; if (pos < _range && pos > _peviousPos) { UInt64 posDelta = pos - _peviousPos; if (posDelta < (_range >> 10)) redraw = false; } if (redraw) { m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100% _peviousPos = pos; } } bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { if (Sync.GetPaused()) return true; CheckNeedClose(); UInt64 total, completed; Sync.GetProgress(total, completed); if (total != _range) SetRange(total); SetPos(completed); if (total == 0) total = 1; const UInt64 percentValue = completed * 100 / total; if (percentValue != _prevPercentValue) { wchar_t s[64]; ConvertUInt64ToString(percentValue, s); UString title = s; title += "% "; SetText(title + _title); #ifndef Z7_SFX AddToTitle(title + MainAddTitle); #endif _prevPercentValue = percentValue; } return true; } bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case kCloseMessage: { if (_timer) { KillTimer(kTimerID); _timer = 0; } if (_inCancelMessageBox) { _externalCloseMessageWasReceived = true; break; } return OnExternalCloseMessage(); } /* case WM_SETTEXT: { if (_timer == 0) return true; } */ } return CModalDialog::OnMessage(message, wParam, lParam); } bool CProgressDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { case IDCANCEL: { bool paused = Sync.GetPaused(); Sync.SetPaused(true); _inCancelMessageBox = true; int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL); _inCancelMessageBox = false; Sync.SetPaused(paused); if (res == IDCANCEL || res == IDNO) { if (_externalCloseMessageWasReceived) OnExternalCloseMessage(); return true; } break; } } return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } void CProgressDialog::CheckNeedClose() { if (_needClose) { PostMsg(kCloseMessage); _needClose = false; } } bool CProgressDialog::OnExternalCloseMessage() { End(0); return true; } tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog.h0000444000175000001440000000772414406117440023253 0ustar nabijaczleweliusers// ProgressDialog.h #ifndef ZIP7_INC_PROGRESS_DIALOG_H #define ZIP7_INC_PROGRESS_DIALOG_H #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #include "../../../Windows/Control/Dialog.h" #include "../../../Windows/Control/ProgressBar.h" #include "ProgressDialogRes.h" class CProgressSync { NWindows::NSynchronization::CCriticalSection _cs; bool _stopped; bool _paused; UInt64 _total; UInt64 _completed; public: CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {} HRESULT ProcessStopAndPause(); bool GetStopped() { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _stopped; } void SetStopped(bool value) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _stopped = value; } bool GetPaused() { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _paused; } void SetPaused(bool value) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _paused = value; } void SetProgress(UInt64 total, UInt64 completed) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _total = total; _completed = completed; } void SetPos(UInt64 completed) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _completed = completed; } void GetProgress(UInt64 &total, UInt64 &completed) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); total = _total; completed = _completed; } }; class CU64ToI32Converter { UInt64 _numShiftBits; public: void Init(UInt64 range) { // Windows CE doesn't like big number here. for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++) range >>= 1; } int Count(UInt64 value) { return int(value >> _numShiftBits); } }; class CProgressDialog: public NWindows::NControl::CModalDialog { private: UINT_PTR _timer; UString _title; CU64ToI32Converter _converter; UInt64 _peviousPos; UInt64 _range; NWindows::NControl::CProgressBar m_ProgressBar; UInt64 _prevPercentValue; bool _wasCreated; bool _needClose; bool _inCancelMessageBox; bool _externalCloseMessageWasReceived; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; virtual bool OnTimer(WPARAM timerID, LPARAM callback) Z7_override; virtual bool OnInit() Z7_override; virtual void OnCancel() Z7_override; virtual void OnOK() Z7_override; virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override; void SetRange(UInt64 range); void SetPos(UInt64 pos); NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; #ifndef Z7_SFX void AddToTitle(LPCWSTR string); #endif void WaitCreating() { _dialogCreatedEvent.Lock(); } void CheckNeedClose(); bool OnExternalCloseMessage(); public: CProgressSync Sync; int IconID; #ifndef Z7_SFX HWND MainWindow; UString MainTitle; UString MainAddTitle; ~CProgressDialog(); #endif CProgressDialog(): _timer(0) #ifndef Z7_SFX ,MainWindow(NULL) #endif { IconID = -1; _wasCreated = false; _needClose = false; _inCancelMessageBox = false; _externalCloseMessageWasReceived = false; if (_dialogCreatedEvent.Create() != S_OK) throw 1334987; } INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL) { _title = title; INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent); thread.Wait_Close(); return res; } enum { kCloseMessage = WM_APP + 1 }; void ProcessWasFinished() { WaitCreating(); if (_wasCreated) PostMsg(kCloseMessage); else _needClose = true; } }; class CProgressCloser { CProgressDialog *_p; public: CProgressCloser(CProgressDialog &p) : _p(&p) {} ~CProgressCloser() { _p->ProcessWasFinished(); } }; #endif tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog.rc0000444000175000001440000000053711573616744023440 0ustar nabijaczleweliusers#include "ProgressDialogRes.h" #include "../../GuiCommon.rc" #define xc 172 #define yc 44 IDD_PROGRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Progress" BEGIN PUSHBUTTON "Cancel", IDCANCEL, bx, by, bxs, bys CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14 END tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog2.cpp0000444000175000001440000010476514573273220023677 0ustar nabijaczleweliusers// ProgressDialog2.cpp #include "StdAfx.h" #ifdef Z7_OLD_WIN_SDK #include #endif #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/Clipboard.h" #include "../../../Windows/ErrorMsg.h" #include "../GUI/ExtractRes.h" #include "LangUtils.h" #include "DialogSize.h" #include "ProgressDialog2.h" #include "ProgressDialog2Res.h" using namespace NWindows; extern HINSTANCE g_hInstance; extern bool g_DisableUserQuestions; static const UINT_PTR kTimerID = 3; static const UINT kCloseMessage = WM_APP + 1; // we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog static const UINT kTimerElapse = #ifdef UNDER_CE 500 #else 200 #endif ; static const UINT kCreateDelay = #ifdef UNDER_CE 2500 #else 500 #endif ; static const DWORD kPauseSleepTime = 100; #ifdef Z7_LANG static const UInt32 kLangIDs[] = { IDT_PROGRESS_ELAPSED, IDT_PROGRESS_REMAINING, IDT_PROGRESS_TOTAL, IDT_PROGRESS_SPEED, IDT_PROGRESS_PROCESSED, IDT_PROGRESS_RATIO, IDT_PROGRESS_ERRORS, IDB_PROGRESS_BACKGROUND, IDB_PAUSE }; static const UInt32 kLangIDs_Colon[] = { IDT_PROGRESS_PACKED, IDT_PROGRESS_FILES }; #endif #define UNDEFINED_VAL ((UInt64)(Int64)-1) #define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL; #define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL) #define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL) CProgressSync::CProgressSync(): _stopped(false), _paused(false), _bytesProgressMode(true), _isDir(false), _totalBytes(UNDEFINED_VAL), _completedBytes(0), _totalFiles(UNDEFINED_VAL), _curFiles(0), _inSize(UNDEFINED_VAL), _outSize(UNDEFINED_VAL) {} #define CHECK_STOP if (_stopped) return E_ABORT; if (!_paused) return S_OK; #define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs); bool CProgressSync::Get_Paused() { CRITICAL_LOCK return _paused; } HRESULT CProgressSync::CheckStop() { for (;;) { { CRITICAL_LOCK CHECK_STOP } ::Sleep(kPauseSleepTime); } } HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir) { { CRITICAL_LOCK _totalFiles = numFiles; _totalBytes = totalSize; _filePath = fs2us(fileName); _isDir = isDir; // _completedBytes = 0; CHECK_STOP } return CheckStop(); } HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val) { { CRITICAL_LOCK _totalFiles = val; CHECK_STOP } return CheckStop(); } void CProgressSync::Set_NumBytesTotal(UInt64 val) { CRITICAL_LOCK _totalBytes = val; } void CProgressSync::Set_NumFilesCur(UInt64 val) { CRITICAL_LOCK _curFiles = val; } HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val) { { CRITICAL_LOCK if (val) _completedBytes = *val; CHECK_STOP } return CheckStop(); } HRESULT CProgressSync::Set_NumBytesCur(UInt64 val) { { CRITICAL_LOCK _completedBytes = val; CHECK_STOP } return CheckStop(); } void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize) { CRITICAL_LOCK if (inSize) _inSize = *inSize; if (outSize) _outSize = *outSize; } void CProgressSync::Set_TitleFileName(const UString &fileName) { CRITICAL_LOCK _titleFileName = fileName; } void CProgressSync::Set_Status(const UString &s) { CRITICAL_LOCK _status = s; } HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir) { { CRITICAL_LOCK _status = s; if (path) _filePath = path; else _filePath.Empty(); _isDir = isDir; } return CheckStop(); } void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir) { CRITICAL_LOCK if (path) _filePath = path; else _filePath.Empty(); _isDir = isDir; } void CProgressSync::AddError_Message(const wchar_t *message) { CRITICAL_LOCK Messages.Add(message); } void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name) { UString s; if (name && *name != 0) s += name; if (message && *message != 0) { if (!s.IsEmpty()) s.Add_LF(); s += message; if (!s.IsEmpty() && s.Back() == L'\n') s.DeleteBack(); } AddError_Message(s); } void CProgressSync::AddError_Code_Name(HRESULT systemError, const wchar_t *name) { UString s = NError::MyFormatMessage(systemError); if (systemError == 0) s = "Error"; AddError_Message_Name(s, name); } CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true), MainWindow(NULL) { _isDir = false; _numMessages = 0; IconID = -1; MessagesDisplayed = false; _wasCreated = false; _needClose = false; _inCancelMessageBox = false; _externalCloseMessageWasReceived = false; _numPostedMessages = 0; _numAutoSizeMessages = 0; _errorsWereDisplayed = false; _waitCloseByCancelButton = false; _cancelWasPressed = false; ShowCompressionInfo = true; WaitMode = false; if (_dialogCreatedEvent.Create() != S_OK) throw 1334987; if (_createDialogEvent.Create() != S_OK) throw 1334987; // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList); if (_taskbarList) _taskbarList->HrInit(); // #endif } #ifndef Z7_SFX CProgressDialog::~CProgressDialog() { // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ SetTaskbarProgressState(TBPF_NOPROGRESS); // #endif AddToTitle(L""); } void CProgressDialog::AddToTitle(LPCWSTR s) { if (MainWindow) { CWindow window(MainWindow); window.SetText((UString)s + MainTitle); } } #endif void CProgressDialog::SetTaskbarProgressState() { // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ if (_taskbarList && _hwndForTaskbar) { TBPFLAG tbpFlags; if (Sync.Get_Paused()) tbpFlags = TBPF_PAUSED; else tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL; SetTaskbarProgressState(tbpFlags); } // #endif } static const unsigned kTitleFileNameSizeLimit = 36; static const unsigned kCurrentFileNameSizeLimit = 82; static void ReduceString(UString &s, unsigned size) { if (s.Len() <= size) return; s.Delete(size / 2, s.Len() - size); s.Insert(size / 2, L" ... "); } void CProgressDialog::EnableErrorsControls(bool enable) { ShowItem_Bool(IDT_PROGRESS_ERRORS, enable); ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable); ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable); } bool CProgressDialog::OnInit() { _hwndForTaskbar = MainWindow; if (!_hwndForTaskbar) _hwndForTaskbar = GetParent(); if (!_hwndForTaskbar) _hwndForTaskbar = *this; INIT_AS_UNDEFINED(_progressBar_Range) INIT_AS_UNDEFINED(_progressBar_Pos) INIT_AS_UNDEFINED(_prevPercentValue) INIT_AS_UNDEFINED(_prevElapsedSec) INIT_AS_UNDEFINED(_prevRemainingSec) INIT_AS_UNDEFINED(_prevSpeed) _prevSpeed_MoveBits = 0; _prevTime = ::GetTickCount(); _elapsedTime = 0; INIT_AS_UNDEFINED(_totalBytes_Prev) INIT_AS_UNDEFINED(_processed_Prev) INIT_AS_UNDEFINED(_packed_Prev) INIT_AS_UNDEFINED(_ratio_Prev) _filesStr_Prev.Empty(); _filesTotStr_Prev.Empty(); _foreground = true; m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES)); _messageList.SetUnicodeFormat(); _messageList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); _wasCreated = true; _dialogCreatedEvent.Set(); #ifdef Z7_LANG LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs)); LangSetDlgItems_Colon(*this, kLangIDs_Colon, Z7_ARRAY_SIZE(kLangIDs_Colon)); #endif CWindow window(GetItem(IDB_PROGRESS_BACKGROUND)); window.GetText(_background_String); _backgrounded_String = _background_String; _backgrounded_String.RemoveChar(L'&'); window = GetItem(IDB_PAUSE); window.GetText(_pause_String); LangString(IDS_PROGRESS_FOREGROUND, _foreground_String); LangString(IDS_CONTINUE, _continue_String); LangString(IDS_PROGRESS_PAUSED, _paused_String); SetText(_title); SetPauseText(); SetPriorityText(); _messageList.InsertColumn(0, L"", 30); _messageList.InsertColumn(1, L"", 600); _messageList.SetColumnWidthAuto(0); _messageList.SetColumnWidthAuto(1); EnableErrorsControls(false); GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY); _numReduceSymbols = kCurrentFileNameSizeLimit; NormalizeSize(true); if (!ShowCompressionInfo) { HideItem(IDT_PROGRESS_PACKED); HideItem(IDT_PROGRESS_PACKED_VAL); HideItem(IDT_PROGRESS_RATIO); HideItem(IDT_PROGRESS_RATIO_VAL); } if (IconID >= 0) { HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID)); // SetIcon(ICON_SMALL, icon); SetIcon(ICON_BIG, icon); } _timer = SetTimer(kTimerID, kTimerElapse); #ifdef UNDER_CE Foreground(); #endif CheckNeedClose(); SetTaskbarProgressState(); return CModalDialog::OnInit(); } static const UINT kIDs[] = { IDT_PROGRESS_ELAPSED, IDT_PROGRESS_ELAPSED_VAL, IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL, IDT_PROGRESS_FILES, IDT_PROGRESS_FILES_VAL, 0, IDT_PROGRESS_FILES_TOTAL, IDT_PROGRESS_ERRORS, IDT_PROGRESS_ERRORS_VAL, IDT_PROGRESS_TOTAL, IDT_PROGRESS_TOTAL_VAL, IDT_PROGRESS_SPEED, IDT_PROGRESS_SPEED_VAL, IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL, IDT_PROGRESS_PACKED, IDT_PROGRESS_PACKED_VAL, IDT_PROGRESS_RATIO, IDT_PROGRESS_RATIO_VAL }; bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) { int sY; int sStep; int mx, my; { RECT r; GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r); mx = r.left; my = r.top; sY = RECT_SIZE_Y(r); GetClientRectOfItem(IDT_PROGRESS_REMAINING, r); sStep = r.top - my; } InvalidateRect(NULL); const int xSizeClient = xSize - mx * 2; { unsigned i; for (i = 800; i > 40; i = i * 9 / 10) if (Units_To_Pixels_X((int)i) <= xSizeClient) break; _numReduceSymbols = i / 4; } int yPos = ySize - my - _buttonSizeY; ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2); ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2); ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2); int bSizeX = _buttonSizeX; int mx2 = mx; for (;; mx2--) { const int bSize2 = bSizeX * 3 + mx2 * 2; if (bSize2 <= xSizeClient) break; if (mx2 < 5) { bSizeX = (xSizeClient - mx2 * 2) / 3; break; } } if (bSizeX < 2) bSizeX = 2; { RECT r; GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r); const int y = r.top; int ySize2 = yPos - my - y; const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4; int xx = xSize - mx * 2; if (ySize2 < kMinYSize) { ySize2 = kMinYSize; if (xx > bSizeX * 2) xx -= bSizeX; } _messageList.Move(mx, y, xx, ySize2); } { int xPos = xSize - mx; xPos -= bSizeX; MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY); xPos -= (mx2 + bSizeX); MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY); xPos -= (mx2 + bSizeX); MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY); } int valueSize; int labelSize; int padSize; labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN); valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS); padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS); const int requiredSize = (labelSize + valueSize) * 2 + padSize; int gSize; { if (requiredSize < xSizeClient) { const int incr = (xSizeClient - requiredSize) / 3; labelSize += incr; } else labelSize = (xSizeClient - valueSize * 2 - padSize) / 2; if (labelSize < 0) labelSize = 0; gSize = labelSize + valueSize; padSize = xSizeClient - gSize * 2; } labelSize = gSize - valueSize; yPos = my; for (unsigned i = 0; i < Z7_ARRAY_SIZE(kIDs); i += 2) { int x = mx; const unsigned kNumColumn1Items = 5 * 2; if (i >= kNumColumn1Items) { if (i == kNumColumn1Items) yPos = my; x = mx + gSize + padSize; } if (kIDs[i] != 0) MoveItem(kIDs[i], x, yPos, labelSize, sY); MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY); yPos += sStep; } return false; } void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); } void CProgressDialog::OnOK() { } void CProgressDialog::SetProgressRange(UInt64 range) { if (range == _progressBar_Range) return; _progressBar_Range = range; INIT_AS_UNDEFINED(_progressBar_Pos) _progressConv.Init(range); m_ProgressBar.SetRange32(0, _progressConv.Count(range)); } void CProgressDialog::SetProgressPos(UInt64 pos) { if (pos >= _progressBar_Range || pos <= _progressBar_Pos || pos - _progressBar_Pos >= (_progressBar_Range >> 10)) { m_ProgressBar.SetPos(_progressConv.Count(pos)); // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ if (_taskbarList && _hwndForTaskbar) _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range); // #endif _progressBar_Pos = pos; } } #define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; } void GetTimeString(UInt64 timeValue, wchar_t *s); void GetTimeString(UInt64 timeValue, wchar_t *s) { UInt64 hours = timeValue / 3600; UInt32 seconds = (UInt32)(timeValue - hours * 3600); UInt32 minutes = seconds / 60; seconds %= 60; if (hours > 99) { ConvertUInt64ToString(hours, s); for (; *s != 0; s++); } else { UInt32 hours32 = (UInt32)hours; UINT_TO_STR_2(hours32) } *s++ = ':'; UINT_TO_STR_2(minutes) *s++ = ':'; UINT_TO_STR_2(seconds) *s = 0; } static void ConvertSizeToString(UInt64 v, wchar_t *s) { Byte c = 0; if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; } else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; } else if (v >= ((UInt64)100000 << 0)) { v >>= 10; c = 'K'; } ConvertUInt64ToString(v, s); if (c != 0) { s += MyStringLen(s); *s++ = ' '; *s++ = c; *s++ = 'B'; *s++ = 0; } } void CProgressDialog::ShowSize(unsigned id, UInt64 val, UInt64 &prev) { if (val == prev) return; prev = val; wchar_t s[40]; s[0] = 0; if (IS_DEFINED_VAL(val)) ConvertSizeToString(val, s); SetItemText(id, s); } static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged) { hasChanged = !(prevStr == newStr); if (hasChanged) prevStr = newStr; } static unsigned GetPower32(UInt32 val) { const unsigned kStart = 32; UInt32 mask = ((UInt32)1 << (kStart - 1)); for (unsigned i = kStart;; i--) { if (i == 0 || (val & mask) != 0) return i; mask >>= 1; } } static unsigned GetPower64(UInt64 val) { UInt32 high = (UInt32)(val >> 32); if (high == 0) return GetPower32((UInt32)val); return GetPower32(high) + 32; } static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) { unsigned pow1 = GetPower64(mult1); unsigned pow2 = GetPower64(mult2); while (pow1 + pow2 > 64) { if (pow1 > pow2) { pow1--; mult1 >>= 1; } else { pow2--; mult2 >>= 1; } divider >>= 1; } UInt64 res = mult1 * mult2; if (divider != 0) res /= divider; return res; } void CProgressDialog::UpdateStatInfo(bool showAll) { UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; bool bytesProgressMode; bool titleFileName_Changed; bool curFilePath_Changed; bool status_Changed; unsigned numErrors; { NSynchronization::CCriticalSectionLock lock(Sync._cs); total = Sync._totalBytes; completed = Sync._completedBytes; totalFiles = Sync._totalFiles; completedFiles = Sync._curFiles; inSize = Sync._inSize; outSize = Sync._outSize; bytesProgressMode = Sync._bytesProgressMode; GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed); GetChangedString(Sync._filePath, _filePath, curFilePath_Changed); GetChangedString(Sync._status, _status, status_Changed); if (_isDir != Sync._isDir) { curFilePath_Changed = true; _isDir = Sync._isDir; } numErrors = Sync.Messages.Size(); } UInt32 curTime = ::GetTickCount(); const UInt64 progressTotal = bytesProgressMode ? total : totalFiles; const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; { if (IS_UNDEFINED_VAL(progressTotal)) { // SetPos(0); // SetRange(progressCompleted); } else { if (_progressBar_Pos != 0 || progressCompleted != 0 || (_progressBar_Range == 0 && progressTotal != 0)) { SetProgressRange(progressTotal); SetProgressPos(progressCompleted); } } } ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev); _elapsedTime += (curTime - _prevTime); _prevTime = curTime; UInt64 elapsedSec = _elapsedTime / 1000; bool elapsedChanged = false; if (elapsedSec != _prevElapsedSec) { _prevElapsedSec = elapsedSec; elapsedChanged = true; wchar_t s[40]; GetTimeString(elapsedSec, s); SetItemText(IDT_PROGRESS_ELAPSED_VAL, s); } bool needSetTitle = false; if (elapsedChanged || showAll) { if (numErrors > _numPostedMessages) { UpdateMessagesDialog(); wchar_t s[32]; ConvertUInt64ToString(numErrors, s); SetItemText(IDT_PROGRESS_ERRORS_VAL, s); if (!_errorsWereDisplayed) { _errorsWereDisplayed = true; EnableErrorsControls(true); SetTaskbarProgressState(); } } if (progressCompleted != 0) { if (IS_UNDEFINED_VAL(progressTotal)) { if (IS_DEFINED_VAL(_prevRemainingSec)) { INIT_AS_UNDEFINED(_prevRemainingSec) SetItemText(IDT_PROGRESS_REMAINING_VAL, L""); } } else { UInt64 remainingTime = 0; if (progressCompleted < progressTotal) remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted); UInt64 remainingSec = remainingTime / 1000; if (remainingSec != _prevRemainingSec) { _prevRemainingSec = remainingSec; wchar_t s[40]; GetTimeString(remainingSec, s); SetItemText(IDT_PROGRESS_REMAINING_VAL, s); } } { const UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime; // 22.02: progressCompleted can be for number of files UInt64 v = (completed * 1000) / elapsedTime; Byte c = 0; unsigned moveBits = 0; if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; } else if (v >= ((UInt64)10000 << 0)) { moveBits = 10; c = 'K'; } v >>= moveBits; if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed) { _prevSpeed_MoveBits = moveBits; _prevSpeed = v; wchar_t s[40]; ConvertUInt64ToString(v, s); unsigned pos = MyStringLen(s); s[pos++] = ' '; if (moveBits != 0) s[pos++] = c; s[pos++] = 'B'; s[pos++] = '/'; s[pos++] = 's'; s[pos++] = 0; SetItemText(IDT_PROGRESS_SPEED_VAL, s); } } } { UInt64 percent = 0; { if (IS_DEFINED_VAL(progressTotal)) { percent = progressCompleted * 100; if (progressTotal != 0) percent /= progressTotal; } } if (percent != _prevPercentValue) { _prevPercentValue = percent; needSetTitle = true; } } { wchar_t s[64]; ConvertUInt64ToString(completedFiles, s); if (_filesStr_Prev != s) { _filesStr_Prev = s; SetItemText(IDT_PROGRESS_FILES_VAL, s); } s[0] = 0; if (IS_DEFINED_VAL(totalFiles)) { MyStringCopy(s, L" / "); ConvertUInt64ToString(totalFiles, s + MyStringLen(s)); } if (_filesTotStr_Prev != s) { _filesTotStr_Prev = s; SetItemText(IDT_PROGRESS_FILES_TOTAL, s); } } const UInt64 packSize = CompressingMode ? outSize : inSize; const UInt64 unpackSize = CompressingMode ? inSize : outSize; if (IS_UNDEFINED_VAL(unpackSize) && IS_UNDEFINED_VAL(packSize)) { ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev); ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev); } else { ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev); ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev); if (IS_DEFINED_VAL(packSize) && IS_DEFINED_VAL(unpackSize) && unpackSize != 0) { wchar_t s[32]; UInt64 ratio = packSize * 100 / unpackSize; if (_ratio_Prev != ratio) { _ratio_Prev = ratio; ConvertUInt64ToString(ratio, s); MyStringCat(s, L"%"); SetItemText(IDT_PROGRESS_RATIO_VAL, s); } } } } if (needSetTitle || titleFileName_Changed) SetTitleText(); if (status_Changed) { UString s = _status; ReduceString(s, _numReduceSymbols); SetItemText(IDT_PROGRESS_STATUS, _status); } if (curFilePath_Changed) { UString s1, s2; if (_isDir) s1 = _filePath; else { int slashPos = _filePath.ReverseFind_PathSepar(); if (slashPos >= 0) { s1.SetFrom(_filePath, (unsigned)(slashPos + 1)); s2 = _filePath.Ptr((unsigned)(slashPos + 1)); } else s2 = _filePath; } ReduceString(s1, _numReduceSymbols); ReduceString(s2, _numReduceSymbols); s1.Add_LF(); s1 += s2; SetItemText(IDT_PROGRESS_FILE_NAME, s1); } } bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { if (Sync.Get_Paused()) return true; CheckNeedClose(); UpdateStatInfo(false); return true; } struct CWaitCursor { HCURSOR _waitCursor; HCURSOR _oldCursor; CWaitCursor() { _waitCursor = LoadCursor(NULL, IDC_WAIT); if (_waitCursor != NULL) _oldCursor = SetCursor(_waitCursor); } ~CWaitCursor() { if (_waitCursor != NULL) SetCursor(_oldCursor); } }; INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent) { INT_PTR res = 0; try { if (WaitMode) { CWaitCursor waitCursor; HANDLE h[] = { thread, _createDialogEvent }; const DWORD res2 = WaitForMultipleObjects(Z7_ARRAY_SIZE(h), h, FALSE, kCreateDelay); if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage()) return 0; } _title = title; BIG_DIALOG_SIZE(360, 192); res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent); } catch(...) { _wasCreated = true; _dialogCreatedEvent.Set(); } thread.Wait_Close(); if (!MessagesDisplayed) if (!g_DisableUserQuestions) MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR); return res; } bool CProgressDialog::OnExternalCloseMessage() { // it doesn't work if there is MessageBox. // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ SetTaskbarProgressState(TBPF_NOPROGRESS); // #endif // AddToTitle(L"Finished "); // SetText(L"Finished2 "); UpdateStatInfo(true); SetItemText(IDCANCEL, LangString(IDS_CLOSE)); ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); HideItem(IDB_PROGRESS_BACKGROUND); HideItem(IDB_PAUSE); ProcessWasFinished_GuiVirt(); bool thereAreMessages; CProgressFinalMessage fm; { NSynchronization::CCriticalSectionLock lock(Sync._cs); thereAreMessages = !Sync.Messages.IsEmpty(); fm = Sync.FinalMessage; } if (!fm.ErrorMessage.Message.IsEmpty()) { MessagesDisplayed = true; if (fm.ErrorMessage.Title.IsEmpty()) fm.ErrorMessage.Title = "7-Zip"; if (!g_DisableUserQuestions) MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR); } else if (!thereAreMessages) { MessagesDisplayed = true; if (!fm.OkMessage.Message.IsEmpty()) { if (fm.OkMessage.Title.IsEmpty()) fm.OkMessage.Title = "7-Zip"; if (!g_DisableUserQuestions) MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK); } } if (!g_DisableUserQuestions) if (thereAreMessages && !_cancelWasPressed) { _waitCloseByCancelButton = true; UpdateMessagesDialog(); return true; } End(0); return true; } bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case kCloseMessage: { if (_timer) { /* 21.03 : KillTimer(kTimerID) instead of KillTimer(_timer). But (_timer == kTimerID) in Win10. So it worked too */ KillTimer(kTimerID); _timer = 0; } if (_inCancelMessageBox) { /* if user is in MessageBox(), we will call OnExternalCloseMessage() later, when MessageBox() will be closed */ _externalCloseMessageWasReceived = true; break; } return OnExternalCloseMessage(); } /* case WM_SETTEXT: { if (_timer == 0) return true; break; } */ } return CModalDialog::OnMessage(message, wParam, lParam); } void CProgressDialog::SetTitleText() { UString s; if (Sync.Get_Paused()) { s += _paused_String; s.Add_Space(); } if (IS_DEFINED_VAL(_prevPercentValue)) { char temp[32]; ConvertUInt64ToString(_prevPercentValue, temp); s += temp; s.Add_Char('%'); } if (!_foreground) { s.Add_Space(); s += _backgrounded_String; } s.Add_Space(); #ifndef Z7_SFX { unsigned len = s.Len(); s += MainAddTitle; AddToTitle(s); s.DeleteFrom(len); } #endif s += _title; if (!_titleFileName.IsEmpty()) { UString fileName = _titleFileName; ReduceString(fileName, kTitleFileNameSizeLimit); s.Add_Space(); s += fileName; } SetText(s); } void CProgressDialog::SetPauseText() { SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String); SetTitleText(); } void CProgressDialog::OnPauseButton() { bool paused = !Sync.Get_Paused(); Sync.Set_Paused(paused); UInt32 curTime = ::GetTickCount(); if (paused) _elapsedTime += (curTime - _prevTime); SetTaskbarProgressState(); _prevTime = curTime; SetPauseText(); } void CProgressDialog::SetPriorityText() { SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ? _background_String : _foreground_String); SetTitleText(); } void CProgressDialog::OnPriorityButton() { _foreground = !_foreground; #ifndef UNDER_CE SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS); #endif SetPriorityText(); } void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber) { wchar_t sz[16]; sz[0] = 0; if (needNumber) ConvertUInt32ToString(_numMessages + 1, sz); const unsigned itemIndex = _messageStrings.Size(); // _messageList.GetItemCount(); if (_messageList.InsertItem(itemIndex, sz) == (int)itemIndex) { _messageList.SetSubItem(itemIndex, 1, message); _messageStrings.Add(message); } } void CProgressDialog::AddMessage(LPCWSTR message) { UString s = message; bool needNumber = true; while (!s.IsEmpty()) { const int pos = s.Find(L'\n'); if (pos < 0) break; AddMessageDirect(s.Left((unsigned)pos), needNumber); needNumber = false; s.DeleteFrontal((unsigned)pos + 1); } AddMessageDirect(s, needNumber); _numMessages++; } static unsigned GetNumDigits(UInt32 val) { unsigned i; for (i = 0; val >= 10; i++) val /= 10; return i; } void CProgressDialog::UpdateMessagesDialog() { UStringVector messages; { NSynchronization::CCriticalSectionLock lock(Sync._cs); unsigned num = Sync.Messages.Size(); if (num > _numPostedMessages) { messages.ClearAndReserve(num - _numPostedMessages); for (unsigned i = _numPostedMessages; i < num; i++) messages.AddInReserved(Sync.Messages[i]); _numPostedMessages = num; } } if (!messages.IsEmpty()) { FOR_VECTOR (i, messages) AddMessage(messages[i]); if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages)) { _messageList.SetColumnWidthAuto(0); _messageList.SetColumnWidthAuto(1); _numAutoSizeMessages = _numPostedMessages; } } } bool CProgressDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON case IDCANCEL: { if (_waitCloseByCancelButton) { MessagesDisplayed = true; End(IDCLOSE); break; } if (_cancelWasPressed) return true; const bool paused = Sync.Get_Paused(); if (!paused) { OnPauseButton(); } _inCancelMessageBox = true; const int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL); _inCancelMessageBox = false; if (res == IDYES) _cancelWasPressed = true; if (!paused) { OnPauseButton(); } if (_externalCloseMessageWasReceived) { /* we have received kCloseMessage while we were in MessageBoxW(). so we call OnExternalCloseMessage() here. it can show MessageBox and it can close dialog */ OnExternalCloseMessage(); return true; } if (!_cancelWasPressed) return true; MessagesDisplayed = true; // we will call Sync.Set_Stopped(true) in OnButtonClicked() : OnCancel() break; } case IDB_PAUSE: OnPauseButton(); return true; case IDB_PROGRESS_BACKGROUND: OnPriorityButton(); return true; } return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } void CProgressDialog::CheckNeedClose() { if (_needClose) { PostMsg(kCloseMessage); _needClose = false; } } void CProgressDialog::ProcessWasFinished() { // Set Window title here. if (!WaitMode) WaitCreating(); if (_wasCreated) PostMsg(kCloseMessage); else _needClose = true; } bool CProgressDialog::OnNotify(UINT /* controlID */, LPNMHDR header) { if (header->hwndFrom != _messageList) return false; switch (header->code) { case LVN_KEYDOWN: { LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header); switch (keyDownInfo->wVKey) { case 'A': { if (IsKeyDown(VK_CONTROL)) { _messageList.SelectAll(); return true; } break; } case VK_INSERT: case 'C': { if (IsKeyDown(VK_CONTROL)) { CopyToClipboard(); return true; } break; } } } } return false; } static void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector) { vector.Clear(); int index = -1; for (;;) { index = listView.GetNextSelectedItem(index); if (index < 0) break; vector.Add((unsigned)index); } } void CProgressDialog::CopyToClipboard() { CUIntVector indexes; ListView_GetSelected(_messageList, indexes); UString s; unsigned numIndexes = indexes.Size(); if (numIndexes == 0) numIndexes = (unsigned)_messageList.GetItemCount(); for (unsigned i = 0; i < numIndexes; i++) { const unsigned index = (i < indexes.Size() ? indexes[i] : i); // s.Add_UInt32(index); // s += ": "; s += _messageStrings[index]; { s += #ifdef _WIN32 "\r\n" #else "\n" #endif ; } } ClipboardSetText(*this, s); } static THREAD_FUNC_DECL MyThreadFunction(void *param) { CProgressThreadVirt *p = (CProgressThreadVirt *)param; try { p->Process(); p->ThreadFinishedOK = true; } catch (...) { p->Result = E_FAIL; } return 0; } HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow) { NWindows::CThread thread; const WRes wres = thread.Create(MyThreadFunction, this); if (wres != 0) return HRESULT_FROM_WIN32(wres); CProgressDialog::Create(title, thread, parentWindow); return S_OK; } static void AddMessageToString(UString &dest, const UString &src) { if (!src.IsEmpty()) { if (!dest.IsEmpty()) dest.Add_LF(); dest += src; } } void CProgressThreadVirt::Process() { CProgressCloser closer(*this); UString m; try { Result = ProcessVirt(); } catch(const wchar_t *s) { m = s; } catch(const UString &s) { m = s; } catch(const char *s) { m = GetUnicodeString(s); } catch(int v) { m = "Error #"; m.Add_UInt32((unsigned)v); } catch(...) { m = "Error"; } if (Result != E_ABORT) { if (m.IsEmpty() && Result != S_OK) m = HResultToMessage(Result); } AddMessageToString(m, FinalMessage.ErrorMessage.Message); { FOR_VECTOR(i, ErrorPaths) { if (i >= 32) break; AddMessageToString(m, fs2us(ErrorPaths[i])); } } CProgressSync &sync = Sync; NSynchronization::CCriticalSectionLock lock(sync._cs); if (m.IsEmpty()) { if (!FinalMessage.OkMessage.Message.IsEmpty()) sync.FinalMessage.OkMessage = FinalMessage.OkMessage; } else { sync.FinalMessage.ErrorMessage.Message = m; if (Result == S_OK) Result = E_FAIL; } } UString HResultToMessage(HRESULT errorCode) { if (errorCode == E_OUTOFMEMORY) return LangString(IDS_MEM_ERROR); else return NError::MyFormatMessage(errorCode); } tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog2.h0000444000175000001440000002211314415516500023322 0ustar nabijaczleweliusers// ProgressDialog2.h #ifndef ZIP7_INC_PROGRESS_DIALOG_2_H #define ZIP7_INC_PROGRESS_DIALOG_2_H #include "../../../Common/MyCom.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #include "../../../Windows/Control/Dialog.h" #include "../../../Windows/Control/ListView.h" #include "../../../Windows/Control/ProgressBar.h" #include "MyWindowsNew.h" struct CProgressMessageBoxPair { UString Title; UString Message; }; struct CProgressFinalMessage { CProgressMessageBoxPair ErrorMessage; CProgressMessageBoxPair OkMessage; bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); } }; class CProgressSync { bool _stopped; bool _paused; public: bool _bytesProgressMode; bool _isDir; UInt64 _totalBytes; UInt64 _completedBytes; UInt64 _totalFiles; UInt64 _curFiles; UInt64 _inSize; UInt64 _outSize; UString _titleFileName; UString _status; UString _filePath; UStringVector Messages; CProgressFinalMessage FinalMessage; NWindows::NSynchronization::CCriticalSection _cs; CProgressSync(); bool Get_Stopped() { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); return _stopped; } void Set_Stopped(bool val) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _stopped = val; } bool Get_Paused(); void Set_Paused(bool val) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _paused = val; } void Set_BytesProgressMode(bool bytesProgressMode) { NWindows::NSynchronization::CCriticalSectionLock lock(_cs); _bytesProgressMode = bytesProgressMode; } HRESULT CheckStop(); HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); HRESULT Set_NumFilesTotal(UInt64 val); void Set_NumBytesTotal(UInt64 val); void Set_NumFilesCur(UInt64 val); HRESULT Set_NumBytesCur(const UInt64 *val); HRESULT Set_NumBytesCur(UInt64 val); void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize); void Set_TitleFileName(const UString &fileName); void Set_Status(const UString &s); HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false); void Set_FilePath(const wchar_t *path, bool isDir = false); void AddError_Message(const wchar_t *message); void AddError_Message_Name(const wchar_t *message, const wchar_t *name); // void AddError_Code_Name(DWORD systemError, const wchar_t *name); void AddError_Code_Name(HRESULT systemError, const wchar_t *name); bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } }; class CProgressDialog: public NWindows::NControl::CModalDialog { UString _titleFileName; UString _filePath; UString _status; bool _isDir; UString _background_String; UString _backgrounded_String; UString _foreground_String; UString _pause_String; UString _continue_String; UString _paused_String; int _buttonSizeX; int _buttonSizeY; UINT_PTR _timer; UString _title; class CU64ToI32Converter { unsigned _numShiftBits; UInt64 _range; public: CU64ToI32Converter(): _numShiftBits(0), _range(1) {} void Init(UInt64 range) { _range = range; // Windows CE doesn't like big number for ProgressBar. for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++) range >>= 1; } int Count(UInt64 val) { int res = (int)(val >> _numShiftBits); if (val == _range) res++; return res; } }; CU64ToI32Converter _progressConv; UInt64 _progressBar_Pos; UInt64 _progressBar_Range; NWindows::NControl::CProgressBar m_ProgressBar; NWindows::NControl::CListView _messageList; unsigned _numMessages; UStringVector _messageStrings; // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ CMyComPtr _taskbarList; // #endif HWND _hwndForTaskbar; UInt32 _prevTime; UInt64 _elapsedTime; UInt64 _prevPercentValue; UInt64 _prevElapsedSec; UInt64 _prevRemainingSec; UInt64 _totalBytes_Prev; UInt64 _processed_Prev; UInt64 _packed_Prev; UInt64 _ratio_Prev; UString _filesStr_Prev; UString _filesTotStr_Prev; unsigned _prevSpeed_MoveBits; UInt64 _prevSpeed; bool _foreground; unsigned _numReduceSymbols; bool _wasCreated; bool _needClose; unsigned _numPostedMessages; UInt32 _numAutoSizeMessages; bool _errorsWereDisplayed; bool _waitCloseByCancelButton; bool _cancelWasPressed; bool _inCancelMessageBox; bool _externalCloseMessageWasReceived; // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ void SetTaskbarProgressState(TBPFLAG tbpFlags) { if (_taskbarList && _hwndForTaskbar) _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags); } // #endif void SetTaskbarProgressState(); void UpdateStatInfo(bool showAll); void SetProgressRange(UInt64 range); void SetProgressPos(UInt64 pos); virtual bool OnTimer(WPARAM timerID, LPARAM callback) Z7_override; virtual bool OnInit() Z7_override; virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; virtual void OnCancel() Z7_override; virtual void OnOK() Z7_override; virtual bool OnNotify(UINT /* controlID */, LPNMHDR header) Z7_override; void CopyToClipboard(); NWindows::NSynchronization::CManualResetEvent _createDialogEvent; NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; #ifndef Z7_SFX void AddToTitle(LPCWSTR string); #endif void SetPauseText(); void SetPriorityText(); void OnPauseButton(); void OnPriorityButton(); bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override; void SetTitleText(); void ShowSize(unsigned id, UInt64 val, UInt64 &prev); void UpdateMessagesDialog(); void AddMessageDirect(LPCWSTR message, bool needNumber); void AddMessage(LPCWSTR message); bool OnExternalCloseMessage(); void EnableErrorsControls(bool enable); void ShowAfterMessages(HWND wndParent); void CheckNeedClose(); public: CProgressSync Sync; bool CompressingMode; bool WaitMode; bool ShowCompressionInfo; bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. int IconID; HWND MainWindow; #ifndef Z7_SFX UString MainTitle; UString MainAddTitle; ~CProgressDialog() Z7_DESTRUCTOR_override; #endif CProgressDialog(); void WaitCreating() { _createDialogEvent.Set(); _dialogCreatedEvent.Lock(); } INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL); /* how it works: 1) the working thread calls ProcessWasFinished() that sends kCloseMessage message to CProgressDialog (GUI) thread 2) CProgressDialog (GUI) thread receives kCloseMessage message and calls ProcessWasFinished_GuiVirt(); So we can implement ProcessWasFinished_GuiVirt() and show special results window in GUI thread with CProgressDialog as parent window */ void ProcessWasFinished(); virtual void ProcessWasFinished_GuiVirt() {} }; class CProgressCloser { CProgressDialog *_p; public: CProgressCloser(CProgressDialog &p) : _p(&p) {} ~CProgressCloser() { _p->ProcessWasFinished(); } }; class CProgressThreadVirt: public CProgressDialog { protected: FStringVector ErrorPaths; CProgressFinalMessage FinalMessage; // error if any of HRESULT, ErrorMessage, ErrorPath virtual HRESULT ProcessVirt() = 0; public: HRESULT Result; bool ThreadFinishedOK; // if there is no fatal exception void Process(); void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } HRESULT Create(const UString &title, HWND parentWindow = NULL); CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } }; UString HResultToMessage(HRESULT errorCode); /* how it works: client code inherits CProgressThreadVirt and calls CProgressThreadVirt::Create() { it creates new thread that calls CProgressThreadVirt::Process(); it creates modal progress dialog window with ProgressDialog.Create() } CProgressThreadVirt::Process() { { Result = ProcessVirt(); // virtual function that must implement real work } if (exceptions) or FinalMessage.ErrorMessage.Message { set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message } else if (FinalMessage.OkMessage.Message) { set message to ProgressDialog.Sync.FinalMessage.OkMessage } PostMsg(kCloseMessage); } CProgressDialog::OnExternalCloseMessage() { if (ProgressDialog.Sync.FinalMessage) { WorkWasFinishedVirt(); Show (ProgressDialog.Sync.FinalMessage) MessagesDisplayed = true; } } */ #endif tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog2.rc0000444000175000001440000000124511561173237023507 0ustar nabijaczleweliusers#include "ProgressDialog2Res.h" #include "../../GuiCommon.rc" #undef DIALOG_ID #define DIALOG_ID IDD_PROGRESS #define xc 360 #define k 11 #define z1s 16 #include "ProgressDialog2a.rc" #ifdef UNDER_CE #include "../../GuiCommon.rc" #undef DIALOG_ID #undef m #undef k #undef z1s #define DIALOG_ID IDD_PROGRESS_2 #define m 4 #define k 8 #define z1s 12 #define xc 280 #include "ProgressDialog2a.rc" #endif STRINGTABLE DISCARDABLE { IDS_PROGRESS_PAUSED "Paused" IDS_PROGRESS_FOREGROUND "&Foreground" IDS_CONTINUE "&Continue" IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?" IDS_CLOSE "&Close" } tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog2a.rc0000444000175000001440000000537014160347720023651 0ustar nabijaczleweliusers#undef bxs #define bxs 80 #define x0s MY_PROGRESS_LABEL_UNITS_START #define x1s MY_PROGRESS_VAL_UNITS #define x2s MY_PROGRESS_LABEL_UNITS_START #define x3s MY_PROGRESS_VAL_UNITS #define x1 (m + x0s) #define x3 (xs - m - x3s) #define x2 (x3 - x2s) #undef y0 #undef y1 #undef y2 #undef y3 #undef y4 #undef z0 #undef z1 #undef z2 #undef z3 #define y0 m #define y1 (y0 + k) #define y2 (y1 + k) #define y3 (y2 + k) #define y4 (y3 + k) #define z3 (y4 + k + 1) #define z2 (z3 + k + 1) #define z2s 24 #define z1 (z2 + z2s) #define z0 (z1 + z1s + m) #define z0s 48 #define yc (z0 + z0s + bys) DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Progress" { DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys PUSHBUTTON "&Pause", IDB_PAUSE, bx2, by, bxs, bys PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8 LTEXT "Remaining time:", IDT_PROGRESS_REMAINING, m, y1, x0s, 8 LTEXT "Files:", IDT_PROGRESS_FILES, m, y2, x0s, 8 LTEXT "Errors:", IDT_PROGRESS_ERRORS, m, y4, x0s, 8 LTEXT "Total size:", IDT_PROGRESS_TOTAL, x2, y0, x2s, 8 LTEXT "Speed:", IDT_PROGRESS_SPEED, x2, y1, x2s, 8 LTEXT "Processed:", IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8 LTEXT "Compressed size:" , IDT_PROGRESS_PACKED, x2, y3, x2s, 8 LTEXT "Compression ratio:", IDT_PROGRESS_RATIO, x2, y4, x2s, 8 RTEXT "", IDT_PROGRESS_ELAPSED_VAL, x1, y0, x1s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_FILES_VAL, x1, y2, x1s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_FILES_TOTAL, x1, y3, x1s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_ERRORS_VAL, x1, y4, x1s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_TOTAL_VAL, x3, y0, x3s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_SPEED_VAL, x3, y1, x3s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_PACKED_VAL, x3, y3, x3s, MY_TEXT_NOPREFIX RTEXT "", IDT_PROGRESS_RATIO_VAL, x3, y4, x3s, MY_TEXT_NOPREFIX LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s CONTROL "List1", IDL_PROGRESS_MESSAGES, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, m, z0, xc, z0s } tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialog2Res.h0000444000175000001440000000273414051676401024006 0ustar nabijaczleweliusers#define IDD_PROGRESS 97 #define IDD_PROGRESS_2 10097 #define IDS_CLOSE 408 #define IDS_CONTINUE 411 #define IDB_PROGRESS_BACKGROUND 444 #define IDS_PROGRESS_FOREGROUND 445 #define IDB_PAUSE 446 #define IDS_PROGRESS_PAUSED 447 #define IDS_PROGRESS_ASK_CANCEL 448 #define IDT_PROGRESS_PACKED 1008 #define IDT_PROGRESS_FILES 1032 #define IDT_PROGRESS_ELAPSED 3900 #define IDT_PROGRESS_REMAINING 3901 #define IDT_PROGRESS_TOTAL 3902 #define IDT_PROGRESS_SPEED 3903 #define IDT_PROGRESS_PROCESSED 3904 #define IDT_PROGRESS_RATIO 3905 #define IDT_PROGRESS_ERRORS 3906 #define IDC_PROGRESS1 100 #define IDL_PROGRESS_MESSAGES 101 #define IDT_PROGRESS_FILE_NAME 102 #define IDT_PROGRESS_STATUS 103 #define IDT_PROGRESS_PACKED_VAL 110 #define IDT_PROGRESS_FILES_VAL 111 #define IDT_PROGRESS_FILES_TOTAL 112 #define IDT_PROGRESS_ELAPSED_VAL 120 #define IDT_PROGRESS_REMAINING_VAL 121 #define IDT_PROGRESS_TOTAL_VAL 122 #define IDT_PROGRESS_SPEED_VAL 123 #define IDT_PROGRESS_PROCESSED_VAL 124 #define IDT_PROGRESS_RATIO_VAL 125 #define IDT_PROGRESS_ERRORS_VAL 126 #ifdef UNDER_CE #define MY_PROGRESS_VAL_UNITS 44 #else #define MY_PROGRESS_VAL_UNITS 72 #endif #define MY_PROGRESS_LABEL_UNITS_MIN 60 #define MY_PROGRESS_LABEL_UNITS_START 90 #define MY_PROGRESS_PAD_UNITS 4 tmp41wklro_/CPP/7zip/UI/FileManager/ProgressDialogRes.h0000444000175000001440000000007011555261345023716 0ustar nabijaczleweliusers#define IDD_PROGRESS 97 #define IDC_PROGRESS1 100 tmp41wklro_/CPP/7zip/UI/FileManager/PropertyName.cpp0000444000175000001440000000066412075751747023321 0ustar nabijaczleweliusers// PropertyName.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "LangUtils.h" #include "PropertyName.h" UString GetNameOfProperty(PROPID propID, const wchar_t *name) { if (propID < 1000) { UString s = LangString(1000 + propID); if (!s.IsEmpty()) return s; } if (name) return name; wchar_t temp[16]; ConvertUInt32ToString(propID, temp); return temp; } tmp41wklro_/CPP/7zip/UI/FileManager/PropertyName.h0000444000175000001440000000031614357314620022746 0ustar nabijaczleweliusers// PropertyName.h #ifndef ZIP7_INC_PROPERTY_NAME_H #define ZIP7_INC_PROPERTY_NAME_H #include "../../../Common/MyString.h" UString GetNameOfProperty(PROPID propID, const wchar_t *name); #endif tmp41wklro_/CPP/7zip/UI/FileManager/PropertyNameRes.h0000444000175000001440000000773414331466140023430 0ustar nabijaczleweliusers #define IDS_PROP_PATH 1003 #define IDS_PROP_NAME 1004 #define IDS_PROP_EXTENSION 1005 #define IDS_PROP_IS_FOLDER 1006 #define IDS_PROP_SIZE 1007 #define IDS_PROP_PACKED_SIZE 1008 #define IDS_PROP_ATTRIBUTES 1009 #define IDS_PROP_CTIME 1010 #define IDS_PROP_ATIME 1011 #define IDS_PROP_MTIME 1012 #define IDS_PROP_SOLID 1013 #define IDS_PROP_C0MMENTED 1014 #define IDS_PROP_ENCRYPTED 1015 #define IDS_PROP_SPLIT_BEFORE 1016 #define IDS_PROP_SPLIT_AFTER 1017 #define IDS_PROP_DICTIONARY_SIZE 1018 #define IDS_PROP_CRC 1019 #define IDS_PROP_FILE_TYPE 1020 #define IDS_PROP_ANTI 1021 #define IDS_PROP_METHOD 1022 #define IDS_PROP_HOST_OS 1023 #define IDS_PROP_FILE_SYSTEM 1024 #define IDS_PROP_USER 1025 #define IDS_PROP_GROUP 1026 #define IDS_PROP_BLOCK 1027 #define IDS_PROP_COMMENT 1028 #define IDS_PROP_POSITION 1029 #define IDS_PROP_PREFIX 1030 #define IDS_PROP_FOLDERS 1031 #define IDS_PROP_FILES 1032 #define IDS_PROP_VERSION 1033 #define IDS_PROP_VOLUME 1034 #define IDS_PROP_IS_VOLUME 1035 #define IDS_PROP_OFFSET 1036 #define IDS_PROP_LINKS 1037 #define IDS_PROP_NUM_BLOCKS 1038 #define IDS_PROP_NUM_VOLUMES 1039 #define IDS_PROP_BIT64 1041 #define IDS_PROP_BIG_ENDIAN 1042 #define IDS_PROP_CPU 1043 #define IDS_PROP_PHY_SIZE 1044 #define IDS_PROP_HEADERS_SIZE 1045 #define IDS_PROP_CHECKSUM 1046 #define IDS_PROP_CHARACTS 1047 #define IDS_PROP_VA 1048 #define IDS_PROP_ID 1049 #define IDS_PROP_SHORT_NAME 1050 #define IDS_PROP_CREATOR_APP 1051 #define IDS_PROP_SECTOR_SIZE 1052 #define IDS_PROP_POSIX_ATTRIB 1053 #define IDS_PROP_SYM_LINK 1054 #define IDS_PROP_ERROR 1055 #define IDS_PROP_TOTAL_SIZE 1056 #define IDS_PROP_FREE_SPACE 1057 #define IDS_PROP_CLUSTER_SIZE 1058 #define IDS_PROP_VOLUME_NAME 1059 #define IDS_PROP_LOCAL_NAME 1060 #define IDS_PROP_PROVIDER 1061 #define IDS_PROP_NT_SECURITY 1062 #define IDS_PROP_ALT_STREAM 1063 #define IDS_PROP_AUX 1064 #define IDS_PROP_DELETED 1065 #define IDS_PROP_IS_TREE 1066 #define IDS_PROP_SHA1 1067 #define IDS_PROP_SHA256 1068 #define IDS_PROP_ERROR_TYPE 1069 #define IDS_PROP_NUM_ERRORS 1070 #define IDS_PROP_ERROR_FLAGS 1071 #define IDS_PROP_WARNING_FLAGS 1072 #define IDS_PROP_WARNING 1073 #define IDS_PROP_NUM_STREAMS 1074 #define IDS_PROP_NUM_ALT_STREAMS 1075 #define IDS_PROP_ALT_STREAMS_SIZE 1076 #define IDS_PROP_VIRTUAL_SIZE 1077 #define IDS_PROP_UNPACK_SIZE 1078 #define IDS_PROP_TOTAL_PHY_SIZE 1079 #define IDS_PROP_VOLUME_INDEX 1080 #define IDS_PROP_SUBTYPE 1081 #define IDS_PROP_SHORT_COMMENT 1082 #define IDS_PROP_CODE_PAGE 1083 #define IDS_PROP_IS_NOT_ARC_TYPE 1084 #define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085 #define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086 #define IDS_PROP_TAIL_SIZE 1087 #define IDS_PROP_EMB_STUB_SIZE 1088 #define IDS_PROP_NT_REPARSE 1089 #define IDS_PROP_HARD_LINK 1090 #define IDS_PROP_INODE 1091 #define IDS_PROP_STREAM_ID 1092 #define IDS_PROP_READ_ONLY 1093 #define IDS_PROP_OUT_NAME 1094 #define IDS_PROP_COPY_LINK 1095 #define IDS_PROP_ARC_FILE_NAME 1096 #define IDS_PROP_IS_HASH 1097 #define IDS_PROP_CHANGE_TIME 1098 #define IDS_PROP_USER_ID 1099 #define IDS_PROP_GROUP_ID 1100 #define IDS_PROP_DEVICE_MAJOR 1101 #define IDS_PROP_DEVICE_MINOR 1102 #define IDS_PROP_DEV_MAJOR 1103 #define IDS_PROP_DEV_MINOR 1104 tmp41wklro_/CPP/7zip/UI/FileManager/resource.h0000444000175000001440000001514114600552340022144 0ustar nabijaczleweliusers#include "resourceGui.h" #define IDR_MENUBAR1 70 #define IDM_MENU 71 #define IDR_ACCELERATOR1 72 #define IDB_ADD 100 #define IDB_EXTRACT 101 #define IDB_TEST 102 #define IDB_COPY 103 #define IDB_MOVE 104 #define IDB_DELETE 105 #define IDB_INFO 106 #define IDB_ADD2 150 #define IDB_EXTRACT2 151 #define IDB_TEST2 152 #define IDB_COPY2 153 #define IDB_MOVE2 154 #define IDB_DELETE2 155 #define IDB_INFO2 156 #define IDM_HASH_ALL 101 #define IDM_CRC32 102 #define IDM_CRC64 103 #define IDM_SHA1 104 #define IDM_SHA256 105 #define IDM_XXH64 106 #define IDM_BLAKE2SP 107 #define IDM_FILE 500 #define IDM_EDIT 501 #define IDM_VIEW 502 #define IDM_FAVORITES 503 #define IDM_TOOLS 504 #define IDM_HELP 505 #define IDM_OPEN 540 #define IDM_OPEN_INSIDE 541 #define IDM_OPEN_OUTSIDE 542 #define IDM_FILE_VIEW 543 #define IDM_FILE_EDIT 544 #define IDM_RENAME 545 #define IDM_COPY_TO 546 #define IDM_MOVE_TO 547 #define IDM_DELETE 548 #define IDM_SPLIT 549 #define IDM_COMBINE 550 #define IDM_PROPERTIES 551 #define IDM_COMMENT 552 #define IDM_CRC 553 #define IDM_DIFF 554 #define IDM_CREATE_FOLDER 555 #define IDM_CREATE_FILE 556 // #define IDM_EXIT 557 #define IDM_LINK 558 #define IDM_ALT_STREAMS 559 #define IDM_VER_EDIT 580 #define IDM_VER_COMMIT 581 #define IDM_VER_REVERT 582 #define IDM_VER_DIFF 583 #define IDM_OPEN_INSIDE_ONE 590 #define IDM_OPEN_INSIDE_PARSER 591 #define IDM_SELECT_ALL 600 #define IDM_DESELECT_ALL 601 #define IDM_INVERT_SELECTION 602 #define IDM_SELECT 603 #define IDM_DESELECT 604 #define IDM_SELECT_BY_TYPE 605 #define IDM_DESELECT_BY_TYPE 606 #define IDM_VIEW_LARGE_ICONS 700 #define IDM_VIEW_SMALL_ICONS 701 #define IDM_VIEW_LIST 702 #define IDM_VIEW_DETAILS 703 #define IDM_VIEW_ARANGE_BY_NAME 710 #define IDM_VIEW_ARANGE_BY_TYPE 711 #define IDM_VIEW_ARANGE_BY_DATE 712 #define IDM_VIEW_ARANGE_BY_SIZE 713 #define IDM_VIEW_ARANGE_NO_SORT 730 #define IDM_VIEW_FLAT_VIEW 731 #define IDM_VIEW_TWO_PANELS 732 #define IDM_VIEW_TOOLBARS 733 #define IDM_OPEN_ROOT_FOLDER 734 #define IDM_OPEN_PARENT_FOLDER 735 #define IDM_FOLDERS_HISTORY 736 #define IDM_VIEW_REFRESH 737 #define IDM_VIEW_AUTO_REFRESH 738 // #define IDM_VIEW_SHOW_DELETED 739 // #define IDM_VIEW_SHOW_STREAMS 740 #define IDM_VIEW_ARCHIVE_TOOLBAR 750 #define IDM_VIEW_STANDARD_TOOLBAR 751 #define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752 #define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753 #define IDM_VIEW_TIME_POPUP 760 #define IDM_VIEW_TIME 761 #define IDM_VIEW_TIME_UTC 799 #define IDM_ADD_TO_FAVORITES 800 #define IDS_BOOKMARK 801 #define IDM_OPTIONS 900 #define IDM_BENCHMARK 901 #define IDM_BENCHMARK2 902 #define IDM_TEMP_DIR 910 #define IDM_HELP_CONTENTS 960 #define IDM_ABOUT 961 #define IDS_OPTIONS 2100 #define IDS_N_SELECTED_ITEMS 3002 #define IDS_FILE_EXIST 3008 #define IDS_WANT_UPDATE_MODIFIED_FILE 3009 #define IDS_CANNOT_UPDATE_FILE 3010 #define IDS_CANNOT_START_EDITOR 3011 #define IDS_VIRUS 3012 #define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 3013 #define IDS_SELECT_ONE_FILE 3014 #define IDS_SELECT_FILES 3015 #define IDS_TOO_MANY_ITEMS 3016 #define IDS_COPY 6000 #define IDS_MOVE 6001 #define IDS_COPY_TO 6002 #define IDS_MOVE_TO 6003 #define IDS_COPYING 6004 #define IDS_MOVING 6005 #define IDS_RENAMING 6006 #define IDS_OPERATION_IS_NOT_SUPPORTED 6008 #define IDS_ERROR_RENAMING 6009 #define IDS_CONFIRM_FILE_COPY 6010 #define IDS_WANT_TO_COPY_FILES 6011 #define IDS_CONFIRM_FILE_DELETE 6100 #define IDS_CONFIRM_FOLDER_DELETE 6101 #define IDS_CONFIRM_ITEMS_DELETE 6102 #define IDS_WANT_TO_DELETE_FILE 6103 #define IDS_WANT_TO_DELETE_FOLDER 6104 #define IDS_WANT_TO_DELETE_ITEMS 6105 #define IDS_DELETING 6106 #define IDS_ERROR_DELETING 6107 #define IDS_ERROR_LONG_PATH_TO_RECYCLE 6108 #define IDS_CREATE_FOLDER 6300 #define IDS_CREATE_FILE 6301 #define IDS_CREATE_FOLDER_NAME 6302 #define IDS_CREATE_FILE_NAME 6303 #define IDS_CREATE_FOLDER_DEFAULT_NAME 6304 #define IDS_CREATE_FILE_DEFAULT_NAME 6305 #define IDS_CREATE_FOLDER_ERROR 6306 #define IDS_CREATE_FILE_ERROR 6307 #define IDS_COMMENT 6400 #define IDS_COMMENT2 6401 #define IDS_SELECT 6402 #define IDS_DESELECT 6403 #define IDS_SELECT_MASK 6404 #define IDS_PROPERTIES 6600 #define IDS_FOLDERS_HISTORY 6601 #define IDS_COMPUTER 7100 #define IDS_NETWORK 7101 #define IDS_DOCUMENTS 7102 #define IDS_SYSTEM 7103 #define IDS_ADD 7200 #define IDS_EXTRACT 7201 #define IDS_TEST 7202 #define IDS_BUTTON_COPY 7203 #define IDS_BUTTON_MOVE 7204 #define IDS_BUTTON_DELETE 7205 #define IDS_BUTTON_INFO 7206 #define IDS_SPLITTING 7303 #define IDS_SPLIT_CONFIRM_TITLE 7304 #define IDS_SPLIT_CONFIRM_MESSAGE 7305 #define IDS_SPLIT_VOL_MUST_BE_SMALLER 7306 #define IDS_COMBINE 7400 #define IDS_COMBINE_TO 7401 #define IDS_COMBINING 7402 #define IDS_COMBINE_SELECT_ONE_FILE 7403 #define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404 #define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405 tmp41wklro_/CPP/7zip/UI/FileManager/resourceGui.h0000444000175000001440000000140314574617400022616 0ustar nabijaczleweliusers#define IDI_ICON 1 #define IDS_MESSAGE_NO_ERRORS 3001 #define IDS_PROGRESS_TESTING 3302 #define IDS_OPENNING 3303 #define IDS_SCANNING 3304 #define IDS_CHECKSUM_CALCULATING 7500 #define IDS_CHECKSUM_INFORMATION 7501 #define IDS_CHECKSUM_CRC_DATA 7502 #define IDS_CHECKSUM_CRC_DATA_NAMES 7503 #define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504 #define IDS_INCORRECT_VOLUME_SIZE 7307 #define IDS_MEM_REQUIRES_BIG_MEM 7811 #define IDS_MEM_REQUIRED_MEM_SIZE 7812 #define IDS_MEM_CURRENT_MEM_LIMIT 7813 #define IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP 7814 #define IDS_MEM_RAM_SIZE 7815 #define IDS_MSG_ARC_UNPACKING_WAS_SKIPPED 7822 tmp41wklro_/CPP/7zip/UI/FileManager/StdAfx.h0000444000175000001440000000374714555143020021517 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../../Common/Common.h" #endif /* WINVER and _WIN32_WINNT MSVC6 / 2003sdk: { doesn't set _WIN32_WINNT if WINVER is not set sets WINVER to value: 0x0400 : MSVC6 0x0501 : Windows Server 2003 PSDK / 2003 R2 PSDK } SDK for Win7 (and later) { sets _WIN32_WINNT if it's not set. sets WINVER if it's not set. includes that does: #if !defined(_WIN32_WINNT) && !defined(_CHICAGO_) #define _WIN32_WINNT 0x0601 // in win7 sdk #define _WIN32_WINNT 0x0A00 // in win10 sdk #endif #ifndef WINVER #ifdef _WIN32_WINNT #define WINVER _WIN32_WINNT else #define WINVER 0x0601 // in win7 sdk #define WINVER 0x0A00 // in win10 sdk endif #endif } Some GUI structures defined by windows will be larger, If (_WIN32_WINNT) value is larger. Also if we send sizeof(win_gui_struct) to some windows function, and we compile that code with big (_WIN32_WINNT) value, the window function in old Windows can fail, if that old Windows doesn't understand new big version of (win_gui_struct) compiled with big (_WIN32_WINNT) value. So it's better to define smallest (_WIN32_WINNT) value here. In 7-Zip FM we use some functions that require (_WIN32_WINNT == 0x0500). So it's simpler to define (_WIN32_WINNT == 0x0500) here. If we define (_WIN32_WINNT == 0x0400) here, we need some manual declarations for functions and macros that require (0x0500) functions. Also libs must contain these (0x0500+) functions. Some code in 7-zip FM uses also CommCtrl.h structures that depend from (_WIN32_IE) value. But default (_WIN32_IE) value from probably is OK for us. So we don't set _WIN32_IE here. default _WIN32_IE value set by : 0x501 2003sdk 0xa00 win10 sdk */ tmp41wklro_/CPP/7zip/UI/FileManager/SysIconUtils.cpp0000444000175000001440000002402314643214060023260 0ustar nabijaczleweliusers// SysIconUtils.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../../Common/StringConvert.h" #endif #include "../../../Windows/FileDir.h" #include "SysIconUtils.h" #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif #ifndef _UNICODE extern bool g_IsNT; #endif CExtToIconMap g_Ext_to_Icon_Map; int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl) { LPITEMIDLIST pidl = NULL; SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (pidl) { SHFILEINFO shFileInfo; shFileInfo.iIcon = -1; const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_DIRECTORY, &shFileInfo, sizeof(shFileInfo), SHGFI_PIDL | SHGFI_SYSICONINDEX); /* IMalloc *pMalloc; SHGetMalloc(&pMalloc); if (pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); } */ // we use OLE2.dll function here CoTaskMemFree(pidl); if (res) return shFileInfo.iIcon; } return -1; } #ifndef _UNICODE Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); static struct C_SHGetFileInfo_Init { Func_SHGetFileInfoW f_SHGetFileInfoW; C_SHGetFileInfo_Init() { f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS( Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); // f_SHGetFileInfoW = NULL; // for debug } } g_SHGetFileInfo_Init; #endif #ifdef _UNICODE #define My_SHGetFileInfoW SHGetFileInfoW #else static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) { if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW) return 0; return g_SHGetFileInfo_Init.f_SHGetFileInfoW(pszPath, attrib, psfi, cbFileInfo, uFlags); } #endif DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( CFSTR path, DWORD attrib, int &iconIndex) { #ifndef _UNICODE if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW) { SHFILEINFO shFileInfo; // ZeroMemory(&shFileInfo, sizeof(shFileInfo)); shFileInfo.iIcon = -1; // optional const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE, &shFileInfo, sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); iconIndex = shFileInfo.iIcon; return res; } else #endif { SHFILEINFOW shFileInfo; // ZeroMemory(&shFileInfo, sizeof(shFileInfo)); shFileInfo.iIcon = -1; // optional const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path), attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE, &shFileInfo, sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); // (shFileInfo.iIcon == 0) returned for unknown extensions and files without extension iconIndex = shFileInfo.iIcon; // we use SHGFI_USEFILEATTRIBUTES, and // (res != 0) is expected for main cases, even if there are no such file. // (res == 0) for path with kSuperPrefix \\?\ // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe. // So we can use SHGFI_USEFILEATTRIBUTES for any case. // UString temp = fs2us(path); // for debug // UString tempName = temp.Ptr(temp.ReverseFind_PathSepar() + 1); // for debug // iconIndex = -1; // for debug return res; } } int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib) { int iconIndex = -1; if (!Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( path, attrib, iconIndex)) iconIndex = -1; return iconIndex; } HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT( CFSTR path, DWORD attrib, Int32 *iconIndex) { *iconIndex = -1; int iconIndexTemp; if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( path, attrib, iconIndexTemp)) { *iconIndex = iconIndexTemp; return S_OK; } return GetLastError_noZero_HRESULT(); } /* DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) { #ifndef _UNICODE if (!g_IsNT) { SHFILEINFO shFileInfo; shFileInfo.szTypeName[0] = 0; DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo, sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); if (typeName) *typeName = GetUnicodeString(shFileInfo.szTypeName); iconIndex = shFileInfo.iIcon; return res; } else #endif { SHFILEINFOW shFileInfo; shFileInfo.szTypeName[0] = 0; DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo, sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); if (typeName) *typeName = shFileInfo.szTypeName; iconIndex = shFileInfo.iIcon; return res; } } */ static int FindInSorted_Attrib(const CRecordVector &vect, DWORD attrib, unsigned &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { const unsigned mid = (left + right) / 2; const DWORD midAttrib = vect[mid].Attrib; if (attrib == midAttrib) return (int)mid; if (attrib < midAttrib) right = mid; else left = mid + 1; } insertPos = left; return -1; } static int FindInSorted_Ext(const CObjectVector &vect, const wchar_t *ext, unsigned &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { const unsigned mid = (left + right) / 2; const int compare = MyStringCompareNoCase(ext, vect[mid].Ext); if (compare == 0) return (int)mid; if (compare < 0) right = mid; else left = mid + 1; } insertPos = left; return -1; } // bool DoItemAlwaysStart(const UString &name); int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) { int dotPos = -1; unsigned i; for (i = 0;; i++) { const wchar_t c = fileName[i]; if (c == 0) break; if (c == '.') dotPos = (int)i; // we don't need IS_PATH_SEPAR check, because (fileName) doesn't include path prefix. // if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1; } /* if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0) { char s[256]; sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib); OutputDebugStringA(s); OutputDebugStringW(fileName); } */ if ((attrib & FILE_ATTRIBUTE_DIRECTORY) || dotPos < 0) for (unsigned k = 0;; k++) { if (k >= 2) return -1; unsigned insertPos = 0; const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); if (index >= 0) { // if (typeName) *typeName = _attribMap[index].TypeName; return _attribMap[(unsigned)index].IconIndex; } CAttribIconPair pair; pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path( #ifdef UNDER_CE FTEXT("\\") #endif FTEXT("__DIR__") , attrib // , pair.TypeName ); if (_attribMap.Size() < (1u << 16) // we limit cache size || attrib < (1u << 15)) // we want to put all items with basic attribs to cache { /* char s[256]; sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); OutputDebugStringA(s); */ pair.Attrib = attrib; _attribMap.Insert(insertPos, pair); // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } if (pair.IconIndex >= 0) return pair.IconIndex; attrib = (attrib & FILE_ATTRIBUTE_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE; } CObjectVector &map = (attrib & FILE_ATTRIBUTE_COMPRESSED) ? _extMap_Compressed : _extMap_Normal; const wchar_t *ext = fileName + dotPos + 1; unsigned insertPos = 0; const int index = FindInSorted_Ext(map, ext, insertPos); if (index >= 0) { const CExtIconPair &pa = map[index]; // if (typeName) *typeName = pa.TypeName; return pa.IconIndex; } for (i = 0;; i++) { const wchar_t c = ext[i]; if (c == 0) break; if (c < L'0' || c > L'9') break; } if (i != 0 && ext[i] == 0) { // Shell_GetFileInfo_SysIconIndex_for_Path is too slow for big number of split extensions: .001, .002, .003 if (!SplitIconIndex_Defined) { Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( #ifdef UNDER_CE FTEXT("\\") #endif FTEXT("__FILE__.001"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex); SplitIconIndex_Defined = true; } return SplitIconIndex; } CExtIconPair pair; pair.Ext = ext; pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path( us2fs(fileName + dotPos), attrib & FILE_ATTRIBUTE_COMPRESSED ? FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED: FILE_ATTRIBUTE_ARCHIVE); if (map.Size() < (1u << 16) // we limit cache size // || DoItemAlwaysStart(fileName + dotPos) // we want some popular extensions in cache ) map.Insert(insertPos, pair); // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons) { SHFILEINFO shFileInfo; // shFileInfo.hIcon = NULL; // optional const DWORD_PTR res = SHGetFileInfo(TEXT(""), /* FILE_ATTRIBUTE_ARCHIVE | */ FILE_ATTRIBUTE_DIRECTORY, &shFileInfo, sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_LARGEICON)); #if 0 // (shFileInfo.hIcon == NULL), because we don't use SHGFI_ICON. // so DestroyIcon() is not required if (res && shFileInfo.hIcon) // unexpected DestroyIcon(shFileInfo.hIcon); #endif return (HIMAGELIST)res; } tmp41wklro_/CPP/7zip/UI/FileManager/SysIconUtils.h0000444000175000001440000000323014643214060022722 0ustar nabijaczleweliusers// SysIconUtils.h #ifndef ZIP7_INC_SYS_ICON_UTILS_H #define ZIP7_INC_SYS_ICON_UTILS_H #include "../../../Common/MyWindows.h" #include #include "../../../Common/MyString.h" struct CExtIconPair { UString Ext; int IconIndex; // UString TypeName; // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); } }; struct CAttribIconPair { DWORD Attrib; int IconIndex; // UString TypeName; // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); } }; struct CExtToIconMap { CRecordVector _attribMap; CObjectVector _extMap_Normal; CObjectVector _extMap_Compressed; int SplitIconIndex; int SplitIconIndex_Defined; CExtToIconMap(): SplitIconIndex_Defined(false) {} void Clear() { SplitIconIndex_Defined = false; _extMap_Normal.Clear(); _extMap_Compressed.Clear(); _attribMap.Clear(); } int GetIconIndex_DIR(DWORD attrib = FILE_ATTRIBUTE_DIRECTORY) { return GetIconIndex(attrib, L"__DIR__"); } int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */); }; extern CExtToIconMap g_Ext_to_Icon_Map; DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( CFSTR path, DWORD attrib, int &iconIndex); HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT( CFSTR path, DWORD attrib, Int32 *iconIndex); int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib); int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl); HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons); #endif tmp41wklro_/CPP/7zip/UI/GUI/0000700000175000001440000000000014706260545016416 5ustar nabijaczleweliuserstmp41wklro_/CPP/7zip/UI/GUI/7zG.exe.manifest0000444000175000001440000000272714412233000021371 0ustar nabijaczleweliusers 7-Zip GUI. true true tmp41wklro_/CPP/7zip/UI/GUI/Extract.rc0000444000175000001440000000547713734576270020410 0ustar nabijaczleweliusers#include "ExtractRes.h" LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US STRINGTABLE DISCARDABLE BEGIN IDS_MEM_ERROR "The system cannot allocate the required amount of memory" IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive." IDS_CANT_OPEN_ARCHIVE "Cannot open file '{0}' as archive" IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Cannot open encrypted archive '{0}'. Wrong password?" IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" IDS_CANT_OPEN_AS_TYPE "Cannot open the file as {0} archive" IDS_IS_OPEN_AS_TYPE "The file is open as {0} archive" IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset" IDS_PROGRESS_EXTRACTING "Extracting" IDS_PROGRESS_SKIPPING "Skipping" IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files." IDS_EXTRACT_PATHS_FULL "Full pathnames" IDS_EXTRACT_PATHS_NO "No pathnames" IDS_EXTRACT_PATHS_ABS "Absolute pathnames" IDS_PATH_MODE_RELAT "Relative pathnames" IDS_EXTRACT_OVERWRITE_ASK "Ask before overwrite" IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt" IDS_EXTRACT_OVERWRITE_SKIP_EXISTING "Skip existing files" IDS_EXTRACT_OVERWRITE_RENAME "Auto rename" IDS_EXTRACT_OVERWRITE_RENAME_EXISTING "Auto rename existing files" IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'." IDS_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken" IDS_EXTRACT_MESSAGE_CRC_ERROR "CRC failed in '{0}'. File is broken." IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?" IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?" IDS_EXTRACT_MSG_WRONG_PSW_GUESS "Wrong password?" // IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file" IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method" IDS_EXTRACT_MSG_DATA_ERROR "Data error" IDS_EXTRACT_MSG_CRC_ERROR "CRC failed" IDS_EXTRACT_MSG_UNAVAILABLE_DATA "Unavailable data" IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data" IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data" IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive" IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error" IDS_EXTRACT_MSG_WRONG_PSW_CLAIM "Wrong password" IDS_OPEN_MSG_UNAVAILABLE_START "Unavailable start of archive" IDS_OPEN_MSG_UNCONFIRMED_START "Unconfirmed start of archive" // IDS_OPEN_MSG_ERROR_FLAGS + 5 "Unexpected end of archive" // IDS_OPEN_MSG_ERROR_FLAGS + 6 "There are data after the end of archive" IDS_OPEN_MSG_UNSUPPORTED_FEATURE "Unsupported feature" END tmp41wklro_/CPP/7zip/UI/GUI/ExtractDialog.cpp0000444000175000001440000002377214405637620021675 0ustar nabijaczleweliusers// ExtractDialog.cpp #include "StdAfx.h" #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileName.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/ResourceString.h" #ifndef Z7_NO_REGISTRY #include "../FileManager/HelpUtils.h" #endif #include "../FileManager/BrowseDialog.h" #include "../FileManager/LangUtils.h" #include "../FileManager/resourceGui.h" #include "ExtractDialog.h" #include "ExtractDialogRes.h" #include "ExtractRes.h" using namespace NWindows; using namespace NFile; using namespace NName; extern HINSTANCE g_hInstance; #ifndef Z7_SFX static const UInt32 kPathMode_IDs[] = { IDS_EXTRACT_PATHS_FULL, IDS_EXTRACT_PATHS_NO, IDS_EXTRACT_PATHS_ABS }; static const UInt32 kOverwriteMode_IDs[] = { IDS_EXTRACT_OVERWRITE_ASK, IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT, IDS_EXTRACT_OVERWRITE_SKIP_EXISTING, IDS_EXTRACT_OVERWRITE_RENAME, IDS_EXTRACT_OVERWRITE_RENAME_EXISTING }; static const // NExtract::NPathMode::EEnum int kPathModeButtonsVals[] = { NExtract::NPathMode::kFullPaths, NExtract::NPathMode::kNoPaths, NExtract::NPathMode::kAbsPaths }; static const int // NExtract::NOverwriteMode::EEnum kOverwriteButtonsVals[] = { NExtract::NOverwriteMode::kAsk, NExtract::NOverwriteMode::kOverwrite, NExtract::NOverwriteMode::kSkip, NExtract::NOverwriteMode::kRename, NExtract::NOverwriteMode::kRenameExisting }; #endif #ifdef Z7_LANG static const UInt32 kLangIDs[] = { IDT_EXTRACT_EXTRACT_TO, IDT_EXTRACT_PATH_MODE, IDT_EXTRACT_OVERWRITE_MODE, // IDX_EXTRACT_ALT_STREAMS, IDX_EXTRACT_NT_SECUR, IDX_EXTRACT_ELIM_DUP, IDG_PASSWORD, IDX_PASSWORD_SHOW }; #endif // static const int kWildcardsButtonIndex = 2; #ifndef Z7_NO_REGISTRY static const unsigned kHistorySize = 16; #endif #ifndef Z7_SFX // it's used in CompressDialog also void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal) { unsigned curSel = 0; for (unsigned i = 0; i < numItems; i++) { UString s = LangString(langIDs[i]); s.RemoveChar(L'&'); const int index = (int)combo.AddString(s); combo.SetItemData(index, (LPARAM)i); if (values[i] == curVal) curSel = i; } combo.SetCurSel(curSel); } // it's used in CompressDialog also bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2) { if (b1.Def) return b1.Val; if (b2.Def) return b2.Val; return b1.Val; } void CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) { CheckButton(id, GetBoolsVal(b1, b2)); } void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) { const bool val = IsButtonCheckedBool(id); const bool oldVal = GetBoolsVal(b1, b2); if (val != oldVal) b1.Def = b2.Def = true; b1.Val = b2.Val = val; } #endif bool CExtractDialog::OnInit() { #ifdef Z7_LANG { UString s; LangString_OnlyFromLangFile(IDD_EXTRACT, s); if (s.IsEmpty()) GetText(s); if (!ArcPath.IsEmpty()) { s += " : "; s += ArcPath; } SetText(s); // LangSetWindowText(*this, IDD_EXTRACT); LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs)); } #endif #ifndef Z7_SFX _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD)); _passwordControl.SetText(Password); _passwordControl.SetPasswordChar(TEXT('*')); _pathName.Attach(GetItem(IDE_EXTRACT_NAME)); #endif #ifdef Z7_NO_REGISTRY PathMode = NExtract::NPathMode::kFullPaths; OverwriteMode = NExtract::NOverwriteMode::kAsk; #else _info.Load(); if (_info.PathMode == NExtract::NPathMode::kCurPaths) _info.PathMode = NExtract::NPathMode::kFullPaths; if (!PathMode_Force && _info.PathMode_Force) PathMode = _info.PathMode; if (!OverwriteMode_Force && _info.OverwriteMode_Force) OverwriteMode = _info.OverwriteMode; // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val); UpdatePasswordControl(); #endif _path.Attach(GetItem(IDC_EXTRACT_PATH)); UString pathPrefix = DirPath; #ifndef Z7_SFX if (_info.SplitDest.Val) { CheckButton(IDX_EXTRACT_NAME_ENABLE, true); UString pathName; SplitPathToParts_Smart(DirPath, pathPrefix, pathName); if (pathPrefix.IsEmpty()) pathPrefix = pathName; else _pathName.SetText(pathName); } else ShowItem_Bool(IDE_EXTRACT_NAME, false); #endif _path.SetText(pathPrefix); #ifndef Z7_NO_REGISTRY for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++) _path.AddString(_info.Paths[i]); #endif /* if (_info.Paths.Size() > 0) _path.SetCurSel(0); else _path.SetCurSel(-1); */ #ifndef Z7_SFX _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE)); _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE)); AddComboItems(_pathMode, kPathMode_IDs, Z7_ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode); AddComboItems(_overwriteMode, kOverwriteMode_IDs, Z7_ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode); #endif HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); SetIcon(ICON_BIG, icon); // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES); // filesWindow.Enable(_enableFilesButton); NormalizePosition(); return CModalDialog::OnInit(); } #ifndef Z7_SFX void CExtractDialog::UpdatePasswordControl() { _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*')); UString password; _passwordControl.GetText(password); _passwordControl.SetText(password); } #endif bool CExtractDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { case IDB_EXTRACT_SET_PATH: OnButtonSetPath(); return true; #ifndef Z7_SFX case IDX_EXTRACT_NAME_ENABLE: ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE)); return true; case IDX_PASSWORD_SHOW: { UpdatePasswordControl(); return true; } #endif } return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } void CExtractDialog::OnButtonSetPath() { UString currentPath; _path.GetText(currentPath); UString title = LangString(IDS_EXTRACT_SET_FOLDER); UString resultPath; if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) return; #ifndef Z7_NO_REGISTRY _path.SetCurSel(-1); #endif _path.SetText(resultPath); } void AddUniqueString(UStringVector &list, const UString &s); void AddUniqueString(UStringVector &list, const UString &s) { FOR_VECTOR (i, list) if (s.IsEqualTo_NoCase(list[i])) return; list.Add(s); } void CExtractDialog::OnOK() { #ifndef Z7_SFX int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()]; if (PathMode != NExtract::NPathMode::kCurPaths || pathMode2 != NExtract::NPathMode::kFullPaths) PathMode = (NExtract::NPathMode::EEnum)pathMode2; OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()]; // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode(); _passwordControl.GetText(Password); #endif #ifndef Z7_NO_REGISTRY // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); GetButton_Bools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); GetButton_Bools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); bool showPassword = IsShowPasswordChecked(); if (showPassword != _info.ShowPassword.Val) { _info.ShowPassword.Def = true; _info.ShowPassword.Val = showPassword; } if (_info.PathMode != pathMode2) { _info.PathMode_Force = true; _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2; /* // we allow kAbsPaths in registry. if (_info.PathMode == NExtract::NPathMode::kAbsPaths) _info.PathMode = NExtract::NPathMode::kFullPaths; */ } if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode) _info.OverwriteMode_Force = true; _info.OverwriteMode = OverwriteMode; #else ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); #endif UString s; #ifdef Z7_NO_REGISTRY _path.GetText(s); #else int currentItem = _path.GetCurSel(); if (currentItem == CB_ERR) { _path.GetText(s); if (_path.GetCount() >= (int)kHistorySize) currentItem = _path.GetCount() - 1; } else _path.GetLBText(currentItem, s); #endif s.Trim(); NName::NormalizeDirPathPrefix(s); #ifndef Z7_SFX const bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE); if (splitDest) { UString pathName; _pathName.GetText(pathName); pathName.Trim(); s += pathName; NName::NormalizeDirPathPrefix(s); } if (splitDest != _info.SplitDest.Val) { _info.SplitDest.Def = true; _info.SplitDest.Val = splitDest; } #endif DirPath = s; #ifndef Z7_NO_REGISTRY _info.Paths.Clear(); #ifndef Z7_SFX AddUniqueString(_info.Paths, s); #endif for (int i = 0; i < _path.GetCount(); i++) if (i != currentItem) { UString sTemp; _path.GetLBText(i, sTemp); sTemp.Trim(); AddUniqueString(_info.Paths, sTemp); } _info.Save(); #endif CModalDialog::OnOK(); } #ifndef Z7_NO_REGISTRY #define kHelpTopic "fm/plugins/7-zip/extract.htm" void CExtractDialog::OnHelp() { ShowHelpWindow(kHelpTopic); CModalDialog::OnHelp(); } #endif tmp41wklro_/CPP/7zip/UI/GUI/ExtractDialog.h0000444000175000001440000000456314365514000021326 0ustar nabijaczleweliusers// ExtractDialog.h #ifndef ZIP7_INC_EXTRACT_DIALOG_H #define ZIP7_INC_EXTRACT_DIALOG_H #include "ExtractDialogRes.h" #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Edit.h" #include "../Common/ExtractMode.h" #include "../FileManager/DialogSize.h" #ifndef Z7_NO_REGISTRY #include "../Common/ZipRegistry.h" #endif namespace NExtractionDialog { /* namespace NFilesMode { enum EEnum { kSelected, kAll, kSpecified }; } */ } class CExtractDialog: public NWindows::NControl::CModalDialog { #ifdef Z7_NO_REGISTRY NWindows::NControl::CDialogChildControl _path; #else NWindows::NControl::CComboBox _path; #endif #ifndef Z7_SFX NWindows::NControl::CEdit _pathName; NWindows::NControl::CEdit _passwordControl; NWindows::NControl::CComboBox _pathMode; NWindows::NControl::CComboBox _overwriteMode; #endif #ifndef Z7_SFX // int GetFilesMode() const; void UpdatePasswordControl(); #endif void OnButtonSetPath(); void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); virtual bool OnInit() Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; virtual void OnOK() Z7_override; #ifndef Z7_NO_REGISTRY virtual void OnHelp() Z7_override; NExtract::CInfo _info; #endif bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); } public: // bool _enableSelectedFilesButton; // bool _enableFilesButton; // NExtractionDialog::NFilesMode::EEnum FilesMode; UString DirPath; UString ArcPath; #ifndef Z7_SFX UString Password; #endif bool PathMode_Force; bool OverwriteMode_Force; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; #ifndef Z7_SFX // CBoolPair AltStreams; CBoolPair NtSecurity; #endif CBoolPair ElimDup; INT_PTR Create(HWND aWndParent = NULL) { #ifdef Z7_SFX BIG_DIALOG_SIZE(240, 64); #else BIG_DIALOG_SIZE(300, 160); #endif return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent); } CExtractDialog(): PathMode_Force(false), OverwriteMode_Force(false) { ElimDup.Val = true; } }; #endif tmp41wklro_/CPP/7zip/UI/GUI/ExtractDialog.rc0000444000175000001440000000603412334076645021512 0ustar nabijaczleweliusers#include "ExtractDialogRes.h" #include "../../GuiCommon.rc" #define xc 336 #define yc 168 #undef g1xs #undef g2x #undef g2x2 #undef g2xs #undef g2xs2 #define g1xs 160 #define gSpace 20 #define g2x (m + g1xs + gSpace) #define g2x2 (g2x + m) #define g2xs (xc - g1xs - gSpace) #define g2xs2 (g2xs - m - m) #undef GROUP_Y_SIZE #ifdef UNDER_CE #define GROUP_Y_SIZE 8 #else #define GROUP_Y_SIZE 56 #endif IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Extract" BEGIN LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP CONTROL "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10 EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8 COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 84, g1xs, 10 LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8 COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO GROUPBOX "Password", IDG_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10 // CONTROL "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX, // g2x, m + 104, g2xs, 10 CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX, g2x, m + 104, g2xs, 10 DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys END #ifdef UNDER_CE #undef m #define m 4 #undef xc #undef yc #define xc 152 #define yc 128 #undef g1xs #define g1xs 64 IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Extract" BEGIN LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8 COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8 COMBOBOX IDC_EXTRACT_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8 COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO LTEXT "Password", IDG_PASSWORD, m, m + 76, g1xs, 8 EDITTEXT IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10 OK_CANCEL END #endif tmp41wklro_/CPP/7zip/UI/GUI/ExtractDialogRes.h0000444000175000001440000000130312567046521021777 0ustar nabijaczleweliusers#define IDD_EXTRACT 3400 #define IDD_EXTRACT_2 13400 #define IDC_EXTRACT_PATH 100 #define IDB_EXTRACT_SET_PATH 101 #define IDC_EXTRACT_PATH_MODE 102 #define IDC_EXTRACT_OVERWRITE_MODE 103 #define IDE_EXTRACT_PASSWORD 120 #define IDE_EXTRACT_NAME 130 #define IDX_EXTRACT_NAME_ENABLE 131 #define IDT_EXTRACT_EXTRACT_TO 3401 #define IDT_EXTRACT_PATH_MODE 3410 #define IDT_EXTRACT_OVERWRITE_MODE 3420 #define IDX_EXTRACT_ELIM_DUP 3430 #define IDX_EXTRACT_NT_SECUR 3431 // #define IDX_EXTRACT_ALT_STREAMS 3432 #define IDX_PASSWORD_SHOW 3803 #define IDG_PASSWORD 3807 tmp41wklro_/CPP/7zip/UI/GUI/ExtractGUI.cpp0000444000175000001440000001745214535565660021130 0ustar nabijaczleweliusers// ExtractGUI.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Thread.h" #include "../FileManager/ExtractCallback.h" #include "../FileManager/FormatUtils.h" #include "../FileManager/LangUtils.h" #include "../FileManager/resourceGui.h" #include "../FileManager/OverwriteDialogRes.h" #include "../Common/ArchiveExtractCallback.h" #include "../Common/PropIDUtils.h" #include "../Explorer/MyMessages.h" #include "resource2.h" #include "ExtractRes.h" #include "ExtractDialog.h" #include "ExtractGUI.h" #include "HashGUI.h" #include "../FileManager/PropertyNameRes.h" using namespace NWindows; using namespace NFile; using namespace NDir; static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path"; #ifndef Z7_SFX static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true) { AddLangString(s, resourceID); if (addColon) s.Add_Colon(); s.Add_Space(); s.Add_UInt64(value); s.Add_LF(); } static void AddSizePair(UString &s, UINT resourceID, UInt64 value) { AddLangString(s, resourceID); s += ": "; AddSizeValue(s, value); s.Add_LF(); } #endif class CThreadExtracting: public CProgressThreadVirt { HRESULT ProcessVirt() Z7_override; public: /* #ifdef Z7_EXTERNAL_CODECS const CExternalCodecs *externalCodecs; #endif */ CCodecs *codecs; CExtractCallbackImp *ExtractCallbackSpec; const CObjectVector *FormatIndices; const CIntVector *ExcludedFormatIndices; UStringVector *ArchivePaths; UStringVector *ArchivePathsFull; const NWildcard::CCensorNode *WildcardCensor; const CExtractOptions *Options; #ifndef Z7_SFX CHashBundle *HashBundle; virtual void ProcessWasFinished_GuiVirt() Z7_override; #endif CMyComPtr FolderArchiveExtractCallback; UString Title; CPropNameValPairs Pairs; }; #ifndef Z7_SFX void CThreadExtracting::ProcessWasFinished_GuiVirt() { if (HashBundle && !Pairs.IsEmpty()) ShowHashResults(Pairs, *this); } #endif HRESULT CThreadExtracting::ProcessVirt() { CDecompressStat Stat; #ifndef Z7_SFX /* if (HashBundle) HashBundle->Init(); */ #endif HRESULT res = Extract( /* #ifdef Z7_EXTERNAL_CODECS externalCodecs, #endif */ codecs, *FormatIndices, *ExcludedFormatIndices, *ArchivePaths, *ArchivePathsFull, *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallbackSpec, FolderArchiveExtractCallback, #ifndef Z7_SFX HashBundle, #endif FinalMessage.ErrorMessage.Message, Stat); #ifndef Z7_SFX if (res == S_OK && ExtractCallbackSpec->IsOK()) { if (HashBundle) { AddValuePair(Pairs, IDS_ARCHIVES_COLON, Stat.NumArchives); AddSizeValuePair(Pairs, IDS_PROP_PACKED_SIZE, Stat.PackSize); AddHashBundleRes(Pairs, *HashBundle); } else if (Options->TestMode) { UString s; AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false); AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize); if (Stat.NumFolders != 0) AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders); AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles); AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize); if (Stat.NumAltStreams != 0) { s.Add_LF(); AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams); AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize); } s.Add_LF(); AddLangString(s, IDS_MESSAGE_NO_ERRORS); FinalMessage.OkMessage.Title = Title; FinalMessage.OkMessage.Message = s; } } #endif return res; } HRESULT ExtractGUI( // DECL_EXTERNAL_CODECS_LOC_VARS CCodecs *codecs, const CObjectVector &formatIndices, const CIntVector &excludedFormatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, CExtractOptions &options, #ifndef Z7_SFX CHashBundle *hb, #endif bool showDialog, bool &messageWasDisplayed, CExtractCallbackImp *extractCallback, HWND hwndParent) { messageWasDisplayed = false; CThreadExtracting extracter; /* #ifdef Z7_EXTERNAL_CODECS extracter.externalCodecs = _externalCodecs; #endif */ extracter.codecs = codecs; extracter.FormatIndices = &formatIndices; extracter.ExcludedFormatIndices = &excludedFormatIndices; if (!options.TestMode) { FString outputDir = options.OutputDir; #ifndef UNDER_CE if (outputDir.IsEmpty()) GetCurrentDir(outputDir); #endif if (showDialog) { CExtractDialog dialog; FString outputDirFull; if (!MyGetFullPathName(outputDir, outputDirFull)) { ShowErrorMessage(kIncorrectOutDir); messageWasDisplayed = true; return E_FAIL; } NName::NormalizeDirPathPrefix(outputDirFull); dialog.DirPath = fs2us(outputDirFull); dialog.OverwriteMode = options.OverwriteMode; dialog.OverwriteMode_Force = options.OverwriteMode_Force; dialog.PathMode = options.PathMode; dialog.PathMode_Force = options.PathMode_Force; dialog.ElimDup = options.ElimDup; if (archivePathsFull.Size() == 1) dialog.ArcPath = archivePathsFull[0]; #ifndef Z7_SFX // dialog.AltStreams = options.NtOptions.AltStreams; dialog.NtSecurity = options.NtOptions.NtSecurity; if (extractCallback->PasswordIsDefined) dialog.Password = extractCallback->Password; #endif if (dialog.Create(hwndParent) != IDOK) return E_ABORT; outputDir = us2fs(dialog.DirPath); options.OverwriteMode = dialog.OverwriteMode; options.PathMode = dialog.PathMode; options.ElimDup = dialog.ElimDup; #ifndef Z7_SFX // options.NtOptions.AltStreams = dialog.AltStreams; options.NtOptions.NtSecurity = dialog.NtSecurity; extractCallback->Password = dialog.Password; extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty(); #endif } if (!MyGetFullPathName(outputDir, options.OutputDir)) { ShowErrorMessage(kIncorrectOutDir); messageWasDisplayed = true; return E_FAIL; } NName::NormalizeDirPathPrefix(options.OutputDir); /* if (!CreateComplexDirectory(options.OutputDir)) { UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError())); UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, #ifdef Z7_LANG 0x02000603, #endif options.OutputDir); s2.Add_LF(); s2 += s; MyMessageBox(s2); return E_FAIL; } */ } UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING); extracter.Title = title; extracter.ExtractCallbackSpec = extractCallback; extracter.ExtractCallbackSpec->ProgressDialog = &extracter; extracter.FolderArchiveExtractCallback = extractCallback; extracter.ExtractCallbackSpec->Init(); extracter.CompressingMode = false; extracter.ArchivePaths = &archivePaths; extracter.ArchivePathsFull = &archivePathsFull; extracter.WildcardCensor = &wildcardCensor; extracter.Options = &options; #ifndef Z7_SFX extracter.HashBundle = hb; #endif extracter.IconID = IDI_ICON; RINOK(extracter.Create(title, hwndParent)) messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed; return extracter.Result; } tmp41wklro_/CPP/7zip/UI/GUI/ExtractGUI.h0000444000175000001440000000204114365514000020540 0ustar nabijaczleweliusers// GUI/ExtractGUI.h #ifndef ZIP7_INC_EXTRACT_GUI_H #define ZIP7_INC_EXTRACT_GUI_H #include "../Common/Extract.h" #include "../FileManager/ExtractCallback.h" /* RESULT can be S_OK, even if there are errors!!! if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI(). RESULT = E_ABORT - user break. RESULT != E_ABORT: { messageWasDisplayed = true - message was displayed already. messageWasDisplayed = false - there was some internal error, so you must show error message. } */ HRESULT ExtractGUI( // DECL_EXTERNAL_CODECS_LOC_VARS CCodecs *codecs, const CObjectVector &formatIndices, const CIntVector &excludedFormatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, CExtractOptions &options, #ifndef Z7_SFX CHashBundle *hb, #endif bool showDialog, bool &messageWasDisplayed, CExtractCallbackImp *extractCallback, HWND hwndParent = NULL); #endif tmp41wklro_/CPP/7zip/UI/GUI/ExtractRes.h0000444000175000001440000000373712503766357020702 0ustar nabijaczleweliusers#define IDS_MEM_ERROR 3000 #define IDS_CANNOT_CREATE_FOLDER 3003 #define IDS_UPDATE_NOT_SUPPORTED 3004 #define IDS_CANT_OPEN_ARCHIVE 3005 #define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006 #define IDS_UNSUPPORTED_ARCHIVE_TYPE 3007 #define IDS_CANT_OPEN_AS_TYPE 3017 #define IDS_IS_OPEN_AS_TYPE 3018 #define IDS_IS_OPEN_WITH_OFFSET 3019 #define IDS_PROGRESS_EXTRACTING 3300 #define IDS_PROGRESS_SKIPPING 3325 #define IDS_EXTRACT_SET_FOLDER 3402 #define IDS_EXTRACT_PATHS_FULL 3411 #define IDS_EXTRACT_PATHS_NO 3412 #define IDS_EXTRACT_PATHS_ABS 3413 #define IDS_PATH_MODE_RELAT 3414 #define IDS_EXTRACT_OVERWRITE_ASK 3421 #define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT 3422 #define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING 3423 #define IDS_EXTRACT_OVERWRITE_RENAME 3424 #define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425 #define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 3700 #define IDS_EXTRACT_MESSAGE_DATA_ERROR 3701 #define IDS_EXTRACT_MESSAGE_CRC_ERROR 3702 #define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703 #define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704 #define IDS_EXTRACT_MSG_WRONG_PSW_GUESS 3710 // #define IDS_EXTRACT_MSG_ENCRYPTED 3711 #define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721 #define IDS_EXTRACT_MSG_DATA_ERROR 3722 #define IDS_EXTRACT_MSG_CRC_ERROR 3723 #define IDS_EXTRACT_MSG_UNAVAILABLE_DATA 3724 #define IDS_EXTRACT_MSG_UEXPECTED_END 3725 #define IDS_EXTRACT_MSG_DATA_AFTER_END 3726 #define IDS_EXTRACT_MSG_IS_NOT_ARC 3727 #define IDS_EXTRACT_MSG_HEADERS_ERROR 3728 #define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM 3729 #define IDS_OPEN_MSG_UNAVAILABLE_START 3763 #define IDS_OPEN_MSG_UNCONFIRMED_START 3764 #define IDS_OPEN_MSG_UNSUPPORTED_FEATURE 3768 tmp41wklro_/CPP/7zip/UI/GUI/HashGUI.h0000444000175000001440000000150514357314620020024 0ustar nabijaczleweliusers// HashGUI.h #ifndef ZIP7_INC_HASH_GUI_H #define ZIP7_INC_HASH_GUI_H #include "../Common/HashCalc.h" #include "../Common/Property.h" HRESULT HashCalcGUI( DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor &censor, const CHashOptions &options, bool &messageWasDisplayed); typedef CObjectVector CPropNameValPairs; void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value); void AddSizeValue(UString &s, UInt64 value); void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value); void AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb); void AddHashBundleRes(UString &s, const CHashBundle &hb); void ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd); void ShowHashResults(const CHashBundle &hb, HWND hwnd); #endif tmp41wklro_/CPP/7zip/UI/GUI/resource2.h0000444000175000001440000000012011563433010020464 0ustar nabijaczleweliusers#define IDS_PROGRESS_COMPRESSING 3301 #define IDS_ARCHIVES_COLON 3907 tmp41wklro_/CPP/7zip/var_clang.mak0000444000175000001440000000022714042243601020077 0ustar nabijaczleweliusersPLATFORM= O=b/c IS_X64= IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM= CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/var_clang_arm64.mak0000444000175000001440000000047014576475540021135 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/c_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= MY_ARCH=-march=armv8-a MY_ARCH=-march=armv8-a+crypto+crc MY_ARCH=-march=armv8.3-a+crypto+crc MY_ARCH= USE_ASM= USE_ASM=1 ASM_FLAGS=-Wno-unused-macros CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/var_clang_x64.mak0000444000175000001440000000025014555702460020610 0ustar nabijaczleweliusersPLATFORM=x64 O=b/c_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/var_clang_x86.mak0000444000175000001440000000025414555702460020620 0ustar nabijaczleweliusersPLATFORM=x86 O=b/c_$(PLATFORM) IS_X64= IS_X86=1 IS_ARM64= CROSS_COMPILE= MY_ARCH=-m32 USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/var_gcc.mak0000444000175000001440000000024314042243561017552 0ustar nabijaczleweliusersPLATFORM= O=b/g IS_X64= IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH= USE_ASM= CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ # -march=armv8-a+crc+crypto tmp41wklro_/CPP/7zip/var_gcc_arm64.mak0000444000175000001440000000030714042243001020551 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/g_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= MY_ARCH=-mtune=cortex-a53 USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ # -march=armv8-a+crc+crypto tmp41wklro_/CPP/7zip/var_gcc_x64.mak0000444000175000001440000000026314555134000020251 0ustar nabijaczleweliusersPLATFORM=x64 O=b/g_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH=-mavx512f -mavx512vl MY_ARCH= USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ tmp41wklro_/CPP/7zip/var_gcc_x86.mak0000444000175000001440000000023114555702460020263 0ustar nabijaczleweliusersPLATFORM=x86 O=b/g_$(PLATFORM) IS_X64= IS_X86=1 IS_ARM64= CROSS_COMPILE= MY_ARCH=-m32 USE_ASM=1 CC=$(CROSS_COMPILE)gcc CXX=$(CROSS_COMPILE)g++ tmp41wklro_/CPP/7zip/var_mac_arm64.mak0000444000175000001440000000037414576504560020607 0ustar nabijaczleweliusersPLATFORM=arm64 O=b/m_$(PLATFORM) IS_X64= IS_X86= IS_ARM64=1 CROSS_COMPILE= #use this code to reduce features MY_ARCH=-arch arm64 -march=armv8-a MY_ARCH=-arch arm64 USE_ASM=1 CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/var_mac_x64.mak0000444000175000001440000000026314042243132020253 0ustar nabijaczleweliusersPLATFORM=x64 O=b/m_$(PLATFORM) IS_X64=1 IS_X86= IS_ARM64= CROSS_COMPILE= MY_ARCH=-arch x86_64 USE_ASM= CC=$(CROSS_COMPILE)clang CXX=$(CROSS_COMPILE)clang++ USE_CLANG=1 tmp41wklro_/CPP/7zip/warn_clang.mak0000444000175000001440000000013414425357320020264 0ustar nabijaczleweliusersCFLAGS_WARN = -Weverything -Wfatal-errors # CXX_STD_FLAGS = -std=c++11 # CXX_STD_FLAGS = tmp41wklro_/CPP/7zip/warn_clang_mac.mak0000444000175000001440000000042014425357320021102 0ustar nabijaczleweliusersCFLAGS_WARN = -Weverything -Wfatal-errors -Wno-poison-system-directories CXX_STD_FLAGS = -std=c++98 CXX_STD_FLAGS = -std=c++11 CXX_STD_FLAGS = -std=c++14 CXX_STD_FLAGS = -std=c++17 CXX_STD_FLAGS = -std=c++20 CXX_STD_FLAGS = -std=c++23 CXX_STD_FLAGS = -std=c++11 tmp41wklro_/CPP/7zip/warn_gcc.mak0000444000175000001440000000176614576504560017757 0ustar nabijaczleweliusersCFLAGS_WARN_GCC_4_8 = \ -Waddress \ -Waggressive-loop-optimizations \ -Wattributes \ -Wcast-align \ -Wcomment \ -Wdiv-by-zero \ -Wformat-contains-nul \ -Winit-self \ -Wint-to-pointer-cast \ -Wunused \ -Wunused-macros \ CFLAGS_WARN_GCC_6 = $(CFLAGS_WARN_GCC_4_8)\ -Wbool-compare \ -Wduplicated-cond \ # -Wno-strict-aliasing CFLAGS_WARN_GCC_9 = $(CFLAGS_WARN_GCC_6)\ -Waddress-of-packed-member \ -Wbool-operation \ -Wcast-align=strict \ -Wconversion \ -Wdangling-else \ -Wduplicated-branches \ -Wimplicit-fallthrough=5 \ -Wint-in-bool-context \ -Wmaybe-uninitialized \ -Wmisleading-indentation \ -Wmissing-attributes # In C: -Wsign-conversion enabled also by -Wconversion # -Wno-sign-conversion \ CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ -Wno-strict-aliasing \ CFLAGS_WARN = $(CFLAGS_WARN_GCC_4_8) CFLAGS_WARN = $(CFLAGS_WARN_GCC_6) CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) # CXX_STD_FLAGS = -std=c++11 # CXX_STD_FLAGS = tmp41wklro_/CPP/Build.mak0000444000175000001440000001213714614700100016311 0ustar nabijaczleweliusersLIBS = $(LIBS) oleaut32.lib ole32.lib # CFLAGS = $(CFLAGS) -DZ7_NO_UNICODE !IFNDEF MY_NO_UNICODE # CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE !ENDIF !IF "$(CC)" != "clang-cl" # for link time code generation: # CFLAGS = $(CFLAGS) -GL !ENDIF !IFNDEF O !IFDEF PLATFORM O=$(PLATFORM) !ELSE O=o !ENDIF !ENDIF !IF "$(CC)" != "clang-cl" # CFLAGS = $(CFLAGS) -FAsc -Fa$O/asm/ !ENDIF # LFLAGS = $(LFLAGS) /guard:cf !IF "$(PLATFORM)" == "x64" MY_ML = ml64 -WX #-Dx64 !ELSEIF "$(PLATFORM)" == "arm64" MY_ML = armasm64 !ELSEIF "$(PLATFORM)" == "arm" MY_ML = armasm -WX !ELSE MY_ML = ml -WX # -DABI_CDECL !ENDIF # MY_ML = "$(MY_ML) -Fl$O\asm\ !IFDEF UNDER_CE RFLAGS = $(RFLAGS) -dUNDER_CE !IFDEF MY_CONSOLE LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup !ENDIF !ELSE !IFDEF OLD_COMPILER LFLAGS = $(LFLAGS) -OPT:NOWIN98 !ENDIF !IF "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" CFLAGS = $(CFLAGS) -Gr !ENDIF LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib !ENDIF !IF "$(PLATFORM)" == "arm" COMPL_ASM = $(MY_ML) $** $O/$(*B).obj !ELSEIF "$(PLATFORM)" == "arm64" COMPL_ASM = $(MY_ML) $** $O/$(*B).obj !ELSE COMPL_ASM = $(MY_ML) -c -Fo$O/ $** !ENDIF !IFDEF OLD_COMPILER CFLAGS_WARN_LEVEL = -W4 !ELSE CFLAGS_WARN_LEVEL = -Wall !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ $(CFLAGS_WARN_LEVEL) -WX -EHsc -Gy -GR- -GF !IF "$(CC)" == "clang-cl" CFLAGS = $(CFLAGS) \ -Werror \ -Wall \ -Wextra \ -Weverything \ -Wfatal-errors \ !ENDIF # !IFDEF MY_DYNAMIC_LINK !IF "$(MY_DYNAMIC_LINK)" != "" CFLAGS = $(CFLAGS) -MD !ELSE !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ENDIF CFLAGS = $(CFLAGS_COMMON) $(CFLAGS) !IFNDEF OLD_COMPILER CFLAGS = $(CFLAGS) -GS- -Zc:wchar_t !IFDEF VCTOOLSVERSION !IF "$(VCTOOLSVERSION)" >= "14.00" !IF "$(CC)" != "clang-cl" CFLAGS = $(CFLAGS) -Zc:throwingNew !ENDIF !ENDIF !ELSE # -Zc:forScope is default in VS2010. so we need it only for older versions CFLAGS = $(CFLAGS) -Zc:forScope !ENDIF !IFNDEF UNDER_CE !IF "$(CC)" != "clang-cl" CFLAGS = $(CFLAGS) -MP4 !ENDIF !IFNDEF PLATFORM # CFLAGS = $(CFLAGS) -arch:IA32 !ENDIF !ENDIF !ENDIF !IFDEF MY_CONSOLE CFLAGS = $(CFLAGS) -D_CONSOLE !ENDIF !IFNDEF UNDER_CE !IF "$(PLATFORM)" == "arm" CFLAGS = $(CFLAGS) -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE !ENDIF !ENDIF !IF "$(PLATFORM)" == "x64" CFLAGS_O1 = $(CFLAGS) -O1 !ELSE CFLAGS_O1 = $(CFLAGS) -O1 !ENDIF CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF -INCREMENTAL:NO !IFNDEF UNDER_CE LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE !ENDIF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ELSE !IF defined(MY_FIXED) && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" LFLAGS = $(LFLAGS) /FIXED !ELSE LFLAGS = $(LFLAGS) /FIXED:NO !ENDIF # /BASE:0x400000 !ENDIF !IF "$(PLATFORM)" == "arm64" # we can get better compression ratio with ARM64 filter if we change alignment to 4096 # LFLAGS = $(LFLAGS) /FILEALIGN:4096 !ENDIF # !IF "$(PLATFORM)" == "x64" !IFDEF SUB_SYS_VER MY_SUB_SYS_VER=5.02 !IFDEF MY_CONSOLE LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) !ELSE LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) !ENDIF !ENDIF !IF "$(PLATFORM)" == "arm64" CLANG_FLAGS_TARGET = --target=arm64-pc-windows-msvc !ENDIF COMPL_CLANG_SPEC=clang-cl $(CLANG_FLAGS_TARGET) COMPL_ASM_CLANG = $(COMPL_CLANG_SPEC) -nologo -c -Fo$O/ $(CFLAGS_WARN_LEVEL) -WX $** # COMPL_C_CLANG = $(COMPL_CLANG_SPEC) $(CFLAGS_O2) PROGPATH = $O\$(PROG) COMPL_O1 = $(CC) $(CFLAGS_O1) $** COMPL_O2 = $(CC) $(CFLAGS_O2) $** COMPL_PCH = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** COMPLB = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $< COMPLB_O2 = $(CC) $(CFLAGS_O2) $< # COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $< CFLAGS_C_ALL = $(CFLAGS_O2) $(CFLAGS_C_SPEC) CCOMPL_PCH = $(CC) $(CFLAGS_C_ALL) -Yc"Precomp.h" -Fp$O/a.pch $** CCOMPL_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $** CCOMPLB_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $< CCOMPL = $(CC) $(CFLAGS_C_ALL) $** CCOMPLB = $(CC) $(CFLAGS_C_ALL) $< !IF "$(CC)" == "clang-cl" COMPL = $(COMPL) -FI StdAfx.h COMPLB = $(COMPLB) -FI StdAfx.h CCOMPL_USE = $(CCOMPL_USE) -FI Precomp.h CCOMPLB_USE = $(CCOMPLB_USE) -FI Precomp.h !ENDIF all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O\*.asm $O: if not exist "$O" mkdir "$O" $O/asm: if not exist "$O/asm" mkdir "$O/asm" !IF "$(CC)" != "clang-cl" # for link time code generation: # LFLAGS = $(LFLAGS) -LTCG !ENDIF $(PROGPATH): $O $O/asm $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) !IFNDEF NO_DEFAULT_RES $O\resource.res: $(*B).rc rc $(RFLAGS) -fo$@ $** !ENDIF $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) predef: empty.c $(CCOMPL) /EP /Zc:preprocessor /PD predef2: A.cpp $(COMPL) -EP -Zc:preprocessor -PD predef3: A.cpp $(COMPL) -E -dM predef4: A.cpp $(COMPL_O2) -E tmp41wklro_/CPP/Common/0000700000175000001440000000000014706260545016014 5ustar nabijaczleweliuserstmp41wklro_/CPP/Common/AutoPtr.h0000444000175000001440000000155314556451140017573 0ustar nabijaczleweliusers// Common/AutoPtr.h #ifndef ZIP7_INC_COMMON_AUTOPTR_H #define ZIP7_INC_COMMON_AUTOPTR_H template class CMyUniquePtr // CMyAutoPtr { T *_p; CMyUniquePtr(CMyUniquePtr& p); // : _p(p.release()) {} CMyUniquePtr& operator=(T *p); CMyUniquePtr& operator=(CMyUniquePtr& p); /* { reset(p.release()); return (*this); } */ void reset(T* p = NULL) { if (p != _p) delete _p; _p = p; } public: CMyUniquePtr(T *p = NULL) : _p(p) {} ~CMyUniquePtr() { delete _p; } T& operator*() const { return *_p; } T* operator->() const { return _p; } // operator bool() const { return _p != NULL; } T* get() const { return _p; } T* release() { T *tmp = _p; _p = NULL; return tmp; } void Create_if_Empty() { if (!_p) _p = new T; } }; #endif tmp41wklro_/CPP/Common/CommandLineParser.cpp0000444000175000001440000001122114615645220022064 0ustar nabijaczleweliusers// CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { #ifdef _WIN32 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; unsigned i; for (i = 0; i < src.Len(); i++) { const wchar_t c = src[i]; if ((c == L' ' || c == L'\t') && !quoteMode) { dest2 = src.Ptr(i + 1); return i != 0; } if (c == L'\"') quoteMode = !quoteMode; else dest1 += c; } return i != 0; } void SplitCommandLine(const UString &s, UStringVector &parts) { #if 0 /* we don't use CommandLineToArgvW() because it can remove tail backslash: "1\" converted to 1" */ parts.Clear(); { int nArgs; LPWSTR *szArgList = CommandLineToArgvW(s, &nArgs); if (szArgList) { for (int i = 0; i < nArgs; i++) { // printf("%2d: |%S|\n", i, szArglist[i]); parts.Add(szArgList[i]); } LocalFree(szArgList); return; } } #endif /* #ifdef _UNICODE throw 20240406; #else */ UString sTemp (s); sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; if (SplitCommandLine(sTemp, s1, s2)) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } // #endif } #endif static const char * const kStopSwitchParsing = "--"; static bool inline IsItSwitchChar(wchar_t c) { return (c == '-'); } CParser::CParser(): _switches(NULL), StopSwitchIndex(-1) { } CParser::~CParser() { delete []_switches; } // if (s) contains switch then function updates switch structures // out: true, if (s) is a switch bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches) { if (s.IsEmpty() || !IsItSwitchChar(s[0])) return false; unsigned pos = 1; unsigned switchIndex = 0; int maxLen = -1; for (unsigned i = 0; i < numSwitches; i++) { const char * const key = switchForms[i].Key; const unsigned switchLen = MyStringLen(key); if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) continue; if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) { switchIndex = i; maxLen = (int)switchLen; } } if (maxLen < 0) { ErrorMessage = "Unknown switch:"; return false; } pos += (unsigned)maxLen; CSwitchResult &sw = _switches[switchIndex]; const CSwitchForm &form = switchForms[switchIndex]; if (!form.Multi && sw.ThereIs) { ErrorMessage = "Multiple instances for switch:"; return false; } sw.ThereIs = true; const unsigned rem = s.Len() - pos; if (rem < form.MinLen) { ErrorMessage = "Too short switch:"; return false; } sw.WithMinus = false; sw.PostCharIndex = -1; switch (form.Type) { case NSwitchType::kMinus: if (rem == 1) { sw.WithMinus = (s[pos] == '-'); if (sw.WithMinus) return true; ErrorMessage = "Incorrect switch postfix:"; return false; } break; case NSwitchType::kChar: if (rem == 1) { const wchar_t c = s[pos]; if (c <= 0x7F) { sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); if (sw.PostCharIndex >= 0) return true; } ErrorMessage = "Incorrect switch postfix:"; return false; } break; case NSwitchType::kString: { sw.PostStrings.Add(s.Ptr(pos)); return true; } // case NSwitchType::kSimple: default: break; } if (pos != s.Len()) { ErrorMessage = "Too long switch:"; return false; } return true; } bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings) { StopSwitchIndex = -1; ErrorMessage.Empty(); ErrorLine.Empty(); NonSwitchStrings.Clear(); delete []_switches; _switches = NULL; _switches = new CSwitchResult[numSwitches]; FOR_VECTOR (i, commandStrings) { const UString &s = commandStrings[i]; if (StopSwitchIndex < 0) { if (s.IsEqualTo(kStopSwitchParsing)) { StopSwitchIndex = (int)NonSwitchStrings.Size(); continue; } if (!s.IsEmpty() && IsItSwitchChar(s[0])) { if (ParseString(s, switchForms, numSwitches)) continue; ErrorLine = s; return false; } } NonSwitchStrings.Add(s); } return true; } } tmp41wklro_/CPP/Common/CommandLineParser.h0000444000175000001440000000242714357314620021541 0ustar nabijaczleweliusers// Common/CommandLineParser.h #ifndef ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H #define ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H #include "MyString.h" namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kMinus, kString, kChar }; } struct CSwitchForm { const char *Key; Byte Type; bool Multi; Byte MinLen; // int MaxLen; const char *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; int PostCharIndex; UStringVector PostStrings; CSwitchResult(): ThereIs(false) {} }; class CParser { CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches); public: UStringVector NonSwitchStrings; int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--" AString ErrorMessage; UString ErrorLine; CParser(); ~CParser(); bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings); const CSwitchResult& operator[](unsigned index) const { return _switches[index]; } }; } #endif tmp41wklro_/CPP/Common/Common.h0000444000175000001440000000127614554701240017424 0ustar nabijaczleweliusers// Common.h #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #ifndef ZIP7_INC_COMMON_H #define ZIP7_INC_COMMON_H #include "../../C/Precomp.h" #include "Common0.h" #include "MyWindows.h" /* This file is included to all cpp files in 7-Zip. Each folder contains StdAfx.h file that includes "Common.h". So 7-Zip includes "Common.h" in both modes: with precompiled StdAfx.h and without precompiled StdAfx.h include "Common.h" before other h files of 7-zip, if you need predefined macros. do not include "Common.h", if you need only interfaces, and you don't need predefined macros. */ #endif tmp41wklro_/CPP/Common/Common0.h0000444000175000001440000002565714567060440017521 0ustar nabijaczleweliusers// Common0.h #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #ifndef ZIP7_INC_COMMON0_H #define ZIP7_INC_COMMON0_H #include "../../C/Compiler.h" /* This file contains compiler related things for cpp files. This file is included to all cpp files in 7-Zip via "Common.h". Also this file is included in "IDecl.h" (that is included in interface files). So external modules can use 7-Zip interfaces without predefined macros defined in "Common.h". */ #ifdef _MSC_VER #pragma warning(disable : 4710) // function not inlined // 'CUncopyable::CUncopyable': #pragma warning(disable : 4514) // unreferenced inline function has been removed #if _MSC_VER < 1300 #pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4714) // function marked as __forceinline not inlined #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information #endif #if _MSC_VER < 1400 #pragma warning(disable : 4511) // copy constructor could not be generated // #pragma warning(disable : 4512) // assignment operator could not be generated #pragma warning(disable : 4512) // assignment operator could not be generated #endif #if _MSC_VER > 1400 && _MSC_VER <= 1900 // #pragma warning(disable : 4996) // strcat: This function or variable may be unsafe // GetVersion was declared deprecated #endif #if _MSC_VER > 1200 // -Wall warnings #if _MSC_VER <= 1600 #pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace #endif // #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label // #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden #pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted #pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted #if _MSC_VER >= 1600 && _MSC_VER < 1920 #pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught #endif #if _MSC_VER >= 1600 #pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch #endif #if _MSC_VER < 1800 // we disable the warning, if we don't use 'final' in class #pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual #endif #if _MSC_VER >= 1900 #pragma warning(disable : 5026) // move constructor was implicitly defined as deleted #pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted #endif #if _MSC_VER >= 1912 #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception. #endif #if _MSC_VER >= 1925 // #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly #endif #if _MSC_VER >= 1934 // #pragma warning(disable : 5264) // const variable is not used #endif #endif // _MSC_VER > 1200 #endif // _MSC_VER #if defined(_MSC_VER) // && !defined(__clang__) #define Z7_DECLSPEC_NOTHROW __declspec(nothrow) #elif defined(__clang__) || defined(__GNUC__) #define Z7_DECLSPEC_NOTHROW __attribute__((nothrow)) #else #define Z7_DECLSPEC_NOTHROW #endif /* #if defined (_MSC_VER) && _MSC_VER >= 1900 \ || defined(__clang__) && __clang_major__ >= 6 \ || defined(__GNUC__) && __GNUC__ >= 6 #define Z7_noexcept noexcept #else #define Z7_noexcept throw() #endif */ #if defined(__clang__) #if /* defined(_WIN32) && */ __clang_major__ >= 16 #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" #endif #if __clang_major__ >= 4 && __clang_major__ < 12 && !defined(_WIN32) /* if compiled with new GCC libstdc++, GCC libstdc++ can use: 13.2.0/include/c++/ : #define _NEW : #define _GLIBCXX_STDLIB_H 1 */ #pragma GCC diagnostic ignored "-Wreserved-id-macro" #endif // noexcept, final, = delete #pragma GCC diagnostic ignored "-Wc++98-compat" #if __clang_major__ >= 4 // throw() dynamic exception specifications are deprecated #pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec" #endif #if __clang_major__ <= 6 // check it #pragma GCC diagnostic ignored "-Wsign-conversion" #endif #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wglobal-constructors" #pragma GCC diagnostic ignored "-Wexit-time-destructors" #if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC #pragma GCC diagnostic ignored "-Wswitch-default" #endif // #pragma GCC diagnostic ignored "-Wunused-private-field" // #pragma GCC diagnostic ignored "-Wnonportable-system-include-path" // #pragma GCC diagnostic ignored "-Wsuggest-override" // #pragma GCC diagnostic ignored "-Wsign-conversion" // #pragma GCC diagnostic ignored "-Winconsistent-missing-override" // #pragma GCC diagnostic ignored "-Wsuggest-destructor-override" // #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" // #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-dtor" // #pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor" // #ifndef _WIN32 // #pragma GCC diagnostic ignored "-Wweak-vtables" // #endif /* #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) \ || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000) // enumeration values not explicitly handled in switch #pragma GCC diagnostic ignored "-Wswitch-enum" #endif */ #endif // __clang__ #ifdef __GNUC__ // #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" #endif /* There is BUG in MSVC 6.0 compiler for operator new[]: It doesn't check overflow, when it calculates size in bytes for allocated array. So we can use Z7_ARRAY_NEW macro instead of new[] operator. */ #if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) #define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)]; #else #define Z7_ARRAY_NEW(p, T, size) p = new T[size]; #endif #if (defined(__GNUC__) && (__GNUC__ >= 8)) #define Z7_ATTR_NORETURN __attribute__((noreturn)) #elif (defined(__clang__) && (__clang_major__ >= 3)) #if __has_feature(cxx_attributes) #define Z7_ATTR_NORETURN [[noreturn]] #else #define Z7_ATTR_NORETURN __attribute__((noreturn)) #endif #elif (defined(_MSC_VER) && (_MSC_VER >= 1900)) #define Z7_ATTR_NORETURN [[noreturn]] #else #define Z7_ATTR_NORETURN #endif // final in "GCC 4.7.0" // In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.) #if defined (__cplusplus) && __cplusplus >= 201103L \ || defined(_MSC_VER) && _MSC_VER >= 1800 \ || defined(__clang__) && __clang_major__ >= 4 \ /* || defined(__GNUC__) && __GNUC__ >= 9 */ #define Z7_final final #if defined(__clang__) && __cplusplus < 201103L #pragma GCC diagnostic ignored "-Wc++11-extensions" #endif #elif defined (__cplusplus) && __cplusplus >= 199711L \ && defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__) #define Z7_final __final #else #define Z7_final #if defined(__clang__) && __clang_major__ >= 4 \ || defined(__GNUC__) && __GNUC__ >= 4 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" #endif #endif #define Z7_class_final(c) class c Z7_final #if defined (__cplusplus) && __cplusplus >= 201103L \ || (defined(_MSC_VER) && _MSC_VER >= 1800) #define Z7_CPP_IS_SUPPORTED_default #define Z7_eq_delete = delete // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default; #else #define Z7_eq_delete // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) #endif #if defined(__cplusplus) && (__cplusplus >= 201103L) \ || defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \ || defined(__clang__) && __clang_major__ >= 4 #if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */ #pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override' #define Z7_DESTRUCTOR_override #else #define Z7_DESTRUCTOR_override override #endif #define Z7_override override #else #define Z7_override #define Z7_DESTRUCTOR_override #endif #define Z7_CLASS_NO_COPY(cls) \ private: \ cls(const cls &) Z7_eq_delete; \ cls &operator=(const cls &) Z7_eq_delete; class CUncopyable { protected: CUncopyable() {} // allow constructor // ~CUncopyable() {} Z7_CLASS_NO_COPY(CUncopyable) }; #define MY_UNCOPYABLE :private CUncopyable // #define MY_UNCOPYABLE // typedef void (*Z7_void_Function)(void); #if defined(__clang__) || defined(__GNUC__) #define Z7_CAST_FUNC(t, e) reinterpret_cast(reinterpret_cast(e)) #else #define Z7_CAST_FUNC(t, e) reinterpret_cast(reinterpret_cast(e)) // #define Z7_CAST_FUNC(t, e) reinterpret_cast(e) #endif #define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name) \ Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name)) // || defined(__clang__) // || defined(__GNUC__) #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define Z7_DECLSPEC_NOVTABLE __declspec(novtable) #else #define Z7_DECLSPEC_NOVTABLE #endif #ifdef __clang__ #define Z7_PURE_INTERFACES_BEGIN \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") _Pragma("GCC diagnostic ignored \"-Wweak-vtables\"") #define Z7_PURE_INTERFACES_END \ _Pragma("GCC diagnostic pop") #else #define Z7_PURE_INTERFACES_BEGIN #define Z7_PURE_INTERFACES_END #endif // NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers #include "NewHandler.h" /* // #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) Z7_ARRAY_SIZE(a) #endif */ #endif // ZIP7_INC_COMMON0_H // #define Z7_REDEFINE_NULL #if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */ // NULL is defined in #include #undef NULL #ifdef __cplusplus #if defined (__cplusplus) && __cplusplus >= 201103L \ || (defined(_MSC_VER) && _MSC_VER >= 1800) #define NULL nullptr #else #define NULL 0 #endif #else #define NULL ((void *)0) #endif #else // Z7_REDEFINE_NULL #if defined(__clang__) && __clang_major__ >= 5 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #endif // Z7_REDEFINE_NULL // for precompiler: // #include "MyWindows.h" tmp41wklro_/CPP/Common/ComTry.h0000444000175000001440000000100014357314620017375 0ustar nabijaczleweliusers// ComTry.h #ifndef ZIP7_INC_COM_TRY_H #define ZIP7_INC_COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } /* #define COM_TRY_END } \ catch(const CNewException &) { return E_OUTOFMEMORY; } \ catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \ */ // catch(const CSystemException &e) { return e.ErrorCode; } // catch(...) { return E_FAIL; } #endif tmp41wklro_/CPP/Common/CRC.cpp0000444000175000001440000000024314002751526017127 0ustar nabijaczleweliusers// Common/CRC.cpp #include "StdAfx.h" #include "../../C/7zCrc.h" static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; tmp41wklro_/CPP/Common/CrcReg.cpp0000444000175000001440000000310314534573460017674 0ustar nabijaczleweliusers// CrcReg.cpp #include "StdAfx.h" #include "../../C/7zCrc.h" #include "../../C/CpuArch.h" #include "../Common/MyCom.h" #include "../7zip/Common/RegisterCodec.h" EXTERN_C_BEGIN EXTERN_C_END Z7_CLASS_IMP_COM_2( CCrcHasher , IHasher , ICompressSetCoderProperties ) UInt32 _crc; Z7_CRC_UPDATE_FUNC _updateFunc; Z7_CLASS_NO_COPY(CCrcHasher) bool SetFunctions(UInt32 tSize); public: Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); } }; bool CCrcHasher::SetFunctions(UInt32 tSize) { const Z7_CRC_UPDATE_FUNC f = z7_GetFunc_CrcUpdate(tSize); if (!f) { _updateFunc = CrcUpdate; return false; } _updateFunc = f; return true; } Z7_COM7F_IMF(CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { for (UInt32 i = 0; i < numProps; i++) { if (propIDs[i] == NCoderPropID::kDefaultProp) { const PROPVARIANT &prop = coderProps[i]; if (prop.vt != VT_UI4) return E_INVALIDARG; if (!SetFunctions(prop.ulVal)) return E_NOTIMPL; } } return S_OK; } Z7_COM7F_IMF2(void, CCrcHasher::Init()) { _crc = CRC_INIT_VAL; } Z7_COM7F_IMF2(void, CCrcHasher::Update(const void *data, UInt32 size)) { _crc = _updateFunc(_crc, data, size); } Z7_COM7F_IMF2(void, CCrcHasher::Final(Byte *digest)) { const UInt32 val = CRC_GET_DIGEST(_crc); SetUi32(digest, val) } REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4) tmp41wklro_/CPP/Common/C_FileIO.cpp0000444000175000001440000000005713765446056020112 0ustar nabijaczleweliusers// Common/C_FileIO.cpp #include "StdAfx.h" tmp41wklro_/CPP/Common/C_FileIO.h0000444000175000001440000000015214357314620017540 0ustar nabijaczleweliusers// Common/C_FileIO.h #ifndef ZIP7_INC_COMMON_C_FILEIO_H #define ZIP7_INC_COMMON_C_FILEIO_H #endif tmp41wklro_/CPP/Common/Defs.h0000444000175000001440000000077114407263220017052 0ustar nabijaczleweliusers// Common/Defs.h #ifndef ZIP7_INC_COMMON_DEFS_H #define ZIP7_INC_COMMON_DEFS_H template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } template inline int MyCompare(T a, T b) { return a == b ? 0 : (a < b ? -1 : 1); } inline int BoolToInt(bool v) { return (v ? 1 : 0); } inline unsigned BoolToUInt(bool v) { return (v ? 1u : 0u); } inline bool IntToBool(int v) { return (v != 0); } #endif tmp41wklro_/CPP/Common/DynamicBuffer.h0000444000175000001440000000305114534573460020714 0ustar nabijaczleweliusers// Common/DynamicBuffer.h #ifndef ZIP7_INC_COMMON_DYNAMIC_BUFFER_H #define ZIP7_INC_COMMON_DYNAMIC_BUFFER_H #include #include "MyTypes.h" template class CDynamicBuffer { T *_items; size_t _size; size_t _pos; CDynamicBuffer(const CDynamicBuffer &buffer); void operator=(const CDynamicBuffer &buffer); void Grow(size_t size) { size_t delta = _size >= 64 ? _size : 64; if (delta < size) delta = size; size_t newCap = _size + delta; if (newCap < delta) { newCap = _size + size; if (newCap < size) throw 20120116; } T *newBuffer = new T[newCap]; if (_pos != 0) memcpy(newBuffer, _items, _pos * sizeof(T)); delete []_items; _items = newBuffer; _size = newCap; } public: CDynamicBuffer(): _items(NULL), _size(0), _pos(0) {} // operator T *() { return _items; } operator const T *() const { return _items; } ~CDynamicBuffer() { delete []_items; } void Free() { delete []_items; _items = NULL; _size = 0; _pos = 0; } T *GetCurPtrAndGrow(size_t addSize) { size_t rem = _size - _pos; if (rem < addSize) Grow(addSize - rem); T *res = _items + _pos; _pos += addSize; return res; } void AddData(const T *data, size_t size) { memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T)); } size_t GetPos() const { return _pos; } // void Empty() { _pos = 0; } }; typedef CDynamicBuffer CByteDynamicBuffer; #endif tmp41wklro_/CPP/Common/DynLimBuf.cpp0000444000175000001440000000320614346676300020362 0ustar nabijaczleweliusers// Common/DynLimBuf.cpp #include "StdAfx.h" #include "DynLimBuf.h" #include "MyString.h" CDynLimBuf::CDynLimBuf(size_t limit) throw() { _chars = NULL; _pos = 0; _size = 0; _sizeLimit = limit; _error = true; unsigned size = 1 << 4; if (size > limit) size = (unsigned)limit; _chars = (Byte *)MyAlloc(size); if (_chars) { _size = size; _error = false; } } CDynLimBuf & CDynLimBuf::operator+=(char c) throw() { if (_error) return *this; if (_size == _pos) { size_t n = _sizeLimit - _size; if (n == 0) { _error = true; return *this; } if (n > _size) n = _size; n += _pos; Byte *newBuf = (Byte *)MyAlloc(n); if (!newBuf) { _error = true; return *this; } memcpy(newBuf, _chars, _pos); MyFree(_chars); _chars = newBuf; _size = n; } _chars[_pos++] = (Byte)c; return *this; } CDynLimBuf &CDynLimBuf::operator+=(const char *s) throw() { if (_error) return *this; unsigned len = MyStringLen(s); size_t rem = _sizeLimit - _pos; if (rem < len) { len = (unsigned)rem; _error = true; } if (_size - _pos < len) { size_t n = _pos + len; if (n - _size < _size) { n = _sizeLimit; if (n - _size > _size) n = _size * 2; } Byte *newBuf = (Byte *)MyAlloc(n); if (!newBuf) { _error = true; return *this; } memcpy(newBuf, _chars, _pos); MyFree(_chars); _chars = newBuf; _size = n; } memcpy(_chars + _pos, s, len); _pos += len; return *this; } tmp41wklro_/CPP/Common/DynLimBuf.h0000444000175000001440000000151714357314620020026 0ustar nabijaczleweliusers// Common/DynLimBuf.h #ifndef ZIP7_INC_COMMON_DYN_LIM_BUF_H #define ZIP7_INC_COMMON_DYN_LIM_BUF_H #include #include "../../C/Alloc.h" #include "MyString.h" class CDynLimBuf { Byte *_chars; size_t _pos; size_t _size; size_t _sizeLimit; bool _error; CDynLimBuf(const CDynLimBuf &s); // ---------- forbidden functions ---------- CDynLimBuf &operator+=(wchar_t c); public: CDynLimBuf(size_t limit) throw(); ~CDynLimBuf() { MyFree(_chars); } size_t Len() const { return _pos; } bool IsError() const { return _error; } void Empty() { _pos = 0; _error = false; } operator const Byte *() const { return _chars; } // const char *Ptr() const { return _chars; } CDynLimBuf &operator+=(char c) throw(); CDynLimBuf &operator+=(const char *s) throw(); }; #endif tmp41wklro_/CPP/Common/IntToString.cpp0000444000175000001440000001034214535531560020752 0ustar nabijaczleweliusers// Common/IntToString.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #include "IntToString.h" #define CONVERT_INT_TO_STR(charType, tempSize) \ if (val < 10) \ *s++ = (charType)('0' + (unsigned)val); \ else { \ Byte temp[tempSize]; \ size_t i = 0; \ do { \ temp[++i] = (Byte)('0' + (unsigned)(val % 10)); \ val /= 10; } \ while (val >= 10); \ *s++ = (charType)('0' + (unsigned)val); \ do { *s++ = (charType)temp[i]; } \ while (--i); \ } \ *s = 0; \ return s; char * ConvertUInt32ToString(UInt32 val, char *s) throw() { CONVERT_INT_TO_STR(char, 16) } char * ConvertUInt64ToString(UInt64 val, char *s) throw() { if (val <= (UInt32)0xFFFFFFFF) return ConvertUInt32ToString((UInt32)val, s); CONVERT_INT_TO_STR(char, 24) } wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() { CONVERT_INT_TO_STR(wchar_t, 16) } wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() { if (val <= (UInt32)0xFFFFFFFF) return ConvertUInt32ToString((UInt32)val, s); CONVERT_INT_TO_STR(wchar_t, 24) } void ConvertInt64ToString(Int64 val, char *s) throw() { if (val < 0) { *s++ = '-'; val = -val; } ConvertUInt64ToString((UInt64)val, s); } void ConvertInt64ToString(Int64 val, wchar_t *s) throw() { if (val < 0) { *s++ = L'-'; val = -val; } ConvertUInt64ToString((UInt64)val, s); } void ConvertUInt64ToOct(UInt64 val, char *s) throw() { { UInt64 v = val; do s++; while (v >>= 3); } *s = 0; do { const unsigned t = (unsigned)val & 7; *--s = (char)('0' + t); } while (val >>= 3); } MY_ALIGN(16) const char k_Hex_Upper[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; MY_ALIGN(16) const char k_Hex_Lower[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; void ConvertUInt32ToHex(UInt32 val, char *s) throw() { { UInt32 v = val; do s++; while (v >>= 4); } *s = 0; do { const unsigned t = (unsigned)val & 0xF; *--s = GET_HEX_CHAR_UPPER(t); } while (val >>= 4); } void ConvertUInt64ToHex(UInt64 val, char *s) throw() { { UInt64 v = val; do s++; while (v >>= 4); } *s = 0; do { const unsigned t = (unsigned)val & 0xF; *--s = GET_HEX_CHAR_UPPER(t); } while (val >>= 4); } void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() { s[8] = 0; int i = 7; do { { const unsigned t = (unsigned)val & 0xF; s[i--] = GET_HEX_CHAR_UPPER(t); } { const unsigned t = (Byte)val >> 4; val >>= 8; s[i--] = GET_HEX_CHAR_UPPER(t); } } while (i >= 0); } /* void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) { s[8] = 0; for (int i = 7; i >= 0; i--) { const unsigned t = (unsigned)val & 0xF; val >>= 4; s[i] = GET_HEX_CHAR(t); } } */ MY_ALIGN(16) static const Byte k_Guid_Pos[] = { 6,4,2,0, 11,9, 16,14, 19,21, 24,26,28,30,32,34 }; char *RawLeGuidToString(const Byte *g, char *s) throw() { s[ 8] = '-'; s[13] = '-'; s[18] = '-'; s[23] = '-'; s[36] = 0; for (unsigned i = 0; i < 16; i++) { char *s2 = s + k_Guid_Pos[i]; const unsigned v = g[i]; s2[0] = GET_HEX_CHAR_UPPER(v >> 4); s2[1] = GET_HEX_CHAR_UPPER(v & 0xF); } return s + 36; } char *RawLeGuidToString_Braced(const Byte *g, char *s) throw() { *s++ = '{'; s = RawLeGuidToString(g, s); *s++ = '}'; *s = 0; return s; } void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw() { if (size) { const Byte *lim = src + size; do { const unsigned b = *src++; dest[0] = GET_HEX_CHAR_LOWER(b >> 4); dest[1] = GET_HEX_CHAR_LOWER(b & 0xF); dest += 2; } while (src != lim); } *dest = 0; } void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw() { if (size) { const Byte *lim = src + size; do { const unsigned b = *src++; dest[0] = GET_HEX_CHAR_UPPER(b >> 4); dest[1] = GET_HEX_CHAR_UPPER(b & 0xF); dest += 2; } while (src != lim); } *dest = 0; } tmp41wklro_/CPP/Common/IntToString.h0000444000175000001440000000343614506205340020415 0ustar nabijaczleweliusers// Common/IntToString.h #ifndef ZIP7_INC_COMMON_INT_TO_STRING_H #define ZIP7_INC_COMMON_INT_TO_STRING_H #include "MyTypes.h" // return: the pointer to the "terminating" null character after written characters char * ConvertUInt32ToString(UInt32 value, char *s) throw(); char * ConvertUInt64ToString(UInt64 value, char *s) throw(); wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); void ConvertInt64ToString(Int64 value, char *s) throw(); void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); void ConvertUInt64ToOct(UInt64 value, char *s) throw(); extern const char k_Hex_Upper[16]; extern const char k_Hex_Lower[16]; #define GET_HEX_CHAR_UPPER(t) (k_Hex_Upper[t]) #define GET_HEX_CHAR_LOWER(t) (k_Hex_Lower[t]) /* // #define GET_HEX_CHAR_UPPER(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) static inline unsigned GetHex_Lower(unsigned v) { const unsigned v0 = v + '0'; v += 'a' - 10; if (v < 'a') v = v0; return v; } static inline char GetHex_Upper(unsigned v) { return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); } */ void ConvertUInt32ToHex(UInt32 value, char *s) throw(); void ConvertUInt64ToHex(UInt64 value, char *s) throw(); void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); // void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); // use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian. char *RawLeGuidToString(const Byte *guid, char *s) throw(); char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw(); void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw(); void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw(); #endif tmp41wklro_/CPP/Common/Lang.h0000444000175000001440000000120614430652040017042 0ustar nabijaczleweliusers// Common/Lang.h #ifndef ZIP7_INC_COMMON_LANG_H #define ZIP7_INC_COMMON_LANG_H #include "MyString.h" class CLang { wchar_t *_text; bool OpenFromString(const AString &s); public: CRecordVector _ids; CRecordVector _offsets; UStringVector Comments; CLang(): _text(NULL) {} ~CLang() { Clear(); } bool Open(CFSTR fileName, const char *id); void Clear() throw(); bool IsEmpty() const { return _ids.IsEmpty(); } const wchar_t *Get(UInt32 id) const throw(); const wchar_t *Get_by_index(unsigned index) const throw() { return _text + (size_t)_offsets[index]; } }; #endif tmp41wklro_/CPP/Common/ListFileUtils.cpp0000444000175000001440000000640014564623240021261 0ustar nabijaczleweliusers// Common/ListFileUtils.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #include "ListFileUtils.h" #include "MyBuffer.h" #include "StringConvert.h" #include "UTFConvert.h" #include "../Windows/FileIO.h" #define CSysInFile NWindows::NFile::NIO::CInFile #define MY_GET_LAST_ERROR ::GetLastError() #define kQuoteChar '\"' static void AddName(UStringVector &strings, UString &s) { s.Trim(); if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) { s.DeleteBack(); s.Delete(0); } if (!s.IsEmpty()) strings.Add(s); } static bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError) { size_t processed; if (!file.ReadFull(data, size, processed)) { lastError = MY_GET_LAST_ERROR; return false; } if (processed != size) { lastError = 1; // error: size of listfile was changed return false; } return true; } bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError) { lastError = 0; CSysInFile file; if (!file.Open(fileName)) { lastError = MY_GET_LAST_ERROR; return false; } UInt64 fileSize; if (!file.GetLength(fileSize)) { lastError = MY_GET_LAST_ERROR; return false; } if (fileSize >= ((UInt32)1 << 31) - 32) return false; UString u; if (codePage == Z7_WIN_CP_UTF16 || codePage == Z7_WIN_CP_UTF16BE) { if ((fileSize & 1) != 0) return false; CByteArr buf((size_t)fileSize); if (!My_File_Read(file, buf, (size_t)fileSize, lastError)) return false; file.Close(); const size_t num = (size_t)fileSize / 2; wchar_t *p = u.GetBuf((unsigned)num); if (codePage == Z7_WIN_CP_UTF16) for (size_t i = 0; i < num; i++) { const wchar_t c = GetUi16(buf.ConstData() + (size_t)i * 2); if (c == 0) return false; p[i] = c; } else for (size_t i = 0; i < num; i++) { const wchar_t c = (wchar_t)GetBe16(buf.ConstData() + (size_t)i * 2); if (c == 0) return false; p[i] = c; } p[num] = 0; u.ReleaseBuf_SetLen((unsigned)num); } else { AString s; char *p = s.GetBuf((unsigned)fileSize); if (!My_File_Read(file, p, (size_t)fileSize, lastError)) return false; file.Close(); s.ReleaseBuf_CalcLen((unsigned)fileSize); if (s.Len() != fileSize) return false; // #ifdef CP_UTF8 if (codePage == CP_UTF8) { // we must check UTF8 here, if convert function doesn't check if (!CheckUTF8_AString(s)) return false; if (!ConvertUTF8ToUnicode(s, u)) return false; } else // #endif MultiByteToUnicodeString2(u, s, codePage); } const wchar_t kGoodBOM = 0xFEFF; // const wchar_t kBadBOM = 0xFFFE; UString s; unsigned i = 0; for (; i < u.Len() && u[i] == kGoodBOM; i++); for (; i < u.Len(); i++) { wchar_t c = u[i]; /* if (c == kGoodBOM || c == kBadBOM) return false; */ if (c == '\n' || c == 0xD) { AddName(strings, s); s.Empty(); } else s += c; } AddName(strings, s); return true; } tmp41wklro_/CPP/Common/ListFileUtils.h0000444000175000001440000000072014366515220020723 0ustar nabijaczleweliusers// Common/ListFileUtils.h #ifndef ZIP7_INC_COMMON_LIST_FILE_UTILS_H #define ZIP7_INC_COMMON_LIST_FILE_UTILS_H #include "MyString.h" #include "MyTypes.h" #define Z7_WIN_CP_UTF16 1200 #define Z7_WIN_CP_UTF16BE 1201 // bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); // = CP_OEMCP bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError); #endif tmp41wklro_/CPP/Common/LzFindPrepare.cpp0000444000175000001440000000025014074007760021226 0ustar nabijaczleweliusers// Sha256Prepare.cpp #include "StdAfx.h" #include "../../C/LzFind.h" static struct CLzFindPrepare { CLzFindPrepare() { LzFindPrepare(); } } g_CLzFindPrepare; tmp41wklro_/CPP/Common/MyBuffer.h0000444000175000001440000001434514564605200017714 0ustar nabijaczleweliusers// Common/MyBuffer.h #ifndef ZIP7_INC_COMMON_MY_BUFFER_H #define ZIP7_INC_COMMON_MY_BUFFER_H #include #include "Defs.h" #include "MyTypes.h" /* 7-Zip now uses CBuffer only as CByteBuffer. So there is no need to use Z7_ARRAY_NEW macro in CBuffer code. */ template class CBuffer { T *_items; size_t _size; public: void Free() { if (_items) { delete []_items; _items = NULL; } _size = 0; } CBuffer(): _items(NULL), _size(0) {} CBuffer(size_t size): _items(NULL), _size(0) { if (size != 0) { _items = new T[size]; _size = size; } } CBuffer(const CBuffer &buffer): _items(NULL), _size(0) { const size_t size = buffer._size; if (size != 0) { _items = new T[size]; memcpy(_items, buffer._items, size * sizeof(T)); _size = size; } } ~CBuffer() { delete []_items; } operator T *() { return _items; } operator const T *() const { return _items; } const T* ConstData() const { return _items; } T* NonConstData() const { return _items; } T* NonConstData() { return _items; } // const T* Data() const { return _items; } // T* Data() { return _items; } size_t Size() const { return _size; } void Alloc(size_t size) { if (size != _size) { Free(); if (size != 0) { _items = new T[size]; _size = size; } } } void AllocAtLeast(size_t size) { if (size > _size) { Free(); _items = new T[size]; _size = size; } } void CopyFrom(const T *data, size_t size) { Alloc(size); if (size != 0) memcpy(_items, data, size * sizeof(T)); } void ChangeSize_KeepData(size_t newSize, size_t keepSize) { if (newSize == _size) return; T *newBuffer = NULL; if (newSize != 0) { newBuffer = new T[newSize]; if (keepSize > _size) keepSize = _size; if (keepSize != 0) memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T)); } delete []_items; _items = newBuffer; _size = newSize; } void Wipe() { if (_size != 0) memset(_items, 0, _size * sizeof(T)); } CBuffer& operator=(const CBuffer &buffer) { if (&buffer != this) CopyFrom(buffer, buffer._size); return *this; } }; template bool operator==(const CBuffer& b1, const CBuffer& b2) { size_t size1 = b1.Size(); if (size1 != b2.Size()) return false; if (size1 == 0) return true; return memcmp(b1, b2, size1 * sizeof(T)) == 0; } template bool operator!=(const CBuffer& b1, const CBuffer& b2) { size_t size1 = b1.Size(); if (size1 != b2.Size()) return true; if (size1 == 0) return false; return memcmp(b1, b2, size1 * sizeof(T)) != 0; } // typedef CBuffer CCharBuffer; // typedef CBuffer CWCharBuffer; typedef CBuffer CByteBuffer; class CByteBuffer_Wipe: public CByteBuffer { Z7_CLASS_NO_COPY(CByteBuffer_Wipe) public: // CByteBuffer_Wipe(): CBuffer() {} CByteBuffer_Wipe(size_t size): CBuffer(size) {} ~CByteBuffer_Wipe() { Wipe(); } }; template class CObjArray { protected: T *_items; private: // we disable copy CObjArray(const CObjArray &buffer); void operator=(const CObjArray &buffer); public: void Free() { delete []_items; _items = NULL; } CObjArray(size_t size): _items(NULL) { if (size != 0) { Z7_ARRAY_NEW(_items, T, size) // _items = new T[size]; } } CObjArray(): _items(NULL) {} ~CObjArray() { delete []_items; } operator T *() { return _items; } operator const T *() const { return _items; } const T* ConstData() const { return _items; } T* NonConstData() const { return _items; } T* NonConstData() { return _items; } // const T* Data() const { return _items; } // T* Data() { return _items; } void Alloc(size_t newSize) { delete []_items; _items = NULL; Z7_ARRAY_NEW(_items, T, newSize) // _items = new T[newSize]; } }; typedef CObjArray CByteArr; typedef CObjArray CBoolArr; typedef CObjArray CIntArr; typedef CObjArray CUIntArr; template class CObjArray2 { T *_items; unsigned _size; // we disable copy CObjArray2(const CObjArray2 &buffer); void operator=(const CObjArray2 &buffer); public: void Free() { delete []_items; _items = NULL; _size = 0; } CObjArray2(): _items(NULL), _size(0) {} /* CObjArray2(const CObjArray2 &buffer): _items(NULL), _size(0) { size_t newSize = buffer._size; if (newSize != 0) { T *newBuffer = new T[newSize];; _items = newBuffer; _size = newSize; const T *src = buffer; for (size_t i = 0; i < newSize; i++) newBuffer[i] = src[i]; } } */ /* CObjArray2(size_t size): _items(NULL), _size(0) { if (size != 0) { _items = new T[size]; _size = size; } } */ ~CObjArray2() { delete []_items; } operator T *() { return _items; } operator const T *() const { return _items; } unsigned Size() const { return (unsigned)_size; } bool IsEmpty() const { return _size == 0; } // SetSize doesn't keep old items. It allocates new array if size is not equal void SetSize(unsigned size) { if (size == _size) return; T *newBuffer = NULL; if (size != 0) { Z7_ARRAY_NEW(newBuffer, T, size) // newBuffer = new T[size]; } delete []_items; _items = newBuffer; _size = size; } /* CObjArray2& operator=(const CObjArray2 &buffer) { Free(); size_t newSize = buffer._size; if (newSize != 0) { T *newBuffer = new T[newSize];; _items = newBuffer; _size = newSize; const T *src = buffer; for (size_t i = 0; i < newSize; i++) newBuffer[i] = src[i]; } return *this; } */ }; #endif tmp41wklro_/CPP/Common/MyBuffer2.h0000444000175000001440000000717514535414300017776 0ustar nabijaczleweliusers// Common/MyBuffer2.h #ifndef ZIP7_INC_COMMON_MY_BUFFER2_H #define ZIP7_INC_COMMON_MY_BUFFER2_H #include "../../C/Alloc.h" #include "MyTypes.h" class CMidBuffer { Byte *_data; size_t _size; Z7_CLASS_NO_COPY(CMidBuffer) public: CMidBuffer(): _data(NULL), _size(0) {} ~CMidBuffer() { ::MidFree(_data); } void Free() { ::MidFree(_data); _data = NULL; _size = 0; } bool IsAllocated() const { return _data != NULL; } operator Byte *() { return _data; } operator const Byte *() const { return _data; } size_t Size() const { return _size; } void Alloc(size_t size) { if (!_data || size != _size) { ::MidFree(_data); _size = 0; _data = NULL; _data = (Byte *)::MidAlloc(size); if (_data) _size = size; } } void AllocAtLeast(size_t size) { if (!_data || size > _size) { ::MidFree(_data); const size_t kMinSize = (size_t)1 << 16; if (size < kMinSize) size = kMinSize; _size = 0; _data = NULL; _data = (Byte *)::MidAlloc(size); if (_data) _size = size; } } }; class CAlignedBuffer1 { Byte *_data; Z7_CLASS_NO_COPY(CAlignedBuffer1) public: ~CAlignedBuffer1() { z7_AlignedFree(_data); } CAlignedBuffer1(size_t size) { _data = NULL; _data = (Byte *)z7_AlignedAlloc(size); if (!_data) throw 1; } operator Byte *() { return _data; } operator const Byte *() const { return _data; } }; class CAlignedBuffer { Byte *_data; size_t _size; Z7_CLASS_NO_COPY(CAlignedBuffer) public: CAlignedBuffer(): _data(NULL), _size(0) {} ~CAlignedBuffer() { z7_AlignedFree(_data); } /* CAlignedBuffer(size_t size): _size(0) { _data = NULL; _data = (Byte *)z7_AlignedAlloc(size); if (!_data) throw 1; _size = size; } */ void Free() { z7_AlignedFree(_data); _data = NULL; _size = 0; } bool IsAllocated() const { return _data != NULL; } operator Byte *() { return _data; } operator const Byte *() const { return _data; } size_t Size() const { return _size; } void Alloc(size_t size) { if (!_data || size != _size) { z7_AlignedFree(_data); _size = 0; _data = NULL; _data = (Byte *)z7_AlignedAlloc(size); if (_data) _size = size; } } void AllocAtLeast(size_t size) { if (!_data || size > _size) { z7_AlignedFree(_data); _size = 0; _data = NULL; _data = (Byte *)z7_AlignedAlloc(size); if (_data) _size = size; } } // (size <= size_max) void AllocAtLeast_max(size_t size, size_t size_max) { if (!_data || size > _size) { z7_AlignedFree(_data); _size = 0; _data = NULL; if (size_max < size) size_max = size; // optional check const size_t delta = size / 2; size += delta; if (size < delta || size > size_max) size = size_max; _data = (Byte *)z7_AlignedAlloc(size); if (_data) _size = size; } } }; /* CMidAlignedBuffer must return aligned pointer. - in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc() VirtualAlloc(): Memory allocated is automatically initialized to zero. MidAlloc(0) returns NULL - in non-Windows systems it uses g_AlignedAlloc. g_AlignedAlloc::Alloc(size = 0) can return non NULL. */ typedef #ifdef _WIN32 CMidBuffer #else CAlignedBuffer #endif CMidAlignedBuffer; #endif tmp41wklro_/CPP/Common/MyCom.h0000444000175000001440000003624114601330040017205 0ustar nabijaczleweliusers// MyCom.h #ifndef ZIP7_INC_MY_COM_H #define ZIP7_INC_MY_COM_H #include "MyWindows.h" #include "MyTypes.h" template class CMyComPtr { T* _p; public: CMyComPtr(): _p(NULL) {} CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } T* Interface() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() { // if (*pp) throw 20220216; // for debug return _p->QueryInterface(iid, (void**)pp); } }; template class CMyComPtr2 { cls* _p; CMyComPtr2(const CMyComPtr2& lp); CMyComPtr2(cls* p); CMyComPtr2(iface* p); iface* operator=(const CMyComPtr2& lp); iface* operator=(cls* p); iface* operator=(iface* p); public: CMyComPtr2(): _p(NULL) {} ~CMyComPtr2() { if (_p) { iface *ip = _p; ip->Release(); } } // void Release() { if (_p) { (iface *)_p->Release(); _p = NULL; } } cls* operator->() const { return _p; } cls* ClsPtr() const { return _p; } operator iface*() const { iface *ip = _p; return ip; } iface* Interface() const { iface *ip = _p; return ip; } // operator bool() const { return _p != NULL; } bool IsDefined() const { return _p != NULL; } void Create_if_Empty() { if (!_p) { _p = new cls; iface *ip = _p; ip->AddRef(); } } iface* Detach() { iface *ip = _p; _p = NULL; return ip; } void SetFromCls(cls *src) { if (src) { iface *ip = src; ip->AddRef(); } if (_p) { iface *ip = _p; ip->Release(); } _p = src; } }; template class CMyComPtr2_Create { cls* _p; CMyComPtr2_Create(const CMyComPtr2_Create& lp); CMyComPtr2_Create(cls* p); CMyComPtr2_Create(iface* p); iface* operator=(const CMyComPtr2_Create& lp); iface* operator=(cls* p); iface* operator=(iface* p); public: CMyComPtr2_Create(): _p(new cls) { iface *ip = _p; ip->AddRef(); } ~CMyComPtr2_Create() { iface *ip = _p; ip->Release(); } cls* operator->() const { return _p; } cls* ClsPtr() const { return _p; } operator iface*() const { iface *ip = _p; return ip; } iface* Interface() const { iface *ip = _p; return ip; } }; #define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \ CMyComPtr v; (unk)->QueryInterface(IID_ ## i, (void **)&v); ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { BSTR m_str; Z7_CLASS_NO_COPY(CMyComBSTR) public: CMyComBSTR(): m_str(NULL) {} ~CMyComBSTR() { ::SysFreeString(m_str); } BSTR* operator&() { return &m_str; } operator LPCOLESTR() const { return m_str; } // operator bool() const { return m_str != NULL; } // bool operator!() const { return m_str == NULL; } void Wipe_and_Free() { if (m_str) { memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str)); Empty(); } } private: // operator BSTR() const { return m_str; } CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ /* CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } */ CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned Len() const { return ::SysStringLen(m_str); } BSTR MyCopy() const { // We don't support Byte BSTRs here return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); /* UINT byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); if (res && byteLen != 0 && m_str) memcpy(res, m_str, byteLen); return res; */ } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } }; class CMyComBSTR_Wipe: public CMyComBSTR { Z7_CLASS_NO_COPY(CMyComBSTR_Wipe) public: CMyComBSTR_Wipe(): CMyComBSTR() {} ~CMyComBSTR_Wipe() { Wipe_and_Free(); } }; /* If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. But if some class_1 derived from CMyUnknownImp uses Z7_COM_ADDREF_RELEASE and IUnknown::Release() and some another class_2 is derived from class_1, then class_1 must use virtual destructor: virtual ~class_1(); In that case, class_1::Release() calls correct destructor of class_2. We can use virtual ~CMyUnknownImp() to disable warning "class has virtual functions, but destructor is not virtual". Also we can use virtual ~IUnknown() {} in MyWindows.h */ class CMyUnknownImp { Z7_CLASS_NO_COPY(CMyUnknownImp) protected: ULONG _m_RefCount; CMyUnknownImp(): _m_RefCount(0) {} #ifdef _WIN32 #if defined(__GNUC__) || defined(__clang__) // virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings #endif #endif }; #define Z7_COM_QI_BEGIN \ private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \ { *outObject = NULL; #define Z7_COM_QI_ENTRY(i) \ else if (iid == IID_ ## i) \ { i *ti = this; *outObject = ti; } // { *outObject = (void *)(i *)this; } #define Z7_COM_QI_ENTRY_UNKNOWN_0 \ if (iid == IID_IUnknown) \ { IUnknown *tu = this; *outObject = tu; } #define Z7_COM_QI_ENTRY_UNKNOWN(i) \ if (iid == IID_IUnknown) \ { i *ti = this; IUnknown *tu = ti; *outObject = tu; } // { *outObject = (void *)(IUnknown *)(i *)this; } #define Z7_COM_QI_BEGIN2(i) \ Z7_COM_QI_BEGIN \ Z7_COM_QI_ENTRY_UNKNOWN(i) \ Z7_COM_QI_ENTRY(i) #define Z7_COM_ADDREF_RELEASE_MT \ private: \ STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \ { return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \ STDMETHOD_(ULONG, Release)() Z7_override Z7_final \ { const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \ if (v != 0) return (ULONG)v; \ delete this; return 0; } #define Z7_COM_QI_END_MT \ else return E_NOINTERFACE; \ InterlockedIncrement((LONG *)&_m_RefCount); /* AddRef(); */ return S_OK; } // you can define Z7_COM_USE_ATOMIC, // if you want to call Release() from different threads (for example, for .NET code) // #define Z7_COM_USE_ATOMIC #if defined(Z7_COM_USE_ATOMIC) && !defined(Z7_ST) #ifndef _WIN32 #if 0 #include "../../C/Threads.h" #else EXTERN_C_BEGIN LONG InterlockedIncrement(LONG volatile *addend); LONG InterlockedDecrement(LONG volatile *addend); EXTERN_C_END #endif #endif // _WIN32 #define Z7_COM_ADDREF_RELEASE Z7_COM_ADDREF_RELEASE_MT #define Z7_COM_QI_END Z7_COM_QI_END_MT #else // !Z7_COM_USE_ATOMIC #define Z7_COM_ADDREF_RELEASE \ private: \ STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \ { return ++_m_RefCount; } \ STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \ { if (--_m_RefCount != 0) return _m_RefCount; \ delete this; return 0; } #define Z7_COM_QI_END \ else return E_NOINTERFACE; \ ++_m_RefCount; /* AddRef(); */ return S_OK; } #endif // !Z7_COM_USE_ATOMIC #define Z7_COM_UNKNOWN_IMP_SPEC(i) \ Z7_COM_QI_BEGIN \ i \ Z7_COM_QI_END \ Z7_COM_ADDREF_RELEASE #define Z7_COM_UNKNOWN_IMP_0 \ Z7_COM_QI_BEGIN \ Z7_COM_QI_ENTRY_UNKNOWN_0 \ Z7_COM_QI_END \ Z7_COM_ADDREF_RELEASE #define Z7_COM_UNKNOWN_IMP_1(i) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i) \ Z7_COM_QI_ENTRY(i) \ ) #define Z7_COM_UNKNOWN_IMP_2(i1, i2) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ ) #define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ ) #define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ ) #define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ ) #define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ Z7_COM_QI_ENTRY(i6) \ ) #define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ Z7_COM_QI_ENTRY(i6) \ Z7_COM_QI_ENTRY(i7) \ ) #define Z7_IFACES_IMP_UNK_1(i1) \ Z7_COM_UNKNOWN_IMP_1(i1) \ Z7_IFACE_COM7_IMP(i1) \ #define Z7_IFACES_IMP_UNK_2(i1, i2) \ Z7_COM_UNKNOWN_IMP_2(i1, i2) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ #define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ #define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ #define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ #define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ Z7_IFACE_COM7_IMP(i6) \ #define Z7_CLASS_IMP_COM_0(c) \ Z7_class_final(c) : \ public IUnknown, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ private: #define Z7_CLASS_IMP_COM_1(c, i1) \ Z7_class_final(c) : \ public i1, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_1(i1) \ private: #define Z7_CLASS_IMP_COM_2(c, i1, i2) \ Z7_class_final(c) : \ public i1, \ public i2, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_2(i1, i2) \ private: #define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ private: #define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ private: #define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ private: #define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public i6, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ private: /* #define Z7_CLASS_IMP_NOQIB_0(c) \ Z7_class_final(c) : \ public IUnknown, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ private: */ #define Z7_CLASS_IMP_NOQIB_1(c, i1) \ Z7_class_final(c) : \ public i1, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ Z7_IFACE_COM7_IMP(i1) \ private: #define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \ Z7_class_final(c) : \ public i1, \ public i2, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_1(i2) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ private: #define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_2(i2, i3) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ private: #define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ /* #define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ */ #define Z7_CLASS_IMP_IInStream(c) \ class c Z7_final : \ public IInStream, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \ #define k_My_HRESULT_WritingWasCut 0x20000010 #endif tmp41wklro_/CPP/Common/MyException.h0000444000175000001440000000037714357314620020444 0ustar nabijaczleweliusers// Common/Exception.h #ifndef ZIP7_INC_COMMON_EXCEPTION_H #define ZIP7_INC_COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif tmp41wklro_/CPP/Common/MyGuidDef.h0000444000175000001440000000237514476130020020005 0ustar nabijaczleweliusers// Common/MyGuidDef.h // #pragma message "Common/MyGuidDef.h" #ifndef GUID_DEFINED #define GUID_DEFINED // #pragma message "GUID_DEFINED" #include "MyTypes.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; Byte Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif // typedef GUID IID; typedef GUID CLSID; #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (unsigned i = 0; i < sizeof(g1); i++) if (((const Byte *)&g1)[i] != ((const Byte *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #endif // GUID_DEFINED #ifndef EXTERN_C #ifdef __cplusplus #define EXTERN_C extern "C" #else #define EXTERN_C extern #endif #endif #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name; \ EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name #endif tmp41wklro_/CPP/Common/MyInitGuid.h0000444000175000001440000000323114407263220020205 0ustar nabijaczleweliusers// Common/MyInitGuid.h #ifndef ZIP7_INC_COMMON_MY_INITGUID_H #define ZIP7_INC_COMMON_MY_INITGUID_H /* This file must be included only to one C++ file in project before declarations of COM interfaces with DEFINE_GUID macro. Each GUID must be initialized exactly once in project. There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h): - if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name. - if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID. Also we need IID_IUnknown that is initialized in some file for linking: MSVC: by default the linker uses some lib file that contains IID_IUnknown MinGW: add -luuid switch for linker WinCE: we define IID_IUnknown in this file Other: we define IID_IUnknown in this file */ // #include "Common.h" /* vc6 without sdk needs before , but it doesn't work in new msvc. So we include full "MyWindows.h" instead of */ // #include #include "MyWindows.h" #ifdef _WIN32 #ifdef __clang__ // #pragma GCC diagnostic ignored "-Wmissing-variable-declarations" #endif #ifdef UNDER_CE #include #endif // for vc6 without sdk we must define INITGUID here #define INITGUID #include #ifdef UNDER_CE DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #else // _WIN32 #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif // _WIN32 #endif tmp41wklro_/CPP/Common/MyLinux.h0000444000175000001440000000420514404365600017574 0ustar nabijaczleweliusers// MyLinux.h #ifndef ZIP7_INC_COMMON_MY_LINUX_H #define ZIP7_INC_COMMON_MY_LINUX_H // #include "../../C/7zTypes.h" #define MY_LIN_DT_UNKNOWN 0 #define MY_LIN_DT_FIFO 1 #define MY_LIN_DT_CHR 2 #define MY_LIN_DT_DIR 4 #define MY_LIN_DT_BLK 6 #define MY_LIN_DT_REG 8 #define MY_LIN_DT_LNK 10 #define MY_LIN_DT_SOCK 12 #define MY_LIN_DT_WHT 14 #define MY_LIN_S_IFMT 00170000 #define MY_LIN_S_IFSOCK 0140000 #define MY_LIN_S_IFLNK 0120000 #define MY_LIN_S_IFREG 0100000 #define MY_LIN_S_IFBLK 0060000 #define MY_LIN_S_IFDIR 0040000 #define MY_LIN_S_IFCHR 0020000 #define MY_LIN_S_IFIFO 0010000 #define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK) #define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG) #define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR) #define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR) #define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK) #define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO) #define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK) #define MY_LIN_S_ISUID 0004000 #define MY_LIN_S_ISGID 0002000 #define MY_LIN_S_ISVTX 0001000 #define MY_LIN_S_IRWXU 00700 #define MY_LIN_S_IRUSR 00400 #define MY_LIN_S_IWUSR 00200 #define MY_LIN_S_IXUSR 00100 #define MY_LIN_S_IRWXG 00070 #define MY_LIN_S_IRGRP 00040 #define MY_LIN_S_IWGRP 00020 #define MY_LIN_S_IXGRP 00010 #define MY_LIN_S_IRWXO 00007 #define MY_LIN_S_IROTH 00004 #define MY_LIN_S_IWOTH 00002 #define MY_LIN_S_IXOTH 00001 /* // major/minor encoding for makedev(): MMMMMmmmmmmMMMmm: inline UInt32 MY_dev_major(UInt64 dev) { return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff); } inline UInt32 MY_dev_minor(UInt64 dev) { return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~0xff); } inline UInt64 MY_dev_makedev(UInt32 __major, UInt32 __minor) { return (__minor & 0xff) | ((__major & 0xfff) << 8) | ((UInt64) (__minor & ~0xff) << 12) | ((UInt64) (__major & ~0xfff) << 32); } */ #endif tmp41wklro_/CPP/Common/MyString.cpp0000444000175000001440000011307214564614220020303 0ustar nabijaczleweliusers// Common/MyString.cpp #include "StdAfx.h" #ifdef _WIN32 #include #else #include #endif #include "IntToString.h" #if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) #include "StringConvert.h" #endif #include "MyString.h" #define MY_STRING_NEW(_T_, _size_) new _T_[_size_] // #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_))) /* inline const char* MyStringGetNextCharPointer(const char *p) throw() { #if defined(_WIN32) && !defined(UNDER_CE) return CharNextA(p); #else return p + 1; #endif } */ #define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, (_size_)) #define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, (_size_)) int FindCharPosInString(const char *s, char c) throw() { for (const char *p = s;; p++) { if (*p == c) return (int)(p - s); if (*p == 0) return -1; // MyStringGetNextCharPointer(p); } } int FindCharPosInString(const wchar_t *s, wchar_t c) throw() { for (const wchar_t *p = s;; p++) { if (*p == c) return (int)(p - s); if (*p == 0) return -1; } } /* void MyStringUpper_Ascii(char *s) throw() { for (;;) { const char c = *s; if (c == 0) return; *s++ = MyCharUpper_Ascii(c); } } void MyStringUpper_Ascii(wchar_t *s) throw() { for (;;) { const wchar_t c = *s; if (c == 0) return; *s++ = MyCharUpper_Ascii(c); } } */ void MyStringLower_Ascii(char *s) throw() { for (;;) { const char c = *s; if (c == 0) return; *s++ = MyCharLower_Ascii(c); } } void MyStringLower_Ascii(wchar_t *s) throw() { for (;;) { const wchar_t c = *s; if (c == 0) return; *s++ = MyCharLower_Ascii(c); } } #ifdef _WIN32 #ifdef _UNICODE // wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } // wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } // for WinCE - FString - char // const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; } #else // const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); } // char * MyStringUpper(char *s) { return CharUpperA(s); } // char * MyStringLower(char *s) { return CharLowerA(s); } wchar_t MyCharUpper_WIN(wchar_t c) throw() { wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned)(UINT_PTR)res; const int kBufSize = 4; char s[kBufSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } /* wchar_t MyCharLower_WIN(wchar_t c) { wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned)(UINT_PTR)res; const int kBufSize = 4; char s[kBufSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); if (numChars == 0 || numChars > kBufSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } */ /* wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); return s; } */ /* wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); return s; } */ #endif #endif bool IsString1PrefixedByString2(const char *s1, const char *s2) throw() { for (;;) { const char c2 = *s2++; if (c2 == 0) return true; const char c1 = *s1++; if (c1 != c2) return false; } } bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { const wchar_t c1 = *s1++; const wchar_t c2 = *s2++; if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; if (c1 == 0) return true; } } // ---------- ASCII ---------- bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() { const char *s1 = _chars; for (;;) { const char c2 = *s++; if (c2 == 0) return true; const char c1 = *s1++; if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) return false; } } bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() { const wchar_t *s1 = _chars; for (;;) { const char c2 = *s++; if (c2 == 0) return true; const wchar_t c1 = *s1++; if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) return false; } } bool StringsAreEqual_Ascii(const char *u, const char *a) throw() { for (;;) { const char c = *a; if (c != *u) return false; if (c == 0) return true; a++; u++; } } bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() { for (;;) { const unsigned char c = (unsigned char)*a; if (c != *u) return false; if (c == 0) return true; a++; u++; } } bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw() { for (;;) { const char c1 = *s1++; const char c2 = *s2++; if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) return false; if (c1 == 0) return true; } } bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { const wchar_t c1 = *s1++; const wchar_t c2 = *s2++; if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) return false; if (c1 == 0) return true; } } bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw() { for (;;) { const wchar_t c1 = *s1++; const char c2 = *s2++; if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) return false; if (c1 == 0) return true; } } bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { const wchar_t c2 = *s2++; if (c2 == 0) return true; const wchar_t c1 = *s1++; if (c1 != c2) return false; } } bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw() { for (;;) { const unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; const wchar_t c1 = *s1++; if (c1 != c2) return false; } } bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw() { for (;;) { const char c2 = *s2++; if (c2 == 0) return true; const char c1 = *s1++; if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) return false; } } bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw() { for (;;) { const char c2 = *s2++; if (c2 == 0) return true; const wchar_t c1 = *s1++; if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) return false; } } bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { const wchar_t c2 = *s2++; if (c2 == 0) return true; const wchar_t c1 = *s1++; if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; } } // NTFS order: uses upper case int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { const wchar_t c1 = *s1++; const wchar_t c2 = *s2++; if (c1 != c2) { const wchar_t u1 = MyCharUpper(c1); const wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) { for (; num != 0; num--) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } return 0; } */ // ---------- AString ---------- void AString::InsertSpace(unsigned &index, unsigned size) { Grow(size); MoveItems(index + size, index); } #define k_Alloc_Len_Limit (0x40000000 - 2) // #define k_Alloc_Len_Limit (((unsigned)1 << (sizeof(unsigned) * 8 - 2)) - 2) void AString::ReAlloc(unsigned newLimit) { // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, (size_t)_len + 1); char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1); memcpy(newBuf, _chars, (size_t)_len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = newLimit; } #define THROW_STRING_ALLOC_EXCEPTION { throw 20130220; } #define CHECK_STRING_ALLOC_LEN(len) \ { if ((len) > k_Alloc_Len_Limit) THROW_STRING_ALLOC_EXCEPTION } void AString::ReAlloc2(unsigned newLimit) { CHECK_STRING_ALLOC_LEN(newLimit) // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0); char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1); newBuf[0] = 0; MY_STRING_DELETE(_chars) _chars = newBuf; _limit = newLimit; _len = 0; } void AString::SetStartLen(unsigned len) { _chars = NULL; _chars = MY_STRING_NEW_char((size_t)len + 1); _len = len; _limit = len; } Z7_NO_INLINE void AString::Grow_1() { unsigned next = _len; next += next / 2; next += 16; next &= ~(unsigned)15; next--; if (next < _len || next > k_Alloc_Len_Limit) next = k_Alloc_Len_Limit; if (next <= _len) THROW_STRING_ALLOC_EXCEPTION ReAlloc(next); // Grow(1); } void AString::Grow(unsigned n) { const unsigned freeSize = _limit - _len; if (n <= freeSize) return; unsigned next = _len + n; next += next / 2; next += 16; next &= ~(unsigned)15; next--; if (next < _len || next > k_Alloc_Len_Limit) next = k_Alloc_Len_Limit; if (next <= _len || next - _len < n) THROW_STRING_ALLOC_EXCEPTION ReAlloc(next); } AString::AString(unsigned num, const char *s) { unsigned len = MyStringLen(s); if (num > len) num = len; SetStartLen(num); memcpy(_chars, s, num); _chars[num] = 0; } AString::AString(unsigned num, const AString &s) { if (num > s._len) num = s._len; SetStartLen(num); memcpy(_chars, s._chars, num); _chars[num] = 0; } AString::AString(const AString &s, char c) { SetStartLen(s.Len() + 1); char *chars = _chars; unsigned len = s.Len(); memcpy(chars, s, len); chars[len] = c; chars[(size_t)len + 1] = 0; } AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) { SetStartLen(num1 + num2); char *chars = _chars; memcpy(chars, s1, num1); memcpy(chars + num1, s2, num2 + 1); } AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } static const unsigned kStartStringCapacity = 4; AString::AString() { _chars = NULL; _chars = MY_STRING_NEW_char(kStartStringCapacity); _len = 0; _limit = kStartStringCapacity - 1; _chars[0] = 0; } AString::AString(char c) { SetStartLen(1); char *chars = _chars; chars[0] = c; chars[1] = 0; } AString::AString(const char *s) { SetStartLen(MyStringLen(s)); MyStringCopy(_chars, s); } AString::AString(const AString &s) { SetStartLen(s._len); MyStringCopy(_chars, s._chars); } AString &AString::operator=(char c) { if (1 > _limit) { char *newBuf = MY_STRING_NEW_char(1 + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = 1; } _len = 1; char *chars = _chars; chars[0] = c; chars[1] = 0; return *this; } AString &AString::operator=(const char *s) { unsigned len = MyStringLen(s); if (len > _limit) { char *newBuf = MY_STRING_NEW_char((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; MyStringCopy(_chars, s); return *this; } AString &AString::operator=(const AString &s) { if (&s == this) return *this; unsigned len = s._len; if (len > _limit) { char *newBuf = MY_STRING_NEW_char((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; MyStringCopy(_chars, s._chars); return *this; } void AString::SetFromWStr_if_Ascii(const wchar_t *s) { unsigned len = 0; { for (;; len++) { wchar_t c = s[len]; if (c == 0) break; if (c >= 0x80) return; } } if (len > _limit) { char *newBuf = MY_STRING_NEW_char((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; char *dest = _chars; unsigned i; for (i = 0; i < len; i++) dest[i] = (char)s[i]; dest[i] = 0; } /* void AString::SetFromBstr_if_Ascii(BSTR s) { unsigned len = ::SysStringLen(s); { for (unsigned i = 0; i < len; i++) if (s[i] <= 0 || s[i] >= 0x80) return; } if (len > _limit) { char *newBuf = MY_STRING_NEW_char((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; char *dest = _chars; unsigned i; for (i = 0; i < len; i++) dest[i] = (char)s[i]; dest[i] = 0; } */ void AString::Add_Char(char c) { operator+=(c); } void AString::Add_Space() { operator+=(' '); } void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } void AString::Add_LF() { operator+=('\n'); } void AString::Add_Slash() { operator+=('/'); } void AString::Add_Dot() { operator+=('.'); } void AString::Add_Minus() { operator+=('-'); } void AString::Add_Colon() { operator+=(':'); } AString &AString::operator+=(const char *s) { unsigned len = MyStringLen(s); Grow(len); MyStringCopy(_chars + _len, s); _len += len; return *this; } void AString::Add_OptSpaced(const char *s) { Add_Space_if_NotEmpty(); (*this) += s; } AString &AString::operator+=(const AString &s) { Grow(s._len); MyStringCopy(_chars + _len, s._chars); _len += s._len; return *this; } void AString::Add_UInt32(UInt32 v) { Grow(10); _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } void UString::Add_UInt64(UInt64 v) { Grow(20); _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); } void AString::AddFrom(const char *s, unsigned len) // no check { if (len != 0) { Grow(len); memcpy(_chars + _len, s, len); len += _len; _chars[len] = 0; _len = len; } } void AString::SetFrom(const char *s, unsigned len) // no check { if (len > _limit) { CHECK_STRING_ALLOC_LEN(len) char *newBuf = MY_STRING_NEW_char((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } if (len != 0) memcpy(_chars, s, len); _chars[len] = 0; _len = len; } void AString::SetFrom_Chars_SizeT(const char *s, size_t len) { CHECK_STRING_ALLOC_LEN(len) SetFrom(s, (unsigned)len); } void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check { unsigned i; for (i = 0; i < len; i++) if (s[i] == 0) break; SetFrom(s, i); } int AString::Find(const char *s, unsigned startIndex) const throw() { const char *fs = strstr(_chars + startIndex, s); if (!fs) return -1; return (int)(fs - _chars); /* if (s[0] == 0) return startIndex; unsigned len = MyStringLen(s); const char *p = _chars + startIndex; for (;; p++) { const char c = *p; if (c != s[0]) { if (c == 0) return -1; continue; } unsigned i; for (i = 1; i < len; i++) if (p[i] != s[i]) break; if (i == len) return (int)(p - _chars); } */ } int AString::ReverseFind(char c) const throw() { if (_len == 0) return -1; const char *p = _chars + _len - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p--; // p = GetPrevCharPointer(_chars, p); } } int AString::ReverseFind_PathSepar() const throw() { if (_len == 0) return -1; const char *p = _chars + _len - 1; for (;;) { const char c = *p; if (IS_PATH_SEPAR(c)) return (int)(p - _chars); if (p == _chars) return -1; p--; } } void AString::TrimLeft() throw() { const char *p = _chars; for (;; p++) { char c = *p; if (c != ' ' && c != '\n' && c != '\t') break; } unsigned pos = (unsigned)(p - _chars); if (pos != 0) { MoveItems(0, pos); _len -= pos; } } void AString::TrimRight() throw() { const char *p = _chars; unsigned i; for (i = _len; i != 0; i--) { char c = p[(size_t)i - 1]; if (c != ' ' && c != '\n' && c != '\t') break; } if (i != _len) { _chars[i] = 0; _len = i; } } void AString::InsertAtFront(char c) { if (_limit == _len) Grow_1(); MoveItems(1, 0); _chars[0] = c; _len++; } /* void AString::Insert(unsigned index, char c) { InsertSpace(index, 1); _chars[index] = c; _len++; } */ void AString::Insert(unsigned index, const char *s) { unsigned num = MyStringLen(s); if (num != 0) { InsertSpace(index, num); memcpy(_chars + index, s, num); _len += num; } } void AString::Insert(unsigned index, const AString &s) { unsigned num = s.Len(); if (num != 0) { InsertSpace(index, num); memcpy(_chars + index, s, num); _len += num; } } void AString::RemoveChar(char ch) throw() { char *src = _chars; for (;;) { char c = *src++; if (c == 0) return; if (c == ch) break; } char *dest = src - 1; for (;;) { char c = *src++; if (c == 0) break; if (c != ch) *dest++ = c; } *dest = 0; _len = (unsigned)(dest - _chars); } // !!!!!!!!!!!!!!! test it if newChar = '\0' void AString::Replace(char oldChar, char newChar) throw() { if (oldChar == newChar) return; // 0; // unsigned number = 0; int pos = 0; char *chars = _chars; while ((unsigned)pos < _len) { pos = Find(oldChar, (unsigned)pos); if (pos < 0) break; chars[(unsigned)pos] = newChar; pos++; // number++; } return; // number; } void AString::Replace(const AString &oldString, const AString &newString) { if (oldString.IsEmpty()) return; // 0; if (oldString == newString) return; // 0; const unsigned oldLen = oldString.Len(); const unsigned newLen = newString.Len(); // unsigned number = 0; int pos = 0; while ((unsigned)pos < _len) { pos = Find(oldString, (unsigned)pos); if (pos < 0) break; Delete((unsigned)pos, oldLen); Insert((unsigned)pos, newString); pos += newLen; // number++; } // return number; } void AString::Delete(unsigned index) throw() { MoveItems(index, index + 1); _len--; } void AString::Delete(unsigned index, unsigned count) throw() { if (index + count > _len) count = _len - index; if (count > 0) { MoveItems(index, index + count); _len -= count; } } void AString::DeleteFrontal(unsigned num) throw() { if (num != 0) { MoveItems(0, num); _len -= num; } } /* AString operator+(const AString &s1, const AString &s2) { AString result(s1); result += s2; return result; } AString operator+(const AString &s, const char *chars) { AString result(s); result += chars; return result; } AString operator+(const char *chars, const AString &s) { AString result(chars); result += s; return result; } AString operator+(const AString &s, char c) { AString result(s); result += c; return result; } */ /* AString operator+(char c, const AString &s) { AString result(c); result += s; return result; } */ // ---------- UString ---------- void UString::InsertSpace(unsigned index, unsigned size) { Grow(size); MoveItems(index + size, index); } void UString::ReAlloc(unsigned newLimit) { // MY_STRING_REALLOC(_chars, wchar_t, (size_t)newLimit + 1, (size_t)_len + 1); wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); wmemcpy(newBuf, _chars, _len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = newLimit; } void UString::ReAlloc2(unsigned newLimit) { CHECK_STRING_ALLOC_LEN(newLimit) // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); newBuf[0] = 0; MY_STRING_DELETE(_chars) _chars = newBuf; _limit = newLimit; _len = 0; } void UString::SetStartLen(unsigned len) { _chars = NULL; _chars = MY_STRING_NEW_wchar_t((size_t)len + 1); _len = len; _limit = len; } Z7_NO_INLINE void UString::Grow_1() { unsigned next = _len; next += next / 2; next += 16; next &= ~(unsigned)15; next--; if (next < _len || next > k_Alloc_Len_Limit) next = k_Alloc_Len_Limit; if (next <= _len) THROW_STRING_ALLOC_EXCEPTION ReAlloc(next); } void UString::Grow(unsigned n) { const unsigned freeSize = _limit - _len; if (n <= freeSize) return; unsigned next = _len + n; next += next / 2; next += 16; next &= ~(unsigned)15; next--; if (next < _len || next > k_Alloc_Len_Limit) next = k_Alloc_Len_Limit; if (next <= _len || next - _len < n) THROW_STRING_ALLOC_EXCEPTION ReAlloc(next - 1); } UString::UString(unsigned num, const wchar_t *s) { unsigned len = MyStringLen(s); if (num > len) num = len; SetStartLen(num); wmemcpy(_chars, s, num); _chars[num] = 0; } UString::UString(unsigned num, const UString &s) { if (num > s._len) num = s._len; SetStartLen(num); wmemcpy(_chars, s._chars, num); _chars[num] = 0; } UString::UString(const UString &s, wchar_t c) { SetStartLen(s.Len() + 1); wchar_t *chars = _chars; unsigned len = s.Len(); wmemcpy(chars, s, len); chars[len] = c; chars[(size_t)len + 1] = 0; } UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) { SetStartLen(num1 + num2); wchar_t *chars = _chars; wmemcpy(chars, s1, num1); wmemcpy(chars + num1, s2, num2 + 1); } UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } UString::UString() { _chars = NULL; _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity); _len = 0; _limit = kStartStringCapacity - 1; _chars[0] = 0; } UString::UString(wchar_t c) { SetStartLen(1); wchar_t *chars = _chars; chars[0] = c; chars[1] = 0; } UString::UString(char c) { SetStartLen(1); wchar_t *chars = _chars; chars[0] = (unsigned char)c; chars[1] = 0; } UString::UString(const wchar_t *s) { const unsigned len = MyStringLen(s); SetStartLen(len); wmemcpy(_chars, s, len + 1); } UString::UString(const char *s) { const unsigned len = MyStringLen(s); SetStartLen(len); wchar_t *chars = _chars; for (unsigned i = 0; i < len; i++) chars[i] = (unsigned char)s[i]; chars[len] = 0; } UString::UString(const AString &s) { const unsigned len = s.Len(); SetStartLen(len); wchar_t *chars = _chars; const char *s2 = s.Ptr(); for (unsigned i = 0; i < len; i++) chars[i] = (unsigned char)s2[i]; chars[len] = 0; } UString::UString(const UString &s) { SetStartLen(s._len); wmemcpy(_chars, s._chars, s._len + 1); } UString &UString::operator=(wchar_t c) { if (1 > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = 1; } _len = 1; wchar_t *chars = _chars; chars[0] = c; chars[1] = 0; return *this; } UString &UString::operator=(const wchar_t *s) { unsigned len = MyStringLen(s); if (len > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; wmemcpy(_chars, s, len + 1); return *this; } UString &UString::operator=(const UString &s) { if (&s == this) return *this; unsigned len = s._len; if (len > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; wmemcpy(_chars, s._chars, len + 1); return *this; } void UString::SetFrom(const wchar_t *s, unsigned len) // no check { if (len > _limit) { CHECK_STRING_ALLOC_LEN(len) wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } if (len != 0) wmemcpy(_chars, s, len); _chars[len] = 0; _len = len; } void UString::SetFromBstr(LPCOLESTR s) { unsigned len = ::SysStringLen((BSTR)(void *)(s)); /* #if WCHAR_MAX > 0xffff size_t num_wchars = 0; for (size_t i = 0; i < len;) { wchar_t c = s[i++]; if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) { wchar_t c2 = s[i]; if (c2 >= 0xdc00 && c2 < 0xe000) { c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); i++; } } num_wchars++; } len = num_wchars; #endif */ if (len > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } _len = len; /* #if WCHAR_MAX > 0xffff wchar_t *chars = _chars; for (size_t i = 0; i <= len; i++) { wchar_t c = *s++; if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) { wchar_t c2 = *s; if (c2 >= 0xdc00 && c2 < 0xe000) { s++; c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); } } chars[i] = c; } #else */ // if (s) wmemcpy(_chars, s, len + 1); // #endif } UString &UString::operator=(const char *s) { unsigned len = MyStringLen(s); if (len > _limit) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); MY_STRING_DELETE(_chars) _chars = newBuf; _limit = len; } wchar_t *chars = _chars; for (unsigned i = 0; i < len; i++) chars[i] = (unsigned char)s[i]; chars[len] = 0; _len = len; return *this; } void UString::Add_Char(char c) { operator+=((wchar_t)(unsigned char)c); } // void UString::Add_WChar(wchar_t c) { operator+=(c); } void UString::Add_Dot() { operator+=(L'.'); } void UString::Add_Space() { operator+=(L' '); } void UString::Add_Minus() { operator+=(L'-'); } void UString::Add_Colon() { operator+=(L':'); } void UString::Add_LF() { operator+=(L'\n'); } void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } UString &UString::operator+=(const wchar_t *s) { unsigned len = MyStringLen(s); Grow(len); wmemcpy(_chars + _len, s, len + 1); _len += len; return *this; } UString &UString::operator+=(const UString &s) { Grow(s._len); wmemcpy(_chars + _len, s._chars, s._len + 1); _len += s._len; return *this; } UString &UString::operator+=(const char *s) { unsigned len = MyStringLen(s); Grow(len); wchar_t *chars = _chars + _len; for (unsigned i = 0; i < len; i++) chars[i] = (unsigned char)s[i]; chars[len] = 0; _len += len; return *this; } void UString::Add_UInt32(UInt32 v) { Grow(10); _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } void AString::Add_UInt64(UInt64 v) { Grow(20); _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); } int UString::Find(const wchar_t *s, unsigned startIndex) const throw() { const wchar_t *fs = wcsstr(_chars + startIndex, s); if (!fs) return -1; return (int)(fs - _chars); /* if (s[0] == 0) return startIndex; unsigned len = MyStringLen(s); const wchar_t *p = _chars + startIndex; for (;; p++) { const wchar_t c = *p; if (c != s[0]) { if (c == 0) return -1; continue; } unsigned i; for (i = 1; i < len; i++) if (p[i] != s[i]) break; if (i == len) return (int)(p - _chars); } */ } int UString::ReverseFind(wchar_t c) const throw() { if (_len == 0) return -1; const wchar_t *p = _chars + _len; do { if (*(--p) == c) return (int)(p - _chars); } while (p != _chars); return -1; } int UString::ReverseFind_PathSepar() const throw() { const wchar_t *p = _chars + _len; while (p != _chars) { const wchar_t c = *(--p); if (IS_PATH_SEPAR(c)) return (int)(p - _chars); } return -1; } void UString::TrimLeft() throw() { const wchar_t *p = _chars; for (;; p++) { wchar_t c = *p; if (c != ' ' && c != '\n' && c != '\t') break; } unsigned pos = (unsigned)(p - _chars); if (pos != 0) { MoveItems(0, pos); _len -= pos; } } void UString::TrimRight() throw() { const wchar_t *p = _chars; unsigned i; for (i = _len; i != 0; i--) { wchar_t c = p[(size_t)i - 1]; if (c != ' ' && c != '\n' && c != '\t') break; } if (i != _len) { _chars[i] = 0; _len = i; } } void UString::InsertAtFront(wchar_t c) { if (_limit == _len) Grow_1(); MoveItems(1, 0); _chars[0] = c; _len++; } /* void UString::Insert_wchar_t(unsigned index, wchar_t c) { InsertSpace(index, 1); _chars[index] = c; _len++; } */ void UString::Insert(unsigned index, const wchar_t *s) { unsigned num = MyStringLen(s); if (num != 0) { InsertSpace(index, num); wmemcpy(_chars + index, s, num); _len += num; } } void UString::Insert(unsigned index, const UString &s) { unsigned num = s.Len(); if (num != 0) { InsertSpace(index, num); wmemcpy(_chars + index, s, num); _len += num; } } void UString::RemoveChar(wchar_t ch) throw() { wchar_t *src = _chars; for (;;) { wchar_t c = *src++; if (c == 0) return; if (c == ch) break; } wchar_t *dest = src - 1; for (;;) { wchar_t c = *src++; if (c == 0) break; if (c != ch) *dest++ = c; } *dest = 0; _len = (unsigned)(dest - _chars); } // !!!!!!!!!!!!!!! test it if newChar = '\0' void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() { if (oldChar == newChar) return; // 0; // unsigned number = 0; int pos = 0; wchar_t *chars = _chars; while ((unsigned)pos < _len) { pos = Find(oldChar, (unsigned)pos); if (pos < 0) break; chars[(unsigned)pos] = newChar; pos++; // number++; } return; // number; } void UString::Replace(const UString &oldString, const UString &newString) { if (oldString.IsEmpty()) return; // 0; if (oldString == newString) return; // 0; unsigned oldLen = oldString.Len(); unsigned newLen = newString.Len(); // unsigned number = 0; int pos = 0; while ((unsigned)pos < _len) { pos = Find(oldString, (unsigned)pos); if (pos < 0) break; Delete((unsigned)pos, oldLen); Insert((unsigned)pos, newString); pos += newLen; // number++; } // return number; } void UString::Delete(unsigned index) throw() { MoveItems(index, index + 1); _len--; } void UString::Delete(unsigned index, unsigned count) throw() { if (index + count > _len) count = _len - index; if (count > 0) { MoveItems(index, index + count); _len -= count; } } void UString::DeleteFrontal(unsigned num) throw() { if (num != 0) { MoveItems(0, num); _len -= num; } } // ---------- UString2 ---------- void UString2::ReAlloc2(unsigned newLimit) { // wrong (_len) is allowed after this function CHECK_STRING_ALLOC_LEN(newLimit) // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); if (_chars) { MY_STRING_DELETE(_chars) _chars = NULL; // _len = 0; } _chars = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); _chars[0] = 0; // _len = newLimit; } void UString2::SetStartLen(unsigned len) { _chars = NULL; _chars = MY_STRING_NEW_wchar_t((size_t)len + 1); _len = len; } /* UString2::UString2(wchar_t c) { SetStartLen(1); wchar_t *chars = _chars; chars[0] = c; chars[1] = 0; } */ UString2::UString2(const wchar_t *s) { const unsigned len = MyStringLen(s); SetStartLen(len); wmemcpy(_chars, s, len + 1); } UString2::UString2(const UString2 &s): _chars(NULL), _len(0) { if (s._chars) { SetStartLen(s._len); wmemcpy(_chars, s._chars, s._len + 1); } } /* UString2 &UString2::operator=(wchar_t c) { if (1 > _len) { wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); if (_chars) MY_STRING_DELETE(_chars) _chars = newBuf; } _len = 1; wchar_t *chars = _chars; chars[0] = c; chars[1] = 0; return *this; } */ UString2 &UString2::operator=(const wchar_t *s) { unsigned len = MyStringLen(s); if (len > _len) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); if (_chars) MY_STRING_DELETE(_chars) _chars = newBuf; } _len = len; MyStringCopy(_chars, s); return *this; } void UString2::SetFromAscii(const char *s) { unsigned len = MyStringLen(s); if (len > _len) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); if (_chars) MY_STRING_DELETE(_chars) _chars = newBuf; } wchar_t *chars = _chars; for (unsigned i = 0; i < len; i++) chars[i] = (unsigned char)s[i]; chars[len] = 0; _len = len; } UString2 &UString2::operator=(const UString2 &s) { if (&s == this) return *this; unsigned len = s._len; if (len > _len) { wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); if (_chars) MY_STRING_DELETE(_chars) _chars = newBuf; } _len = len; MyStringCopy(_chars, s._chars); return *this; } bool operator==(const UString2 &s1, const UString2 &s2) { return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0); } bool operator==(const UString2 &s1, const wchar_t *s2) { if (s1.IsEmpty()) return (*s2 == 0); return wcscmp(s1.GetRawPtr(), s2) == 0; } bool operator==(const wchar_t *s1, const UString2 &s2) { if (s2.IsEmpty()) return (*s1 == 0); return wcscmp(s1, s2.GetRawPtr()) == 0; } // ---------------------------------------- /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ #if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE) static inline UINT GetCurrentCodePage() { #if defined(UNDER_CE) || !defined(_WIN32) return CP_ACP; #else return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; #endif } #endif #ifdef USE_UNICODE_FSTRING #ifndef _UNICODE AString fs2fas(CFSTR s) { return UnicodeStringToMultiByte(s, GetCurrentCodePage()); } FString fas2fs(const char *s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); } FString fas2fs(const AString &s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); } #endif // _UNICODE #else // USE_UNICODE_FSTRING UString fs2us(const FChar *s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); } UString fs2us(const FString &s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); } FString us2fs(const wchar_t *s) { return UnicodeStringToMultiByte(s, GetCurrentCodePage()); } #endif // USE_UNICODE_FSTRING bool CStringFinder::FindWord_In_LowCaseAsciiList_NoCase(const char *p, const wchar_t *str) { _temp.Empty(); for (;;) { const wchar_t c = *str++; if (c == 0) break; if (c <= 0x20 || c > 0x7f) return false; _temp.Add_Char((char)MyCharLower_Ascii((char)c)); } while (*p != 0) { const char *s2 = _temp.Ptr(); char c, c2; do { c = *p++; c2 = *s2++; } while (c == c2); if (c == ' ') { if (c2 == 0) return true; continue; } while (*p++ != ' '); } return false; } void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); unsigned len = srcString.Len(); if (len == 0) return; UString s; for (unsigned i = 0; i < len; i++) { const wchar_t c = srcString[i]; if (c == ' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } tmp41wklro_/CPP/Common/MyString.h0000444000175000001440000007761314553427220017762 0ustar nabijaczleweliusers// Common/MyString.h #ifndef ZIP7_INC_COMMON_MY_STRING_H #define ZIP7_INC_COMMON_MY_STRING_H #include #ifndef _WIN32 #include #include #endif #include "Common.h" #include "MyWindows.h" #include "MyTypes.h" #include "MyVector.h" /* if (DEBUG_FSTRING_INHERITS_ASTRING is defined), then FString inherits from AString, so we can find bugs related to FString at compile time. DON'T define DEBUG_FSTRING_INHERITS_ASTRING in release code */ // #define DEBUG_FSTRING_INHERITS_ASTRING #ifdef DEBUG_FSTRING_INHERITS_ASTRING class FString; #endif #ifdef _MSC_VER #ifdef _NATIVE_WCHAR_T_DEFINED #define MY_NATIVE_WCHAR_T_DEFINED #endif #else #define MY_NATIVE_WCHAR_T_DEFINED #endif /* native support for wchar_t: _MSC_VER == 1600 : /Zc:wchar_t is not supported _MSC_VER == 1310 (VS2003) ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED _MSC_VER > 1400 (VS2008+) /Zc:wchar_t[-] /Zc:wchar_t is on by default */ #ifdef _WIN32 #define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/') #else #define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR) #endif inline bool IsPathSepar(char c) { return IS_PATH_SEPAR(c); } inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); } inline unsigned MyStringLen(const char *s) { unsigned i; for (i = 0; s[i] != 0; i++); return i; } inline void MyStringCopy(char *dest, const char *src) { while ((*dest++ = *src++) != 0); } inline char *MyStpCpy(char *dest, const char *src) { for (;;) { const char c = *src; *dest = c; if (c == 0) return dest; src++; dest++; } } inline void MyStringCat(char *dest, const char *src) { for (; *dest != 0; dest++); while ((*dest++ = *src++) != 0); // MyStringCopy(dest + MyStringLen(dest), src); } inline unsigned MyStringLen(const wchar_t *s) { unsigned i; for (i = 0; s[i] != 0; i++); return i; } inline void MyStringCopy(wchar_t *dest, const wchar_t *src) { while ((*dest++ = *src++) != 0); } inline void MyStringCat(wchar_t *dest, const wchar_t *src) { for (; *dest != 0; dest++); while ((*dest++ = *src++) != 0); // MyStringCopy(dest + MyStringLen(dest), src); } /* inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src) { for (;;) { const wchar_t c = *src; *dest = c; if (c == 0) return dest; src++; dest++; } } */ int FindCharPosInString(const char *s, char c) throw(); int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); #ifdef _WIN32 #ifndef _UNICODE #define STRING_UNICODE_THROW #endif #endif #ifndef STRING_UNICODE_THROW #define STRING_UNICODE_THROW throw() #endif inline char MyCharUpper_Ascii(char c) { if (c >= 'a' && c <= 'z') return (char)((unsigned char)c - 0x20); return c; } /* inline wchar_t MyCharUpper_Ascii(wchar_t c) { if (c >= 'a' && c <= 'z') return (wchar_t)(c - 0x20); return c; } */ inline char MyCharLower_Ascii(char c) { if (c >= 'A' && c <= 'Z') return (char)((unsigned char)c + 0x20); return c; } inline wchar_t MyCharLower_Ascii(wchar_t c) { if (c >= 'A' && c <= 'Z') return (wchar_t)(c + 0x20); return c; } wchar_t MyCharUpper_WIN(wchar_t c) throw(); inline wchar_t MyCharUpper(wchar_t c) throw() { if (c < 'a') return c; if (c <= 'z') return (wchar_t)(c - 0x20); if (c <= 0x7F) return c; #ifdef _WIN32 #ifdef _UNICODE return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); #else return (wchar_t)MyCharUpper_WIN(c); #endif #else return (wchar_t)towupper((wint_t)c); #endif } /* wchar_t MyCharLower_WIN(wchar_t c) throw(); inline wchar_t MyCharLower(wchar_t c) throw() { if (c < 'A') return c; if (c <= 'Z') return (wchar_t)(c + 0x20); if (c <= 0x7F) return c; #ifdef _WIN32 #ifdef _UNICODE return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); #else return (wchar_t)MyCharLower_WIN(c); #endif #else return (wchar_t)tolower(c); #endif } */ // char *MyStringUpper(char *s) throw(); // char *MyStringLower(char *s) throw(); // void MyStringUpper_Ascii(char *s) throw(); // void MyStringUpper_Ascii(wchar_t *s) throw(); void MyStringLower_Ascii(char *s) throw(); void MyStringLower_Ascii(wchar_t *s) throw(); // wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW; // wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW; bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw(); bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw(); bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw(); bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw(); #define MyStringCompare(s1, s2) wcscmp(s1, s2) int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); // int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); // ---------- ASCII ---------- // char values in ASCII strings must be less then 128 bool StringsAreEqual_Ascii(const char *u, const char *a) throw(); bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); #define MY_STRING_DELETE(_p_) { delete [](_p_); } // #define MY_STRING_DELETE(_p_) my_delete(_p_); #define FORBID_STRING_OPS_2(cls, t) \ void Find(t) const; \ void Find(t, unsigned startIndex) const; \ void ReverseFind(t) const; \ void InsertAtFront(t); \ void RemoveChar(t); \ void Replace(t, t); \ #define FORBID_STRING_OPS(cls, t) \ explicit cls(t); \ explicit cls(const t *); \ cls &operator=(t); \ cls &operator=(const t *); \ cls &operator+=(t); \ cls &operator+=(const t *); \ FORBID_STRING_OPS_2(cls, t) \ /* cls &operator+(t); \ cls &operator+(const t *); \ */ #define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t) #define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t) #define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t) class AString { char *_chars; unsigned _len; unsigned _limit; void MoveItems(unsigned dest, unsigned src) { memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char)); } void InsertSpace(unsigned &index, unsigned size); void ReAlloc(unsigned newLimit); void ReAlloc2(unsigned newLimit); void SetStartLen(unsigned len); Z7_NO_INLINE void Grow_1(); void Grow(unsigned n); AString(unsigned num, const char *s); AString(unsigned num, const AString &s); AString(const AString &s, char c); // it's for String + char AString(const char *s1, unsigned num1, const char *s2, unsigned num2); friend AString operator+(const AString &s, char c) { return AString(s, c); } // friend AString operator+(char c, const AString &s); // is not supported friend AString operator+(const AString &s1, const AString &s2); friend AString operator+(const AString &s1, const char *s2); friend AString operator+(const char *s1, const AString &s2); // ---------- forbidden functions ---------- #ifdef MY_NATIVE_WCHAR_T_DEFINED FORBID_STRING_OPS_AString(wchar_t) #endif FORBID_STRING_OPS_AString(signed char) FORBID_STRING_OPS_AString(unsigned char) FORBID_STRING_OPS_AString(short) FORBID_STRING_OPS_AString(unsigned short) FORBID_STRING_OPS_AString(int) FORBID_STRING_OPS_AString(unsigned) FORBID_STRING_OPS_AString(long) FORBID_STRING_OPS_AString(unsigned long) #ifdef DEBUG_FSTRING_INHERITS_ASTRING AString(const FString &s); AString &operator=(const FString &s); AString &operator+=(const FString &s); #endif public: explicit AString(); explicit AString(char c); explicit AString(const char *s); AString(const AString &s); ~AString() { MY_STRING_DELETE(_chars) } unsigned Len() const { return _len; } bool IsEmpty() const { return _len == 0; } void Empty() { _len = 0; _chars[0] = 0; } operator const char *() const { return _chars; } char *Ptr_non_const() const { return _chars; } const char *Ptr() const { return _chars; } const char *Ptr(unsigned pos) const { return _chars + pos; } const char *Ptr(int pos) const { return _chars + (unsigned)pos; } const char *RightPtr(unsigned num) const { return _chars + _len - num; } char Back() const { return _chars[(size_t)_len - 1]; } void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } char *GetBuf() { return _chars; } /* GetBuf(minLen): provides the buffer that can store at least (minLen) characters and additional null terminator. 9.35: GetBuf doesn't preserve old characters and terminator */ char *GetBuf(unsigned minLen) { if (minLen > _limit) ReAlloc2(minLen); return _chars; } char *GetBuf_SetEnd(unsigned minLen) { if (minLen > _limit) ReAlloc2(minLen); char *chars = _chars; chars[minLen] = 0; _len = minLen; return chars; } void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } void ReleaseBuf_CalcLen(unsigned maxLen) { char *chars = _chars; chars[maxLen] = 0; _len = MyStringLen(chars); } AString &operator=(char c); AString &operator=(const char *s); AString &operator=(const AString &s); void SetFromWStr_if_Ascii(const wchar_t *s); // void SetFromBstr_if_Ascii(BSTR s); // private: Z7_FORCE_INLINE AString &operator+=(char c) { if (_limit == _len) Grow_1(); unsigned len = _len; char *chars = _chars; chars[len++] = c; chars[len] = 0; _len = len; return *this; } public: void Add_Space(); void Add_Space_if_NotEmpty(); void Add_OptSpaced(const char *s); void Add_Char(char c); void Add_LF(); void Add_Slash(); void Add_Dot(); void Add_Minus(); void Add_Colon(); void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } AString &operator+=(const char *s); AString &operator+=(const AString &s); void Add_UInt32(UInt32 v); void Add_UInt64(UInt64 v); void AddFrom(const char *s, unsigned len); // no check void SetFrom(const char *s, unsigned len); // no check void SetFrom_Chars_SizeT(const char* s, size_t len); // no check void SetFrom(const char* s, int len) // no check { SetFrom(s, (unsigned)len); // no check } void SetFrom_CalcLen(const char *s, unsigned len); AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } AString Left(unsigned count) const { return AString(count, *this); } // void MakeUpper() { MyStringUpper(_chars); } // void MakeLower() { MyStringLower(_chars); } void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; } bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } // int Compare(const char *s) const { return MyStringCompare(_chars, s); } // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); } // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); bool IsAscii() const { unsigned len = Len(); const char *s = _chars; for (unsigned i = 0; i < len; i++) if ((unsigned char)s[i] >= 0x80) return false; return true; } int Find(char c) const { return FindCharPosInString(_chars, c); } int Find(char c, unsigned startIndex) const { const int pos = FindCharPosInString(_chars + startIndex, c); return pos < 0 ? -1 : (int)startIndex + pos; } int Find(char c, int startIndex) const { return Find(c, (unsigned)startIndex); } int ReverseFind(char c) const throw(); int ReverseFind_Dot() const throw() { return ReverseFind('.'); } int ReverseFind_PathSepar() const throw(); int Find(const char *s) const { return Find(s, 0); } int Find(const char *s, unsigned startIndex) const throw(); void TrimLeft() throw(); void TrimRight() throw(); void Trim() { TrimRight(); TrimLeft(); } void InsertAtFront(char c); // void Insert(unsigned index, char c); void Insert(unsigned index, const char *s); void Insert(unsigned index, const AString &s); void RemoveChar(char ch) throw(); void Replace(char oldChar, char newChar) throw(); void Replace(const AString &oldString, const AString &newString); void Delete(unsigned index) throw(); void Delete(unsigned index, unsigned count) throw(); void DeleteFrontal(unsigned num) throw(); void DeleteBack() { _chars[--_len] = 0; } void DeleteFrom(unsigned index) { if (index < _len) { _len = index; _chars[index] = 0; } } void DeleteFrom(int index) { DeleteFrom((unsigned)index); } void Wipe_and_Empty() { if (_chars) { memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); _len = 0; } } }; class AString_Wipe: public AString { Z7_CLASS_NO_COPY(AString_Wipe) public: AString_Wipe(): AString() {} // AString_Wipe(const AString &s): AString(s) {} // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; } // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; } ~AString_Wipe() { Wipe_and_Empty(); } }; bool operator<(const AString &s1, const AString &s2); bool operator>(const AString &s1, const AString &s2); /* bool operator==(const AString &s1, const AString &s2); bool operator==(const AString &s1, const char *s2); bool operator==(const char *s1, const AString &s2); bool operator!=(const AString &s1, const AString &s2); bool operator!=(const AString &s1, const char *s2); bool operator!=(const char *s1, const AString &s2); */ inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; } inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; } inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; } inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; } inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; } inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; } // ---------- forbidden functions ---------- void operator==(char c1, const AString &s2); void operator==(const AString &s1, char c2); void operator+(char c, const AString &s); // this function can be OK, but we don't use it void operator+(const AString &s, int c); void operator+(const AString &s, unsigned c); void operator+(int c, const AString &s); void operator+(unsigned c, const AString &s); void operator-(const AString &s, int c); void operator-(const AString &s, unsigned c); class UString { wchar_t *_chars; unsigned _len; unsigned _limit; void MoveItems(unsigned dest, unsigned src) { memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t)); } void InsertSpace(unsigned index, unsigned size); void ReAlloc(unsigned newLimit); void ReAlloc2(unsigned newLimit); void SetStartLen(unsigned len); void Grow_1(); void Grow(unsigned n); UString(unsigned num, const wchar_t *s); // for Mid UString(unsigned num, const UString &s); // for Left UString(const UString &s, wchar_t c); // it's for String + char UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } // friend UString operator+(wchar_t c, const UString &s); // is not supported friend UString operator+(const UString &s1, const UString &s2); friend UString operator+(const UString &s1, const wchar_t *s2); friend UString operator+(const wchar_t *s1, const UString &s2); // ---------- forbidden functions ---------- FORBID_STRING_OPS_UString(signed char) FORBID_STRING_OPS_UString(unsigned char) FORBID_STRING_OPS_UString(short) #ifdef MY_NATIVE_WCHAR_T_DEFINED FORBID_STRING_OPS_UString(unsigned short) #endif FORBID_STRING_OPS_UString(int) FORBID_STRING_OPS_UString(unsigned) FORBID_STRING_OPS_UString(long) FORBID_STRING_OPS_UString(unsigned long) FORBID_STRING_OPS_2(UString, char) #ifdef DEBUG_FSTRING_INHERITS_ASTRING UString(const FString &s); UString &operator=(const FString &s); UString &operator+=(const FString &s); #endif public: UString(); explicit UString(wchar_t c); explicit UString(char c); explicit UString(const char *s); explicit UString(const AString &s); UString(const wchar_t *s); UString(const UString &s); ~UString() { MY_STRING_DELETE(_chars) } unsigned Len() const { return _len; } bool IsEmpty() const { return _len == 0; } void Empty() { _len = 0; _chars[0] = 0; } operator const wchar_t *() const { return _chars; } wchar_t *Ptr_non_const() const { return _chars; } const wchar_t *Ptr() const { return _chars; } const wchar_t *Ptr(int pos) const { return _chars + (unsigned)pos; } const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } wchar_t Back() const { return _chars[(size_t)_len - 1]; } void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } wchar_t *GetBuf() { return _chars; } /* wchar_t *GetBuf_GetMaxAvail(unsigned &availBufLen) { availBufLen = _limit; return _chars; } */ wchar_t *GetBuf(unsigned minLen) { if (minLen > _limit) ReAlloc2(minLen); return _chars; } wchar_t *GetBuf_SetEnd(unsigned minLen) { if (minLen > _limit) ReAlloc2(minLen); wchar_t *chars = _chars; chars[minLen] = 0; _len = minLen; return chars; } void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } void ReleaseBuf_CalcLen(unsigned maxLen) { wchar_t *chars = _chars; chars[maxLen] = 0; _len = MyStringLen(chars); } UString &operator=(wchar_t c); UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); } UString &operator=(const wchar_t *s); UString &operator=(const UString &s); void SetFrom(const wchar_t *s, unsigned len); // no check void SetFromBstr(LPCOLESTR s); UString &operator=(const char *s); UString &operator=(const AString &s) { return operator=(s.Ptr()); } // private: Z7_FORCE_INLINE UString &operator+=(wchar_t c) { if (_limit == _len) Grow_1(); unsigned len = _len; wchar_t *chars = _chars; chars[len++] = c; chars[len] = 0; _len = len; return *this; } private: UString &operator+=(char c); // { return (*this)+=((wchar_t)(unsigned char)c); } public: void Add_Char(char c); // void Add_WChar(wchar_t c); void Add_Space(); void Add_Space_if_NotEmpty(); void Add_LF(); void Add_Dot(); void Add_Minus(); void Add_Colon(); void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); } UString &operator+=(const wchar_t *s); UString &operator+=(const UString &s); UString &operator+=(const char *s); UString &operator+=(const AString &s) { return operator+=(s.Ptr()); } void Add_UInt32(UInt32 v); void Add_UInt64(UInt64 v); UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } UString Left(unsigned count) const { return UString(count, *this); } UString Left(int count) const { return Left((unsigned)count); } // void MakeUpper() { MyStringUpper(_chars); } // void MakeUpper() { MyStringUpper_Ascii(_chars); } // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); } void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); } bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); } bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); } // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); } bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); } bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); bool IsAscii() const { unsigned len = Len(); const wchar_t *s = _chars; for (unsigned i = 0; i < len; i++) if (s[i] >= 0x80) return false; return true; } int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } int Find(wchar_t c, unsigned startIndex) const { int pos = FindCharPosInString(_chars + startIndex, c); return pos < 0 ? -1 : (int)startIndex + pos; } int ReverseFind(wchar_t c) const throw(); int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); } int ReverseFind_PathSepar() const throw(); int Find(const wchar_t *s) const { return Find(s, 0); } int Find(const wchar_t *s, unsigned startIndex) const throw(); void TrimLeft() throw(); void TrimRight() throw(); void Trim() { TrimRight(); TrimLeft(); } void InsertAtFront(wchar_t c); // void Insert_wchar_t(unsigned index, wchar_t c); void Insert(unsigned index, const wchar_t *s); void Insert(unsigned index, const UString &s); void RemoveChar(wchar_t ch) throw(); void Replace(wchar_t oldChar, wchar_t newChar) throw(); void Replace(const UString &oldString, const UString &newString); void Delete(int index) throw() { Delete((unsigned)index); } void Delete(unsigned index) throw(); void Delete(unsigned index, unsigned count) throw(); void DeleteFrontal(unsigned num) throw(); void DeleteBack() { _chars[--_len] = 0; } void DeleteFrom(int index) { DeleteFrom((unsigned)index); } void DeleteFrom(unsigned index) { if (index < _len) { _len = index; _chars[index] = 0; } } void Wipe_and_Empty() { if (_chars) { memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); _len = 0; } } }; class UString_Wipe: public UString { Z7_CLASS_NO_COPY(UString_Wipe) public: UString_Wipe(): UString() {} // UString_Wipe(const UString &s): UString(s) {} // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; } // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; } ~UString_Wipe() { Wipe_and_Empty(); } }; bool operator<(const UString &s1, const UString &s2); bool operator>(const UString &s1, const UString &s2); inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; } inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; } inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; } inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; } inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; } inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; } // ---------- forbidden functions ---------- void operator==(wchar_t c1, const UString &s2); void operator==(const UString &s1, wchar_t c2); void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it void operator+(const AString &s1, const UString &s2); void operator+(const UString &s1, const AString &s2); void operator+(const UString &s1, const char *s2); void operator+(const char *s1, const UString &s2); void operator+(const UString &s, char c); void operator+(const UString &s, unsigned char c); void operator+(char c, const UString &s); void operator+(unsigned char c, const UString &s); void operator-(const UString &s1, wchar_t c); #ifdef _WIN32 // can we forbid these functions, if wchar_t is 32-bit ? void operator+(const UString &s, int c); void operator+(const UString &s, unsigned c); void operator+(int c, const UString &s); void operator+(unsigned c, const UString &s); void operator-(const UString &s1, int c); void operator-(const UString &s1, unsigned c); #endif class UString2 { wchar_t *_chars; unsigned _len; void ReAlloc2(unsigned newLimit); void SetStartLen(unsigned len); // ---------- forbidden functions ---------- FORBID_STRING_OPS_UString2(char) FORBID_STRING_OPS_UString2(signed char) FORBID_STRING_OPS_UString2(unsigned char) FORBID_STRING_OPS_UString2(short) UString2 &operator=(wchar_t c); UString2(const AString &s); UString2 &operator=(const AString &s); UString2 &operator+=(const AString &s); #ifdef DEBUG_FSTRING_INHERITS_ASTRING UString2(const FString &s); UString2 &operator=(const FString &s); UString2 &operator+=(const FString &s); #endif public: UString2(): _chars(NULL), _len(0) {} UString2(const wchar_t *s); UString2(const UString2 &s); ~UString2() { if (_chars) { MY_STRING_DELETE(_chars) } } unsigned Len() const { return _len; } bool IsEmpty() const { return _len == 0; } // void Empty() { _len = 0; _chars[0] = 0; } // operator const wchar_t *() const { return _chars; } const wchar_t *GetRawPtr() const { return _chars; } int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } wchar_t *GetBuf(unsigned minLen) { if (!_chars || minLen > _len) ReAlloc2(minLen); return _chars; } void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } UString2 &operator=(const wchar_t *s); UString2 &operator=(const UString2 &s); void SetFromAscii(const char *s); }; bool operator==(const UString2 &s1, const UString2 &s2); bool operator==(const UString2 &s1, const wchar_t *s2); bool operator==(const wchar_t *s1, const UString2 &s2); inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); } inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); } inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); } // ---------- forbidden functions ---------- void operator==(wchar_t c1, const UString2 &s2); void operator==(const UString2 &s1, wchar_t c2); bool operator<(const UString2 &s1, const UString2 &s2); bool operator>(const UString2 &s1, const UString2 &s2); void operator+(const UString2 &s1, const UString2 &s2); void operator+(const UString2 &s1, const wchar_t *s2); void operator+(const wchar_t *s1, const UString2 &s2); void operator+(wchar_t c, const UString2 &s); void operator+(const UString2 &s, wchar_t c); void operator+(const UString2 &s, char c); void operator+(const UString2 &s, unsigned char c); void operator+(char c, const UString2 &s); void operator+(unsigned char c, const UString2 &s); void operator-(const UString2 &s1, wchar_t c); typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector CSysStringVector; // ---------- FString ---------- #ifndef DEBUG_FSTRING_INHERITS_ASTRING #ifdef _WIN32 #define USE_UNICODE_FSTRING #endif #endif #ifdef USE_UNICODE_FSTRING #define MY_FTEXT(quote) L##quote typedef wchar_t FChar; typedef UString FString; #define fs2us(_x_) (_x_) #define us2fs(_x_) (_x_) FString fas2fs(const char *s); FString fas2fs(const AString &s); AString fs2fas(const FChar *s); #else // USE_UNICODE_FSTRING #define MY_FTEXT(quote) quote typedef char FChar; #ifdef DEBUG_FSTRING_INHERITS_ASTRING class FString: public AString { // FString &operator=(const char *s); FString &operator=(const AString &s); // FString &operator+=(const AString &s); public: FString(const AString &s): AString(s.Ptr()) {} FString(const FString &s): AString(s.Ptr()) {} FString(const char *s): AString(s) {} FString() {} FString &operator=(const FString &s) { AString::operator=((const AString &)s); return *this; } FString &operator=(char c) { AString::operator=(c); return *this; } FString &operator+=(char c) { AString::operator+=(c); return *this; } FString &operator+=(const FString &s) { AString::operator+=((const AString &)s); return *this; } FString Left(unsigned count) const { return FString(AString::Left(count)); } }; void operator+(const AString &s1, const FString &s2); void operator+(const FString &s1, const AString &s2); inline FString operator+(const FString &s1, const FString &s2) { AString s =(const AString &)s1 + (const AString &)s2; return FString(s.Ptr()); // return FString((const AString &)s1 + (const AString &)s2); } inline FString operator+(const FString &s1, const FChar *s2) { return s1 + (FString)s2; } /* inline FString operator+(const FChar *s1, const FString &s2) { return (FString)s1 + s2; } */ inline FString fas2fs(const char *s) { return FString(s); } #else // DEBUG_FSTRING_INHERITS_ASTRING typedef AString FString; #define fas2fs(_x_) (_x_) #endif // DEBUG_FSTRING_INHERITS_ASTRING UString fs2us(const FChar *s); UString fs2us(const FString &s); FString us2fs(const wchar_t *s); #define fs2fas(_x_) (_x_) #endif // USE_UNICODE_FSTRING #define FTEXT(quote) MY_FTEXT(quote) #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) // #define FCHAR_ANY_MASK FTEXT('*') // #define FSTRING_ANY_MASK FTEXT("*") typedef const FChar *CFSTR; typedef CObjectVector FStringVector; class CStringFinder { AString _temp; public: // list - is list of low case Ascii strings separated by space " ". // the function returns true, if it can find exact word (str) in (list). bool FindWord_In_LowCaseAsciiList_NoCase(const char *list, const wchar_t *str); }; void SplitString(const UString &srcString, UStringVector &destStrings); #endif #if defined(_WIN32) // #include // WCHAR_MAX is defined as ((wchar_t)-1) #define Z7_WCHART_IS_16BIT 1 #elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \ || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2)) #define Z7_WCHART_IS_16BIT 1 #endif #if WCHAR_PATH_SEPARATOR == L'\\' // WSL scheme #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\')) // #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT '_' #endif tmp41wklro_/CPP/Common/MyTypes.h0000444000175000001440000000101014554701240017570 0ustar nabijaczleweliusers// Common/MyTypes.h #ifndef ZIP7_INC_COMMON_MY_TYPES_H #define ZIP7_INC_COMMON_MY_TYPES_H #include "Common0.h" #include "../../C/7zTypes.h" // typedef int HRes; // typedef HRESULT HRes; struct CBoolPair { bool Val; bool Def; CBoolPair(): Val(false), Def(false) {} void Init() { Val = false; Def = false; } void SetTrueTrue() { Val = true; Def = true; } void SetVal_as_Defined(bool val) { Val = val; Def = true; } }; #endif tmp41wklro_/CPP/Common/MyUnknown.h0000444000175000001440000000016414405360000020122 0ustar nabijaczleweliusers// MyUnknown.h #ifndef ZIP7_INC_MY_UNKNOWN_H #define ZIP7_INC_MY_UNKNOWN_H #include "MyWindows.h" #endif tmp41wklro_/CPP/Common/MyVector.cpp0000444000175000001440000000005711664467247020312 0ustar nabijaczleweliusers// Common/MyVector.cpp #include "StdAfx.h" tmp41wklro_/CPP/Common/MyVector.h0000444000175000001440000004042714553445260017753 0ustar nabijaczleweliusers// Common/MyVector.h #ifndef ZIP7_INC_COMMON_MY_VECTOR_H #define ZIP7_INC_COMMON_MY_VECTOR_H #include #include "Common.h" const unsigned k_VectorSizeMax = ((unsigned)1 << 31) - 1; template class CRecordVector { T *_items; unsigned _size; unsigned _capacity; void MoveItems(unsigned destIndex, unsigned srcIndex) { memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T)); } void ReAllocForNewCapacity(const unsigned newCapacity) { T *p; Z7_ARRAY_NEW(p, T, newCapacity) // p = new T[newCapacity]; if (_size != 0) memcpy(p, _items, (size_t)_size * sizeof(T)); delete []_items; _items = p; _capacity = newCapacity; } public: void ReserveOnePosition() { if (_size != _capacity) return; if (_capacity >= k_VectorSizeMax) throw 2021; const unsigned rem = k_VectorSizeMax - _capacity; unsigned add = (_capacity >> 2) + 1; if (add > rem) add = rem; ReAllocForNewCapacity(_capacity + add); } CRecordVector(): _items(NULL), _size(0), _capacity(0) {} CRecordVector(const CRecordVector &v): _items(NULL), _size(0), _capacity(0) { const unsigned size = v.Size(); if (size != 0) { // Z7_ARRAY_NEW(_items, T, size) _items = new T[size]; _size = size; _capacity = size; memcpy(_items, v._items, (size_t)size * sizeof(T)); } } unsigned Size() const { return _size; } bool IsEmpty() const { return _size == 0; } void ConstructReserve(unsigned size) { if (size != 0) { Z7_ARRAY_NEW(_items, T, size) // _items = new T[size]; _capacity = size; } } void Reserve(unsigned newCapacity) { if (newCapacity > _capacity) { if (newCapacity > k_VectorSizeMax) throw 2021; ReAllocForNewCapacity(newCapacity); } } void ChangeSize_KeepData(unsigned newSize) { Reserve(newSize); _size = newSize; } void ClearAndReserve(unsigned newCapacity) { Clear(); if (newCapacity > _capacity) { if (newCapacity > k_VectorSizeMax) throw 2021; delete []_items; _items = NULL; _capacity = 0; Z7_ARRAY_NEW(_items, T, newCapacity) // _items = new T[newCapacity]; _capacity = newCapacity; } } void ClearAndSetSize(unsigned newSize) { ClearAndReserve(newSize); _size = newSize; } void ReserveDown() { if (_size == _capacity) return; T *p = NULL; if (_size != 0) { // Z7_ARRAY_NEW(p, T, _size) p = new T[_size]; memcpy(p, _items, (size_t)_size * sizeof(T)); } delete []_items; _items = p; _capacity = _size; } ~CRecordVector() { delete []_items; } void ClearAndFree() { delete []_items; _items = NULL; _size = 0; _capacity = 0; } void Clear() { _size = 0; } void DeleteBack() { _size--; } void DeleteFrom(unsigned index) { // if (index <= _size) _size = index; } void DeleteFrontal(unsigned num) { if (num != 0) { MoveItems(0, num); _size -= num; } } void Delete(unsigned index) { MoveItems(index, index + 1); _size -= 1; } /* void Delete(unsigned index, unsigned num) { if (num > 0) { MoveItems(index, index + num); _size -= num; } } */ CRecordVector& operator=(const CRecordVector &v) { if (&v == this) return *this; const unsigned size = v.Size(); if (size > _capacity) { delete []_items; _capacity = 0; _size = 0; _items = NULL; _items = new T[size]; _capacity = size; } _size = size; if (size != 0) memcpy(_items, v._items, (size_t)size * sizeof(T)); return *this; } CRecordVector& operator+=(const CRecordVector &v) { const unsigned size = v.Size(); if (size != 0) { if (_size >= k_VectorSizeMax || size > k_VectorSizeMax - _size) throw 2021; const unsigned newSize = _size + size; Reserve(newSize); memcpy(_items + _size, v._items, (size_t)size * sizeof(T)); _size = newSize; } return *this; } unsigned Add(const T item) { ReserveOnePosition(); const unsigned size = _size; _size = size + 1; _items[size] = item; return size; } /* unsigned Add2(const T &item) { ReserveOnePosition(); const unsigned size = _size; _size = size + 1; _items[size] = item; return size; } */ unsigned AddInReserved(const T item) { const unsigned size = _size; _size = size + 1; _items[size] = item; return size; } void Insert(unsigned index, const T item) { ReserveOnePosition(); MoveItems(index + 1, index); _items[index] = item; _size++; } void InsertInReserved(unsigned index, const T item) { MoveItems(index + 1, index); _items[index] = item; _size++; } void MoveToFront(unsigned index) { if (index != 0) { const T temp = _items[index]; memmove(_items + 1, _items, (size_t)index * sizeof(T)); _items[0] = temp; } } const T& operator[](unsigned index) const { return _items[index]; } T& operator[](unsigned index) { return _items[index]; } const T& operator[](int index) const { return _items[(unsigned)index]; } T& operator[](int index) { return _items[(unsigned)index]; } const T* ConstData() const { return _items; } T* NonConstData() const { return _items; } T* NonConstData() { return _items; } const T* Data() const { return _items; } T* Data() { return _items; } const T& FrontItem() const { return _items[0]; } T& FrontItem() { return _items[0]; } /* const T Front() const { return _items[0]; } T Front() { return _items[0]; } const T& Front() const { return _items[0]; } T& Front() { return _items[0]; } */ const T& Back() const { return _items[(size_t)_size - 1]; } T& Back() { return _items[(size_t)_size - 1]; } /* void Swap(unsigned i, unsigned j) { const T temp = _items[i]; _items[i] = _items[j]; _items[j] = temp; } */ int FindInSorted(const T item, unsigned left, unsigned right) const { while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T midVal = (*this)[mid]; if (item == midVal) return (int)mid; if (item < midVal) right = mid; else left = mid + 1; } return -1; } int FindInSorted2(const T &item, unsigned left, unsigned right) const { while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T& midVal = (*this)[mid]; const int comp = item.Compare(midVal); if (comp == 0) return (int)mid; if (comp < 0) right = mid; else left = mid + 1; } return -1; } int FindInSorted(const T item) const { return FindInSorted(item, 0, _size); } int FindInSorted2(const T &item) const { return FindInSorted2(item, 0, _size); } unsigned AddToUniqueSorted(const T item) { unsigned left = 0, right = _size; while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T midVal = (*this)[mid]; if (item == midVal) return mid; if (item < midVal) right = mid; else left = mid + 1; } Insert(right, item); return right; } unsigned AddToUniqueSorted2(const T &item) { unsigned left = 0, right = _size; while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T& midVal = (*this)[mid]; const int comp = item.Compare(midVal); if (comp == 0) return mid; if (comp < 0) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) { const T temp = p[k]; for (;;) { unsigned s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { unsigned size = _size; if (size <= 1) return; T* p = _items - 1; { unsigned i = size >> 1; do SortRefDown(p, i, size, compare, param); while (--i); } do { const T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } static void SortRefDown2(T* p, unsigned k, unsigned size) { const T temp = p[k]; for (;;) { unsigned s = (k << 1); if (s > size) break; if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0) s++; if (temp.Compare(p[s]) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort2() { unsigned size = _size; if (size <= 1) return; T* p = _items - 1; { unsigned i = size >> 1; do SortRefDown2(p, i, size); while (--i); } do { const T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown2(p, 1, size); } while (size > 1); } }; typedef CRecordVector CIntVector; typedef CRecordVector CUIntVector; typedef CRecordVector CBoolVector; typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template class CObjectVector { CPointerVector _v; public: unsigned Size() const { return _v.Size(); } bool IsEmpty() const { return _v.IsEmpty(); } void ReserveDown() { _v.ReserveDown(); } // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } CObjectVector() {} CObjectVector(const CObjectVector &v) { const unsigned size = v.Size(); _v.ConstructReserve(size); for (unsigned i = 0; i < size; i++) AddInReserved(v[i]); } CObjectVector& operator=(const CObjectVector &v) { if (&v == this) return *this; Clear(); const unsigned size = v.Size(); _v.Reserve(size); for (unsigned i = 0; i < size; i++) AddInReserved(v[i]); return *this; } CObjectVector& operator+=(const CObjectVector &v) { const unsigned addSize = v.Size(); if (addSize != 0) { const unsigned size = Size(); if (size >= k_VectorSizeMax || addSize > k_VectorSizeMax - size) throw 2021; _v.Reserve(size + addSize); for (unsigned i = 0; i < addSize; i++) AddInReserved(v[i]); } return *this; } const T& operator[](unsigned index) const { return *((T *)_v[index]); } T& operator[](unsigned index) { return *((T *)_v[index]); } const T& operator[](int index) const { return *((T *)_v[(unsigned)index]); } T& operator[](int index) { return *((T *)_v[(unsigned)index]); } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return *(T *)_v.Back(); } T& Back() { return *(T *)_v.Back(); } void MoveToFront(unsigned index) { _v.MoveToFront(index); } unsigned Add(const T& item) { _v.ReserveOnePosition(); return AddInReserved(item); } unsigned AddInReserved(const T& item) { return _v.AddInReserved(new T(item)); } void ReserveOnePosition() { _v.ReserveOnePosition(); } unsigned AddInReserved_Ptr_of_new(T *ptr) { return _v.AddInReserved(ptr); } #define VECTOR_ADD_NEW_OBJECT(v, a) \ (v).ReserveOnePosition(); \ (v).AddInReserved_Ptr_of_new(new a); T& AddNew() { _v.ReserveOnePosition(); T *p = new T; _v.AddInReserved(p); return *p; } T& AddNewInReserved() { T *p = new T; _v.AddInReserved(p); return *p; } void Insert(unsigned index, const T& item) { _v.ReserveOnePosition(); _v.InsertInReserved(index, new T(item)); } T& InsertNew(unsigned index) { _v.ReserveOnePosition(); T *p = new T; _v.InsertInReserved(index, p); return *p; } ~CObjectVector() { for (unsigned i = _v.Size(); i != 0;) delete (T *)_v[--i]; } void ClearAndFree() { Clear(); _v.ClearAndFree(); } void Clear() { for (unsigned i = _v.Size(); i != 0;) delete (T *)_v[--i]; _v.Clear(); } void DeleteFrom(unsigned index) { const unsigned size = _v.Size(); for (unsigned i = index; i < size; i++) delete (T *)_v[i]; _v.DeleteFrom(index); } void DeleteFrontal(unsigned num) { for (unsigned i = 0; i < num; i++) delete (T *)_v[i]; _v.DeleteFrontal(num); } void DeleteBack() { delete (T *)_v.Back(); _v.DeleteBack(); } void Delete(unsigned index) { delete (T *)_v[index]; _v.Delete(index); } // void Delete(int index) { Delete((unsigned)index); } /* void Delete(unsigned index, unsigned num) { for (unsigned i = 0; i < num; i++) delete (T *)_v[index + i]; _v.Delete(index, num); } */ /* int Find(const T& item) const { unsigned size = Size(); for (unsigned i = 0; i < size; i++) if (item == (*this)[i]) return i; return -1; } */ int FindInSorted(const T& item) const { unsigned left = 0, right = Size(); while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T& midVal = (*this)[mid]; const int comp = item.Compare(midVal); if (comp == 0) return (int)mid; if (comp < 0) right = mid; else left = mid + 1; } return -1; } unsigned AddToUniqueSorted(const T& item) { unsigned left = 0, right = Size(); while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T& midVal = (*this)[mid]; const int comp = item.Compare(midVal); if (comp == 0) return mid; if (comp < 0) right = mid; else left = mid + 1; } Insert(right, item); return right; } /* unsigned AddToSorted(const T& item) { unsigned left = 0, right = Size(); while (left != right) { // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); const unsigned mid = (left + right) / 2; const T& midVal = (*this)[mid]; const int comp = item.Compare(midVal); if (comp == 0) { right = mid + 1; break; } if (comp < 0) right = mid; else left = mid + 1; } Insert(right, item); return right; } */ void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { _v.Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); } void Sort() { _v.Sort(CompareObjectItems, NULL); } }; #define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) #endif tmp41wklro_/CPP/Common/MyWindows.cpp0000444000175000001440000001700614563333160020467 0ustar nabijaczleweliusers// MyWindows.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #ifdef __GNUC__ #include #endif #include "MyWindows.h" static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } static inline void FreeForBSTR(void *pv) { ::free(pv);} /* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string. We must select CBstrSizeType for another systems (not Win32): if (CBstrSizeType is UINT32), then we support only strings smaller than 4 GB. Win32 version always has that limitation. if (CBstrSizeType is UINT), (UINT can be 16/32/64-bit) We can support strings larger than 4 GB (if UINT is 64-bit), but sizeof(UINT) can be different in parts compiled by different compilers/settings, and we can't send such BSTR strings between such parts. */ typedef UINT32 CBstrSizeType; // typedef UINT CBstrSizeType; #define k_BstrSize_Max 0xFFFFFFFF // #define k_BstrSize_Max UINT_MAX // #define k_BstrSize_Max ((UINT)(INT)-1) BSTR SysAllocStringByteLen(LPCSTR s, UINT len) { /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end. We provide also aligned null OLECHAR at the end. */ if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType))) return NULL; UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1); void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType)); if (!p) return NULL; *(CBstrSizeType *)p = (CBstrSizeType)len; BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); if (s) memcpy(bstr, s, len); for (; len < size; len++) ((Byte *)bstr)[len] = 0; return bstr; } BSTR SysAllocStringLen(const OLECHAR *s, UINT len) { if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR)) return NULL; UINT size = len * (UINT)sizeof(OLECHAR); void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR)); if (!p) return NULL; *(CBstrSizeType *)p = (CBstrSizeType)size; BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); if (s) memcpy(bstr, s, size); bstr[len] = 0; return bstr; } BSTR SysAllocString(const OLECHAR *s) { if (!s) return NULL; const OLECHAR *s2 = s; while (*s2 != 0) s2++; return SysAllocStringLen(s, (UINT)(s2 - s)); } void SysFreeString(BSTR bstr) { if (bstr) FreeForBSTR((CBstrSizeType *)(void *)bstr - 1); } UINT SysStringByteLen(BSTR bstr) { if (!bstr) return 0; return *((CBstrSizeType *)(void *)bstr - 1); } UINT SysStringLen(BSTR bstr) { if (!bstr) return 0; return *((CBstrSizeType *)(void *)bstr - 1) / (UINT)sizeof(OLECHAR); } HRESULT VariantClear(VARIANTARG *prop) { if (prop->vt == VT_BSTR) SysFreeString(prop->bstrVal); prop->vt = VT_EMPTY; return S_OK; } HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src) { HRESULT res = ::VariantClear(dest); if (res != S_OK) return res; if (src->vt == VT_BSTR) { dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal, SysStringByteLen(src->bstrVal)); if (!dest->bstrVal) return E_OUTOFMEMORY; dest->vt = VT_BSTR; } else *dest = *src; return S_OK; } LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) { if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1; if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1; if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1; if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1; return 0; } DWORD GetLastError() { return (DWORD)errno; } void SetLastError(DWORD dw) { errno = (int)dw; } static LONG TIME_GetBias() { time_t utc = time(NULL); struct tm *ptm = localtime(&utc); int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ ptm = gmtime(&utc); ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ LONG bias = (int)(mktime(ptm)-utc); return bias; } #define TICKS_PER_SEC 10000000 /* #define SECS_PER_DAY (24 * 60 * 60) #define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY) #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC) */ #define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32)) #define SET_FILETIME(ft, v64) \ (ft)->dwLowDateTime = (DWORD)v64; \ (ft)->dwHighDateTime = (DWORD)(v64 >> 32); BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime) { UInt64 v = GET_TIME_64(fileTime); v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC); SET_FILETIME(localFileTime, v) return TRUE; } BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime) { UInt64 v = GET_TIME_64(localFileTime); v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC); SET_FILETIME(fileTime, v) return TRUE; } /* VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft) { UInt64 t = 0; timeval tv; if (gettimeofday(&tv, NULL) == 0) { t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970; t += tv.tv_usec * 10; } SET_FILETIME(ft, t) } */ DWORD WINAPI GetTickCount(VOID) { #ifndef _WIN32 // gettimeofday() doesn't work in some MINGWs by unknown reason timeval tv; if (gettimeofday(&tv, NULL) == 0) { // tv_sec and tv_usec are (long) return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000); } #endif return (DWORD)time(NULL) * 1000; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st) { UInt32 v; UInt64 v64 = GET_TIME_64(ft); v64 /= 10000; st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000; st->wSecond = (WORD)(v64 % 60); v64 /= 60; st->wMinute = (WORD)(v64 % 60); v64 /= 60; v = (UInt32)v64; st->wHour = (WORD)(v % 24); v /= 24; // 1601-01-01 was Monday st->wDayOfWeek = (WORD)((v + 1) % 7); UInt32 leaps, year, day, mon; leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4; v += 28188 + leaps; // leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01 // (1959 / 64) - converts day from 03-01 to month year = (20 * v - 2442) / (5 * PERIOD_4); day = v - (year * PERIOD_4) / 4; mon = (64 * day) / 1959; st->wDay = (WORD)(day - (1959 * mon) / 64); mon -= 1; year += 1524; if (mon > 12) { mon -= 12; year++; } st->wMonth = (WORD)mon; st->wYear = (WORD)year; /* unsigned year, mon; unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned t; year = (WORD)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; st->wYear = (WORD)year; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 0;; mon++) { unsigned d = ms[mon]; if (v < d) break; v -= d; } st->wDay = (WORD)(v + 1); st->wMonth = (WORD)(mon + 1); */ return TRUE; } #endif tmp41wklro_/CPP/Common/MyWindows.h0000444000175000001440000001704014500563660020133 0ustar nabijaczleweliusers// MyWindows.h #ifdef Z7_DEFINE_GUID #undef Z7_DEFINE_GUID #endif #ifdef INITGUID #define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name; \ EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name #endif #ifndef ZIP7_INC_MY_WINDOWS_H #define ZIP7_INC_MY_WINDOWS_H #ifdef _WIN32 #include "../../C/7zWindows.h" #else // _WIN32 #include // for wchar_t #include // #include // for uintptr_t #include "../../C/7zTypes.h" #include "MyGuidDef.h" // WINAPI is __stdcall in Windows-MSVC in windef.h #define WINAPI typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff)) #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) // MS uses long for BOOL, but long is 32-bit in MS. So we use int. // typedef long BOOL; typedef int BOOL; #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif // typedef size_t ULONG_PTR; // typedef size_t DWORD_PTR; // typedef uintptr_t UINT_PTR; // typedef ptrdiff_t UINT_PTR; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct { LONGLONG QuadPart; } LARGE_INTEGER; typedef struct { ULONGLONG QuadPart; } ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME; #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) #define FAILED(hr) ((HRESULT)(hr) < 0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #define STDAPICALLTYPE __stdcall #else // do we need __export here? #define STDMETHODCALLTYPE #define STDAPICALLTYPE #endif #define STDAPI EXTERN_C HRESULT STDAPICALLTYPE #ifndef DECLSPEC_NOTHROW #define DECLSPEC_NOTHROW Z7_DECLSPEC_NOTHROW #endif #ifndef DECLSPEC_NOVTABLE #define DECLSPEC_NOVTABLE Z7_DECLSPEC_NOVTABLE #endif #ifndef COM_DECLSPEC_NOTHROW #ifdef COM_STDMETHOD_CAN_THROW #define COM_DECLSPEC_NOTHROW #else #define COM_DECLSPEC_NOTHROW DECLSPEC_NOTHROW #endif #endif #define DECLARE_INTERFACE(iface) struct DECLSPEC_NOVTABLE iface #define DECLARE_INTERFACE_(iface, baseiface) struct DECLSPEC_NOVTABLE iface : public baseiface #define STDMETHOD_(t, f) virtual COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(t) COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 // #define MIDL_INTERFACE(x) struct #ifdef __cplusplus /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown, if _WIN32 is not defined. It used virtual destructor, because some compilers don't like virtual interfaces without virtual destructor. IUnknown in Windows (_WIN32) doesn't use virtual destructor in IUnknown. We still can define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here, if we want to be compatible with old plugin interface of p7zip and 7-Zip before v23. v23: In new 7-Zip v23 we try to be more compatible with original IUnknown from _WIN32. So we do not define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here, */ // #define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN #ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN #if defined(__clang__) #pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override" #endif #endif Z7_PURE_INTERFACES_BEGIN DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) =0; STDMETHOD_(ULONG, AddRef)() =0; STDMETHOD_(ULONG, Release)() =0; #ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; Z7_PURE_INTERFACES_END #endif // __cplusplus #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; EXTERN_C HRESULT VariantClear(VARIANTARG *prop); EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src); typedef struct tagSTATPROPSTG { LPOLESTR lpwstrName; PROPID propid; VARTYPE vt; } STATPROPSTG; EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len); EXTERN_C BSTR SysAllocString(const OLECHAR *sz); EXTERN_C void SysFreeString(BSTR bstr); EXTERN_C UINT SysStringByteLen(BSTR bstr); EXTERN_C UINT SysStringLen(BSTR bstr); EXTERN_C DWORD GetLastError(); EXTERN_C void SetLastError(DWORD dwCode); EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); EXTERN_C DWORD GetCurrentThreadId(); EXTERN_C DWORD GetCurrentProcessId(); #define MAX_PATH 1024 #define CP_ACP 0 #define CP_OEMCP 1 #define CP_UTF8 65001 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; typedef struct { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME; BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime); BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime); BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime); // VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime); DWORD GetTickCount(); /* #define CREATE_NEW 1 #define CREATE_ALWAYS 2 #define OPEN_EXISTING 3 #define OPEN_ALWAYS 4 #define TRUNCATE_EXISTING 5 */ #endif // _WIN32 #endif tmp41wklro_/CPP/Common/NewHandler.cpp0000444000175000001440000001413414601337060020551 0ustar nabijaczleweliusers// NewHandler.cpp #include "StdAfx.h" #include #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef Z7_REDEFINE_OPERATOR_NEW /* void * my_new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); if (size == 0) size = 1; void *p = ::malloc(size); if (!p) throw CNewException(); return p; } void my_delete(void *p) throw() { // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p); ::free(p); } void * my_Realloc(void *p, size_t newSize, size_t oldSize) { void *newBuf = my_new(newSize); if (oldSize != 0) memcpy(newBuf, p, oldSize); my_delete(p); return newBuf; } */ void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { /* by C++ specification: if (size == 0), operator new(size) returns non_NULL pointer. If (operator new(0) returns NULL), it's out of specification. but some calling code can work correctly even in this case too. */ // if (size == 0) return NULL; // for debug only. don't use it /* malloc(0) returns non_NULL in main compilers, as we need here. But specification also allows malloc(0) to return NULL. So we change (size=0) to (size=1) here to get real non_NULL pointer */ if (size == 0) size = 1; // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); // void *p = ::MyAlloc(size); // note: MyAlloc(0) returns NULL void *p = ::malloc(size); if (!p) throw CNewException(); return p; } #if defined(_MSC_VER) && _MSC_VER == 1600 // vs2010 has no throw() by default ? #pragma warning(push) #pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration #endif void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p); // MyFree(p); ::free(p); } /* we define operator delete(void *p, size_t n) because vs2022 compiler uses delete(void *p, size_t n), and we want to mix files from different compilers: - old vc6 linker - old vc6 complier - new vs2022 complier */ void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t n) throw() { UNUSED_VAR(n) ::free(p); } #if defined(_MSC_VER) && _MSC_VER == 1600 #pragma warning(pop) #endif /* void * #ifdef _MSC_VER __cdecl #endif operator new[](size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); if (size == 0) size = 1; void *p = ::malloc(size); if (!p) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete[](void *p) throw() { // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p); ::free(p); } */ #endif #else #include // #pragma init_seg(lib) /* const int kDebugSize = 1000000; static void *a[kDebugSize]; static int g_index = 0; class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { printf("\nDestructor: %d\n", numAllocs); for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; */ #ifdef _WIN32 static bool wasInit = false; static CRITICAL_SECTION cs; #endif static int numAllocs = 0; void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { #ifdef _WIN32 if (!wasInit) { InitializeCriticalSection(&cs); wasInit = true; } EnterCriticalSection(&cs); numAllocs++; int loc = numAllocs; void *p = HeapAlloc(GetProcessHeap(), 0, size); /* if (g_index < kDebugSize) { a[g_index] = p; g_index++; } */ printf("Alloc %6d, size = %8u\n", loc, (unsigned)size); LeaveCriticalSection(&cs); if (!p) throw CNewException(); return p; #else numAllocs++; int loc = numAllocs; if (size == 0) size = 1; void *p = malloc(size); /* if (g_index < kDebugSize) { a[g_index] = p; g_index++; } */ printf("Alloc %6d, size = %8u\n", loc, (unsigned)size); if (!p) throw CNewException(); return p; #endif } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { if (!p) return; #ifdef _WIN32 EnterCriticalSection(&cs); /* for (int i = 0; i < g_index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); // if (numAllocs == 0) numAllocs = numAllocs; // ERROR numAllocs--; // if (numAllocs == 0) numAllocs = numAllocs; // OK: all objects were deleted printf("Free %d\n", numAllocs); LeaveCriticalSection(&cs); #else free(p); numAllocs--; printf("Free %d\n", numAllocs); #endif } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t n) throw(); void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t n) throw() { UNUSED_VAR(n) printf("delete_WITH_SIZE=%u, ptr = %p\n", (unsigned)n, p); operator delete(p); } /* void * #ifdef _MSC_VER __cdecl #endif operator new[](size_t size) { printf("operator_new[] : "); return operator new(size); } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t sz) throw(); void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t sz) throw() { if (!p) return; printf("operator_delete_size : size=%d : ", (unsigned)sz); operator delete(p); } void #ifdef _MSC_VER __cdecl #endif operator delete[](void *p) throw() { if (!p) return; printf("operator_delete[] : "); operator delete(p); } void #ifdef _MSC_VER __cdecl #endif operator delete[](void *p, size_t sz) throw(); void #ifdef _MSC_VER __cdecl #endif operator delete[](void *p, size_t sz) throw() { if (!p) return; printf("operator_delete_size[] : size=%d : ", (unsigned)sz); operator delete(p); } */ #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ tmp41wklro_/CPP/Common/NewHandler.h0000444000175000001440000000637614553445260020237 0ustar nabijaczleweliusers// Common/NewHandler.h #ifndef ZIP7_INC_COMMON_NEW_HANDLER_H #define ZIP7_INC_COMMON_NEW_HANDLER_H /* NewHandler.h and NewHandler.cpp allows to solve problem with compilers that don't throw exception in operator new(). This file must be included before any code that uses operators new() or delete() and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler. DOCs: Since ISO C++98, operator new throws std::bad_alloc when memory allocation fails. MSVC 6.0 returned a null pointer on an allocation failure. Beginning in VS2002, operator new conforms to the standard and throws on failure. By default, the compiler also generates defensive null checks to prevent these older-style allocators from causing an immediate crash on failure. The /Zc:throwingNew option tells the compiler to leave out these null checks, on the assumption that all linked memory allocators conform to the standard. The operator new() in some MSVC versions doesn't throw exception std::bad_alloc. MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception. The code produced by some another MSVC compilers also can be linked to library that doesn't throw exception. We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc. For older _MSC_VER versions we redefine operator new() and operator delete(). Our version of operator new() throws CNewException() exception on failure. It's still allowed to use redefined version of operator new() from "NewHandler.cpp" with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions. But if you use some additional code (outside of 7-Zip's code), you must check that redefined version of operator new() is not problem for your code. */ #include #ifdef _WIN32 // We can compile my_new and my_delete with _fastcall /* void * my_new(size_t size); void my_delete(void *p) throw(); // void * my_Realloc(void *p, size_t newSize, size_t oldSize); */ #endif #if defined(_MSC_VER) && (_MSC_VER < 1600) // If you want to use default operator new(), you can disable the following line #define Z7_REDEFINE_OPERATOR_NEW #endif #ifdef Z7_REDEFINE_OPERATOR_NEW // std::bad_alloc can require additional DLL dependency. // So we don't define CNewException as std::bad_alloc here. class CNewException {}; void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size); /* #if 0 && defined(_MSC_VER) && _MSC_VER == 1600 #define Z7_OPERATOR_DELETE_SPEC_THROW0 #else #define Z7_OPERATOR_DELETE_SPEC_THROW0 throw() #endif */ #if defined(_MSC_VER) && _MSC_VER == 1600 #pragma warning(push) #pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration #endif void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); void #ifdef _MSC_VER __cdecl #endif operator delete(void *p, size_t n) throw(); #if defined(_MSC_VER) && _MSC_VER == 1600 #pragma warning(pop) #endif #else #include #define CNewException std::bad_alloc #endif /* #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new[](size_t size); void #ifdef _MSC_VER __cdecl #endif operator delete[](void *p) throw(); #endif */ #endif tmp41wklro_/CPP/Common/Sha256Prepare.cpp0000444000175000001440000000024714002751723021012 0ustar nabijaczleweliusers// Sha256Prepare.cpp #include "StdAfx.h" #include "../../C/Sha256.h" static struct CSha256Prepare { CSha256Prepare() { Sha256Prepare(); } } g_Sha256Prepare; tmp41wklro_/CPP/Common/Sha256Reg.cpp0000444000175000001440000000266114404672500020134 0ustar nabijaczleweliusers// Sha256Reg.cpp #include "StdAfx.h" #include "../../C/Sha256.h" #include "../Common/MyBuffer2.h" #include "../Common/MyCom.h" #include "../7zip/Common/RegisterCodec.h" Z7_CLASS_IMP_COM_2( CSha256Hasher , IHasher , ICompressSetCoderProperties ) CAlignedBuffer1 _buf; public: Byte _mtDummy[1 << 7]; CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_buf; } public: CSha256Hasher(): _buf(sizeof(CSha256)) { Sha256_SetFunction(Sha(), 0); Sha256_InitState(Sha()); } }; Z7_COM7F_IMF2(void, CSha256Hasher::Init()) { Sha256_InitState(Sha()); } Z7_COM7F_IMF2(void, CSha256Hasher::Update(const void *data, UInt32 size)) { Sha256_Update(Sha(), (const Byte *)data, size); } Z7_COM7F_IMF2(void, CSha256Hasher::Final(Byte *digest)) { Sha256_Final(Sha(), digest); } Z7_COM7F_IMF(CSha256Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) { unsigned algo = 0; for (UInt32 i = 0; i < numProps; i++) { if (propIDs[i] == NCoderPropID::kDefaultProp) { const PROPVARIANT &prop = coderProps[i]; if (prop.vt != VT_UI4) return E_INVALIDARG; if (prop.ulVal > 2) return E_NOTIMPL; algo = (unsigned)prop.ulVal; } } if (!Sha256_SetFunction(Sha(), algo)) return E_NOTIMPL; return S_OK; } REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE) tmp41wklro_/CPP/Common/StdAfx.h0000444000175000001440000000014614360505460017361 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #include "Common.h" #endif tmp41wklro_/CPP/Common/StdInStream.cpp0000444000175000001440000000361314535603720020724 0ustar nabijaczleweliusers// Common/StdInStream.cpp #include "StdAfx.h" #ifdef _WIN32 #include #endif #include "StdInStream.h" #include "StringConvert.h" #include "UTFConvert.h" // #define kEOFMessage "Unexpected end of input stream" // #define kReadErrorMessage "Error reading input stream" // #define kIllegalCharMessage "Illegal zero character in input stream" CStdInStream g_StdIn(stdin); /* #define kFileOpenMode TEXT("r") bool CStdInStream::Open(LPCTSTR fileName) throw() { Close(); _stream = #ifdef _WIN32 _tfopen #else fopen #endif (fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() throw() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } */ bool CStdInStream::ScanAStringUntilNewLine(AString &s) { s.Empty(); for (;;) { const int intChar = GetChar(); if (intChar == EOF) return true; const char c = (char)intChar; if (c == 0) return false; if (c == '\n') return true; s.Add_Char(c); } } bool CStdInStream::ScanUStringUntilNewLine(UString &dest) { dest.Empty(); AString s; const bool res = ScanAStringUntilNewLine(s); int codePage = CodePage; if (codePage == -1) codePage = CP_OEMCP; if ((unsigned)codePage == CP_UTF8) ConvertUTF8ToUnicode(s, dest); else MultiByteToUnicodeString2(dest, s, (UINT)(unsigned)codePage); return res; } /* bool CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); for (;;) { int intChar = GetChar(); if (intChar == EOF) return !Error(); char c = (char)intChar; if (c == 0) return false; resultString += c; } } */ int CStdInStream::GetChar() { return fgetc(_stream); // getc() doesn't work in BeOS? } tmp41wklro_/CPP/Common/StdInStream.h0000444000175000001440000000164514357314620020374 0ustar nabijaczleweliusers// Common/StdInStream.h #ifndef ZIP7_INC_COMMON_STD_IN_STREAM_H #define ZIP7_INC_COMMON_STD_IN_STREAM_H #include #include "MyString.h" #include "MyTypes.h" class CStdInStream { FILE *_stream; // bool _streamIsOpen; public: int CodePage; CStdInStream(FILE *stream = NULL): _stream(stream), // _streamIsOpen(false), CodePage(-1) {} /* ~CStdInStream() { Close(); } bool Open(LPCTSTR fileName) throw(); bool Close() throw(); */ // returns: // false, if ZERO character in stream // true, if EOF or '\n' bool ScanAStringUntilNewLine(AString &s); bool ScanUStringUntilNewLine(UString &s); // bool ReadToString(AString &resultString); bool Eof() const throw() { return (feof(_stream) != 0); } bool Error() const throw() { return (ferror(_stream) != 0); } int GetChar(); }; extern CStdInStream g_StdIn; #endif tmp41wklro_/CPP/Common/StdOutStream.cpp0000444000175000001440000001217714561364620021134 0ustar nabijaczleweliusers// Common/StdOutStream.cpp #include "StdAfx.h" #ifdef _WIN32 #include #endif #include "IntToString.h" #include "StdOutStream.h" #include "StringConvert.h" #include "UTFConvert.h" CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); /* // #define kFileOpenMode "wt" bool CStdOutStream::Open(const char *fileName) throw() { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() throw() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } */ bool CStdOutStream::Flush() throw() { return (fflush(_stream) == 0); } CStdOutStream & endl(CStdOutStream & outStream) throw() { return outStream << '\n'; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) { AString temp; UString s2(s); PrintUString(s2, temp); return *this; } void CStdOutStream::PrintUString(const UString &s, AString &temp) { Convert_UString_to_AString(s, temp); *this << (const char *)temp; } void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest) { int codePage = CodePage; if (codePage == -1) codePage = CP_OEMCP; if ((unsigned)codePage == CP_UTF8) ConvertUnicodeToUTF8(src, dest); else UnicodeStringToMultiByte2(dest, src, (UINT)(unsigned)codePage); } static const wchar_t kReplaceChar = '_'; /* void CStdOutStream::Normalize_UString_LF_Allowed(UString &s) { if (!IsTerminalMode) return; const unsigned len = s.Len(); wchar_t *d = s.GetBuf(); for (unsigned i = 0; i < len; i++) { const wchar_t c = d[i]; if (c == 0x1b || (c <= 13 && c >= 7 && c != '\n')) d[i] = kReplaceChar; } } */ void CStdOutStream::Normalize_UString(UString &s) { const unsigned len = s.Len(); wchar_t *d = s.GetBuf(); if (IsTerminalMode) for (unsigned i = 0; i < len; i++) { const wchar_t c = d[i]; if ((c <= 13 && c >= 7) || c == 0x1b) d[i] = kReplaceChar; } else for (unsigned i = 0; i < len; i++) { const wchar_t c = d[i]; if (c == '\n') d[i] = kReplaceChar; } } void CStdOutStream::Normalize_UString_Path(UString &s) { if (ListPathSeparatorSlash.Def) { #ifdef _WIN32 if (ListPathSeparatorSlash.Val) s.Replace(L'\\', L'/'); #else if (!ListPathSeparatorSlash.Val) s.Replace(L'/', L'\\'); #endif } Normalize_UString(s); } /* void CStdOutStream::Normalize_UString(UString &src) { const wchar_t *s = src.Ptr(); const unsigned len = src.Len(); unsigned i; for (i = 0; i < len; i++) { const wchar_t c = s[i]; #if 0 && !defined(_WIN32) if (c == '\\') // IsTerminalMode && break; #endif if ((unsigned)c < 0x20) break; } if (i == len) return; UString temp; for (i = 0; i < len; i++) { wchar_t c = s[i]; #if 0 && !defined(_WIN32) if (c == '\\') temp += (wchar_t)L'\\'; else #endif if ((unsigned)c < 0x20) { if (c == '\n' || (IsTerminalMode && (c == 0x1b || (c <= 13 && c >= 7)))) { #if 1 || defined(_WIN32) c = (wchar_t)kReplaceChar; #else temp += (wchar_t)L'\\'; if (c == '\n') c = L'n'; else if (c == '\r') c = L'r'; else if (c == '\a') c = L'a'; else if (c == '\b') c = L'b'; else if (c == '\t') c = L't'; else if (c == '\v') c = L'v'; else if (c == '\f') c = L'f'; else { temp += (wchar_t)(L'0' + (unsigned)c / 64); temp += (wchar_t)(L'0' + (unsigned)c / 8 % 8); c = (wchar_t)(L'0' + (unsigned)c % 8); } #endif } } temp += c; } src = temp; } */ void CStdOutStream::NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA) { tempU = s; Normalize_UString_Path(tempU); PrintUString(tempU, tempA); } void CStdOutStream::NormalizePrint_UString_Path(const UString &s) { UString tempU; AString tempA; NormalizePrint_UString_Path(s, tempU, tempA); } void CStdOutStream::NormalizePrint_wstr_Path(const wchar_t *s) { UString tempU = s; Normalize_UString_Path(tempU); AString tempA; PrintUString(tempU, tempA); } void CStdOutStream::NormalizePrint_UString(const UString &s) { UString tempU = s; Normalize_UString(tempU); AString tempA; PrintUString(tempU, tempA); } CStdOutStream & CStdOutStream::operator<<(Int32 number) throw() { char s[32]; ConvertInt64ToString(number, s); return operator<<(s); } CStdOutStream & CStdOutStream::operator<<(Int64 number) throw() { char s[32]; ConvertInt64ToString(number, s); return operator<<(s); } CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw() { char s[16]; ConvertUInt32ToString(number, s); return operator<<(s); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw() { char s[32]; ConvertUInt64ToString(number, s); return operator<<(s); } tmp41wklro_/CPP/Common/StdOutStream.h0000444000175000001440000000413414561364620020573 0ustar nabijaczleweliusers// Common/StdOutStream.h #ifndef ZIP7_INC_COMMON_STD_OUT_STREAM_H #define ZIP7_INC_COMMON_STD_OUT_STREAM_H #include #include "MyString.h" #include "MyTypes.h" class CStdOutStream { FILE *_stream; // bool _streamIsOpen; public: bool IsTerminalMode; CBoolPair ListPathSeparatorSlash; int CodePage; CStdOutStream(FILE *stream = NULL): _stream(stream), // _streamIsOpen(false), IsTerminalMode(false), CodePage(-1) { ListPathSeparatorSlash.Val = #ifdef _WIN32 false; #else true; #endif } // ~CStdOutStream() { Close(); } // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; } // bool IsDefined() const { return _stream != NULL; } operator FILE *() { return _stream; } /* bool Open(const char *fileName) throw(); bool Close() throw(); */ bool Flush() throw(); CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &)) { (*func)(*this); return *this; } CStdOutStream & operator<<(const char *s) throw() { fputs(s, _stream); return *this; } CStdOutStream & operator<<(char c) throw() { fputc((unsigned char)c, _stream); return *this; } CStdOutStream & operator<<(Int32 number) throw(); CStdOutStream & operator<<(Int64 number) throw(); CStdOutStream & operator<<(UInt32 number) throw(); CStdOutStream & operator<<(UInt64 number) throw(); CStdOutStream & operator<<(const wchar_t *s); void PrintUString(const UString &s, AString &temp); void Convert_UString_to_AString(const UString &src, AString &dest); void Normalize_UString(UString &s); void Normalize_UString_Path(UString &s); void NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA); void NormalizePrint_UString_Path(const UString &s); void NormalizePrint_UString(const UString &s); void NormalizePrint_wstr_Path(const wchar_t *s); }; CStdOutStream & endl(CStdOutStream & outStream) throw(); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif tmp41wklro_/CPP/Common/StringConvert.cpp0000444000175000001440000004445614564623240021351 0ustar nabijaczleweliusers// Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 // #include #include #endif #if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) #include "UTFConvert.h" #endif #ifdef ENV_HAVE_LOCALE #include #endif static const char k_DefultChar = '_'; #ifdef _WIN32 /* MultiByteToWideChar(CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) if (cbMultiByte == 0) return: 0. ERR: ERROR_INVALID_PARAMETER if (cchWideChar == 0) return: the required buffer size in characters. if (supplied buffer size was not large enough) return: 0. ERR: ERROR_INSUFFICIENT_BUFFER The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex) If there are illegal characters: if MB_ERR_INVALID_CHARS is set in dwFlags: - the function stops conversion on illegal character. - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION. if MB_ERR_INVALID_CHARS is NOT set in dwFlags: before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0. in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal character is converted to U+FFFD, which is REPLACEMENT CHARACTER. */ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) { dest.Empty(); if (src.IsEmpty()) return; { /* wchar_t *d = dest.GetBuf(src.Len()); const char *s = (const char *)src; unsigned i; for (i = 0;;) { Byte c = (Byte)s[i]; if (c >= 0x80 || c == 0) break; d[i++] = (wchar_t)c; } if (i != src.Len()) { unsigned len = MultiByteToWideChar(codePage, 0, s + i, src.Len() - i, d + i, src.Len() + 1 - i); if (len == 0) throw 282228; i += len; } d[i] = 0; dest.ReleaseBuf_SetLen(i); */ unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0); if (len == 0) { if (GetLastError() != 0) throw 282228; } else { len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len); if (len == 0) throw 282228; dest.ReleaseBuf_SetEnd(len); } } } /* int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); if (lpDefaultChar == NULL), - it uses system default value. if (CodePage == CP_UTF7 || CodePage == CP_UTF8) if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL) return: 0. ERR: ERROR_INVALID_PARAMETER. The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL) */ static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { dest.Empty(); defaultCharWasUsed = false; if (src.IsEmpty()) return; { /* unsigned numRequiredBytes = src.Len() * 2; char *d = dest.GetBuf(numRequiredBytes); const wchar_t *s = (const wchar_t *)src; unsigned i; for (i = 0;;) { wchar_t c = s[i]; if (c >= 0x80 || c == 0) break; d[i++] = (char)c; } if (i != src.Len()) { BOOL defUsed = FALSE; defaultChar = defaultChar; bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i, d + i, numRequiredBytes + 1 - i, (isUtf ? NULL : &defaultChar), (isUtf ? NULL : &defUsed)); defaultCharWasUsed = (defUsed != FALSE); if (len == 0) throw 282229; i += len; } d[i] = 0; dest.ReleaseBuf_SetLen(i); */ /* if (codePage != CP_UTF7) { const wchar_t *s = (const wchar_t *)src; unsigned i; for (i = 0;; i++) { wchar_t c = s[i]; if (c >= 0x80 || c == 0) break; } if (s[i] == 0) { char *d = dest.GetBuf(src.Len()); for (i = 0;;) { wchar_t c = s[i]; if (c == 0) break; d[i++] = (char)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); return; } } */ unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL); if (len == 0) { if (GetLastError() != 0) throw 282228; } else { BOOL defUsed = FALSE; bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); // defaultChar = defaultChar; len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len, (isUtf ? NULL : &defaultChar), (isUtf ? NULL : &defUsed) ); if (!isUtf) defaultCharWasUsed = (defUsed != FALSE); if (len == 0) throw 282228; dest.ReleaseBuf_SetEnd(len); } } } /* #ifndef UNDER_CE AString SystemStringToOemString(const CSysString &src) { AString dest; const unsigned len = src.Len() * 2; CharToOem(src, dest.GetBuf(len)); dest.ReleaseBuf_CalcLen(len); return dest; } #endif */ #else // _WIN32 // #include /* if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff), and utf-8 string contains big unicode character > 0xffff), then we still use 16-bit surrogate pair in UString. It simplifies another code where utf-16 encoding is used. So we use surrogate-conversion code only in is file. */ /* mbstowcs() returns error if there is error in utf-8 stream, mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream */ /* static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src) { dest.Empty(); if (src.IsEmpty()) return; const size_t limit = ((size_t)src.Len() + 1) * 2; wchar_t *d = dest.GetBuf((unsigned)limit); const size_t len = mbstowcs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } dest.ReleaseBuf_SetEnd(0); } */ bool g_ForceToUTF8 = true; // false; void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) { dest.Empty(); if (src.IsEmpty()) return; if (codePage == CP_UTF8 || g_ForceToUTF8) { #if 1 ConvertUTF8ToUnicode(src, dest); return; #endif } const size_t limit = ((size_t)src.Len() + 1) * 2; wchar_t *d = dest.GetBuf((unsigned)limit); const size_t len = mbstowcs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); #if WCHAR_MAX > 0xffff d = dest.GetBuf(); for (size_t i = 0;; i++) { wchar_t c = d[i]; // printf("\ni=%2d c = %4x\n", (unsigned)i, (unsigned)c); if (c == 0) break; if (c >= 0x10000 && c < 0x110000) { UString tempString = d + i; const wchar_t *t = tempString.Ptr(); for (;;) { wchar_t w = *t++; // printf("\nchar=%x\n", w); if (w == 0) break; if (i == limit) break; // unexpected error if (w >= 0x10000 && w < 0x110000) { #if 1 if (i + 1 == limit) break; // unexpected error w -= 0x10000; d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff); w = 0xdc00 + (w & 0x3ff); #else // w = '_'; // for debug #endif } d[i++] = w; } dest.ReleaseBuf_SetEnd((unsigned)i); break; } } #endif /* printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr()); printf("char: "); for (unsigned i = 0; i < src.Len(); i++) printf (" %02x", (int)(Byte)src[i]); printf("\n"); printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr()); printf("wchar_t: "); for (unsigned i = 0; i < dest.Len(); i++) { printf (" %02x", (int)dest[i]); } printf("\n"); */ return; } /* if there is mbstowcs() error, we have two ways: 1) change 0x80+ characters to some character: '_' in that case we lose data, but we have correct UString() and that scheme can show errors to user in early stages, when file converted back to mbs() cannot be found 2) transfer bad characters in some UTF-16 range. it can be non-original Unicode character. but later we still can restore original character. */ // printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr()); { unsigned i; const char *s = (const char *)src; for (i = 0;;) { Byte c = (Byte)s[i]; if (c == 0) break; // we can use ascii compatibilty character '_' // if (c > 0x7F) c = '_'; // we replace "bad: character d[i++] = (wchar_t)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); } } static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src) { dest.Empty(); if (src.IsEmpty()) return; const size_t limit = ((size_t)src.Len() + 1) * 6; char *d = dest.GetBuf((unsigned)limit); const size_t len = wcstombs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } dest.ReleaseBuf_SetEnd(0); } static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { // if (codePage == 1234567) // for debug purposes if (codePage == CP_UTF8 || g_ForceToUTF8) { #if 1 defaultCharWasUsed = false; ConvertUnicodeToUTF8(src2, dest); return; #endif } UString src = src2; #if WCHAR_MAX > 0xffff { src.Empty(); for (unsigned i = 0; i < src2.Len();) { wchar_t c = src2[i++]; if (c >= 0xd800 && c < 0xdc00 && i != src2.Len()) { const wchar_t c2 = src2[i]; if (c2 >= 0xdc00 && c2 < 0xe000) { #if 1 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); // printf("%4x\n", (int)c); i++; #else // c = '_'; // for debug #endif } } src += c; } } #endif dest.Empty(); defaultCharWasUsed = false; if (src.IsEmpty()) return; const size_t len = wcstombs(NULL, src, 0); if (len != (size_t)-1) { const unsigned limit = ((unsigned)len); if (limit == len) { char *d = dest.GetBuf(limit); /* { printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr()); for (unsigned i = 0; i < src.Len(); i++) printf (" %02x", (int)src[i]); printf("\n"); printf("\ndest Limit = %d \n", limit); } */ const size_t len2 = wcstombs(d, src, len + 1); if (len2 != (size_t)-1 && len2 <= limit) { /* printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr()); for (unsigned i = 0; i < len2; i++) printf(" %02x", (int)(Byte)dest[i]); printf("\n"); */ dest.ReleaseBuf_SetEnd((unsigned)len2); return; } } } { const wchar_t *s = (const wchar_t *)src; char *d = dest.GetBuf(src.Len()); unsigned i; for (i = 0;;) { wchar_t c = s[i]; if (c == 0) break; if (c >= 0x100 // 0x80 ) { c = defaultChar; defaultCharWasUsed = true; } d[i++] = (char)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); /* printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len()); printf("ERROR: %s\n", dest.Ptr()); */ } } #endif // _WIN32 UString MultiByteToUnicodeString(const AString &src, UINT codePage) { UString dest; MultiByteToUnicodeString2(dest, src, codePage); return dest; } UString MultiByteToUnicodeString(const char *src, UINT codePage) { return MultiByteToUnicodeString(AString(src), codePage); } void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage) { bool defaultCharWasUsed; UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); } AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed); return dest; } AString UnicodeStringToMultiByte(const UString &src, UINT codePage) { AString dest; bool defaultCharWasUsed; UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); return dest; } #if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) #ifdef _WIN32 #define U_to_A(a, b, c) UnicodeStringToMultiByte2 // #define A_to_U(a, b, c) MultiByteToUnicodeString2 #else // void MultiByteToUnicodeString2_Native(UString &dest, const AString &src); #define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b) // #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b) #endif bool IsNativeUTF8() { UString u; AString a, a2; // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1) for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1) { u.Empty(); u += (wchar_t)c; /* if (Unicode_Is_There_Utf16SurrogateError(u)) continue; #ifndef _WIN32 if (Unicode_Is_There_BmpEscape(u)) continue; #endif */ ConvertUnicodeToUTF8(u, a); U_to_A(a2, u, CP_OEMCP); if (a != a2) return false; } return true; } #endif #ifdef ENV_HAVE_LOCALE const char *GetLocale(void) { #ifdef ENV_HAVE_LOCALE // printf("\n\nsetlocale(LC_CTYPE, NULL) : return : "); const char *s = setlocale(LC_CTYPE, NULL); if (!s) { // printf("[NULL]\n"); s = "C"; } else { // ubuntu returns "C" after program start // printf("\"%s\"\n", s); } return s; #elif defined(LOCALE_IS_UTF8) return "utf8"; #else return "C"; #endif } #ifdef _WIN32 static void Set_ForceToUTF8(bool) {} #else static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; } #endif static bool Is_Default_Basic_Locale(const char *locale) { const AString a (locale); if (a.IsEqualTo_Ascii_NoCase("") || a.IsEqualTo_Ascii_NoCase("C") || a.IsEqualTo_Ascii_NoCase("POSIX")) return true; return false; } static bool Is_Default_Basic_Locale() { return Is_Default_Basic_Locale(GetLocale()); } void MY_SetLocale() { #ifdef ENV_HAVE_LOCALE /* { const char *s = GetLocale(); printf("\nGetLocale() : returned : \"%s\"\n", s); } */ unsigned start = 0; // unsigned lim = 0; unsigned lim = 3; /* #define MY_SET_LOCALE_FLAGS__FROM_ENV 1 #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2 unsigned flags = MY_SET_LOCALE_FLAGS__FROM_ENV | MY_SET_LOCALE_FLAGS__TRY_UTF8 if (flags != 0) { if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV) lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1; else { start = 1; lim = 2; } } */ for (unsigned i = start; i < lim; i++) { /* man7: "If locale is an empty string, "", each part of the locale that should be modified is set according to the environment variables. for glibc: glibc, first from the user's environment variables: 1) the environment variable LC_ALL, 2) environment variable with the same name as the category (see the 3) the environment variable LANG The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems. for WIN32 : MSDN : Sets the locale to the default, which is the user-default ANSI code page obtained from the operating system. The locale name is set to the value returned by GetUserDefaultLocaleName. The code page is set to the value returned by GetACP */ const char *newLocale = ""; #ifdef __APPLE__ /* look also CFLocale there is no C.UTF-8 in macos macos has UTF-8 locale only with some language like en_US.UTF-8 what is best way to set UTF-8 locale in macos? */ if (i == 1) newLocale = "en_US.UTF-8"; /* file open with non-utf8 sequencies return #define EILSEQ 92 // "Illegal byte sequence" */ #else // newLocale = "C"; if (i == 1) { newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu // newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime // newLocale = "en_US.utf8"; // supported by ubuntu ? // newLocale = "en_US.UTF-8"; /* setlocale() in ubuntu allows locales with minor chracter changes in strings "en_US.UTF-8" / "en_US.utf8" */ } #endif // printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale); // const char *s = setlocale(LC_ALL, newLocale); /* if (!s) printf("NULL: can't set locale"); else printf("\"%s\"\n", s); */ // request curent locale of program const char *locale = GetLocale(); if (locale) { AString a (locale); a.MakeLower_Ascii(); // if (a.Find("utf") >= 0) { if (IsNativeUTF8()) { Set_ForceToUTF8(true); return; } } if (!Is_Default_Basic_Locale(locale)) { // if there is some non-default and non-utf locale, we want to use it break; // comment it for debug } } } if (IsNativeUTF8()) { Set_ForceToUTF8(true); return; } if (Is_Default_Basic_Locale()) { Set_ForceToUTF8(true); return; } Set_ForceToUTF8(false); #elif defined(LOCALE_IS_UTF8) // assume LC_CTYPE="utf8" #else // assume LC_CTYPE="C" #endif } #endif tmp41wklro_/CPP/Common/StringConvert.h0000444000175000001440000001037714357314620021010 0ustar nabijaczleweliusers// Common/StringConvert.h #ifndef ZIP7_INC_COMMON_STRING_CONVERT_H #define ZIP7_INC_COMMON_STRING_CONVERT_H #include "MyString.h" #include "MyWindows.h" UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP); UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP); // optimized versions that work faster for ASCII strings void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP); // void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage); AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; } inline const UString& GetUnicodeString(const UString &u) { return u; } inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); } inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); } inline UString GetUnicodeString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } inline UString GetUnicodeString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; } inline const UString& GetUnicodeString(const UString &u, UINT) { return u; } inline const char* GetAnsiString(const char *a) { return a; } inline const AString& GetAnsiString(const AString &a) { return a; } inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); } /* inline const char* GetOemString(const char* oem) { return oem; } inline const AString& GetOemString(const AString &oem) { return oem; } */ const char* GetOemString(const char* oem); const AString& GetOemString(const AString &oem); inline AString GetOemString(const UString &u) { return UnicodeStringToMultiByte(u, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t *u) { return u;} inline const UString& GetSystemString(const UString &u) { return u;} inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;} inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;} inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); } inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); } #else inline const char* GetSystemString(const char *a) { return a; } inline const AString& GetSystemString(const AString &a) { return a; } inline const char* GetSystemString(const char *a, UINT) { return a; } inline const AString& GetSystemString(const AString &a, UINT) { return a; } inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); } inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); } /* inline AString GetSystemString(const wchar_t *u) { UString s; s = u; return UnicodeStringToMultiByte(s); } */ #endif #ifndef UNDER_CE AString SystemStringToOemString(const CSysString &src); #endif #ifdef _WIN32 /* we don't need locale functions in Windows but we can define ENV_HAVE_LOCALE here for debug purposes */ // #define ENV_HAVE_LOCALE #else #define ENV_HAVE_LOCALE #endif #ifdef ENV_HAVE_LOCALE void MY_SetLocale(); const char *GetLocale(void); #endif #if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) bool IsNativeUTF8(); #endif #ifndef _WIN32 extern bool g_ForceToUTF8; #endif #endif tmp41wklro_/CPP/Common/StringToInt.cpp0000444000175000001440000001061614570556200020753 0ustar nabijaczleweliusers// Common/StringToInt.cpp #include "StdAfx.h" #include #if defined(_MSC_VER) && (_MSC_VER >= 1600) #include // for WCHAR_MAX in vs2022 #endif #include "StringToInt.h" static const UInt32 k_UInt32_max = 0xFFFFFFFF; static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); // static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(charTypeUnsigned)digit - '0') // #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)digit - '0') // #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(digit - '0')) #define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \ uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ if (end) *end = s; \ uintType res = 0; \ for (;; s++) { \ const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \ if (v > 9) { if (end) *end = s; return res; } \ if (res > (k_ ## uintType ## _max) / 10) return 0; \ res *= 10; \ if (res > (k_ ## uintType ## _max) - v) return 0; \ res += v; }} // arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason // so we don't use this branch #if 0 && WCHAR_MAX > UINT_MAX /* if (sizeof(wchar_t) > sizeof(unsigned) we must use CONVERT_STRING_TO_UINT_FUNC_SLOW But we just stop compiling instead. We need some real cases to test this code. */ #error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX #define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \ uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ if (end) *end = s; \ uintType res = 0; \ for (;; s++) { \ const charTypeUnsigned c = (charTypeUnsigned)*s; \ if (c < '0' || c > '9') { if (end) *end = s; return res; } \ if (res > (k_ ## uintType ## _max) / 10) return 0; \ res *= 10; \ const unsigned v = (unsigned)(c - '0'); \ if (res > (k_ ## uintType ## _max) - v) return 0; \ res += v; }} #endif CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte) CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() { if (end) *end = s; const wchar_t *s2 = s; if (*s == '-') s2++; const wchar_t *end2; UInt32 res = ConvertStringToUInt32(s2, &end2); if (s2 == end2) return 0; if (s != s2) { if (res > (UInt32)1 << (32 - 1)) return 0; res = 0 - res; } else { if (res & (UInt32)1 << (32 - 1)) return 0; } if (end) *end = end2; return (Int32)res; } #define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \ uintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \ { \ if (end) *end = s; \ uintType res = 0; \ for (;; s++) { \ const unsigned c = (unsigned)(Byte)*s - '0'; \ if (c > 7) { \ if (end) \ *end = s; \ return res; \ } \ if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \ return 0; \ res <<= 3; \ res |= c; \ } \ } CONVERT_OCT_STRING_TO_UINT_FUNC(UInt32) CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64) #define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \ uintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \ { \ if (end) *end = s; \ uintType res = 0; \ for (;; s++) { \ unsigned c = (unsigned)(Byte)*s; \ Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s; return res; }) \ if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \ return 0; \ res <<= 4; \ res |= c; \ } \ } CONVERT_HEX_STRING_TO_UINT_FUNC(UInt32) CONVERT_HEX_STRING_TO_UINT_FUNC(UInt64) const char *FindNonHexChar(const char *s) throw() { for (;;) { unsigned c = (Byte)*s++; // pointer can go 1 byte after end c -= '0'; if (c <= 9) continue; c -= 'A' - '0'; c &= ~0x20u; if (c > 5) return s - 1; } } Byte *ParseHexString(const char *s, Byte *dest) throw() { for (;;) { unsigned v0 = (Byte)s[0]; Z7_PARSE_HEX_DIGIT(v0, return dest;) unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;) *dest++ = (Byte)(v1 | (v0 << 4)); } } tmp41wklro_/CPP/Common/StringToInt.h0000444000175000001440000000236614535540600020421 0ustar nabijaczleweliusers// Common/StringToInt.h #ifndef ZIP7_INC_COMMON_STRING_TO_INT_H #define ZIP7_INC_COMMON_STRING_TO_INT_H #include "MyTypes.h" UInt32 ConvertStringToUInt32(const char *s, const char **end) throw(); UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); // Int32 ConvertStringToInt32(const char *s, const char **end) throw(); Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw(); UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); #define Z7_PARSE_HEX_DIGIT(c, err_op) \ { c -= '0'; \ if (c > 9) { \ c -= 'A' - '0'; \ c &= ~0x20u; \ if (c > 5) { err_op } \ c += 10; \ } \ } const char *FindNonHexChar(const char *s) throw(); // in: (dest != NULL) // returns: pointer in dest array after last written byte Byte *ParseHexString(const char *s, Byte *dest) throw(); #endif tmp41wklro_/CPP/Common/TextConfig.cpp0000444000175000001440000000516114535414300020573 0ustar nabijaczleweliusers// Common/TextConfig.cpp #include "StdAfx.h" #include "TextConfig.h" #include "UTFConvert.h" static inline bool IsDelimitChar(char c) { return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t'); } static AString GetIDString(const char *s, unsigned &finishPos) { AString result; for (finishPos = 0; ; finishPos++) { const char c = s[finishPos]; if (IsDelimitChar(c) || c == '=') break; result += c; } return result; } static bool WaitNextLine(const AString &s, unsigned &pos) { for (; pos < s.Len(); pos++) if (s[pos] == 0x0A) return true; return false; } static bool SkipSpaces(const AString &s, unsigned &pos) { for (; pos < s.Len(); pos++) { const char c = s[pos]; if (!IsDelimitChar(c)) { if (c != ';') return true; if (!WaitNextLine(s, pos)) return false; } } return false; } bool GetTextConfig(const AString &s, CObjectVector &pairs) { pairs.Clear(); unsigned pos = 0; ///////////////////// // read strings for (;;) { if (!SkipSpaces(s, pos)) break; CTextConfigPair pair; unsigned finishPos; const AString temp (GetIDString(((const char *)s) + pos, finishPos)); if (!ConvertUTF8ToUnicode(temp, pair.ID)) return false; if (finishPos == 0) return false; pos += finishPos; if (!SkipSpaces(s, pos)) return false; if (s[pos] != '=') return false; pos++; if (!SkipSpaces(s, pos)) return false; if (s[pos] != '\"') return false; pos++; AString message; for (;;) { if (pos >= s.Len()) return false; char c = s[pos++]; if (c == '\"') break; if (c == '\\') { c = s[pos++]; switch (c) { case 'n': c = '\n'; break; case 't': c = '\t'; break; case '\\': break; case '\"': break; default: message += '\\'; break; } } message += c; } if (!ConvertUTF8ToUnicode(message, pair.String)) return false; pairs.Add(pair); } return true; } int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw() { FOR_VECTOR (i, pairs) if (pairs[i].ID.IsEqualTo(id)) return (int)i; return -1; } UString GetTextConfigValue(const CObjectVector &pairs, const char *id) { const int index = FindTextConfigItem(pairs, id); if (index < 0) return UString(); return pairs[index].String; } tmp41wklro_/CPP/Common/TextConfig.h0000444000175000001440000000073314357314620020246 0ustar nabijaczleweliusers// Common/TextConfig.h #ifndef ZIP7_INC_COMMON_TEXT_CONFIG_H #define ZIP7_INC_COMMON_TEXT_CONFIG_H #include "MyString.h" struct CTextConfigPair { UString ID; UString String; }; bool GetTextConfig(const AString &text, CObjectVector &pairs); int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw(); UString GetTextConfigValue(const CObjectVector &pairs, const char *id); #endif tmp41wklro_/CPP/Common/UTFConvert.cpp0000444000175000001440000005104114564614220020523 0ustar nabijaczleweliusers// UTFConvert.cpp #include "StdAfx.h" // #include #include "MyTypes.h" #include "UTFConvert.h" #ifndef Z7_WCHART_IS_16BIT #ifndef __APPLE__ // we define it if the system supports files with non-utf8 symbols: #define MY_UTF8_RAW_NON_UTF8_SUPPORTED #endif #endif /* MY_UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte n : MY_UTF8_START(n) : Bits of code point 0 : 0x80 : : unused 1 : 0xC0 : 11 : 2 : 0xE0 : 16 : Basic Multilingual Plane 3 : 0xF0 : 21 : Unicode space 4 : 0xF8 : 26 : 5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value 7 : 0xFF : */ #define MY_UTF8_START(n) (0x100 - (1 << (7 - (n)))) #define MY_UTF8_HEAD_PARSE2(n) \ if (c < MY_UTF8_START((n) + 1)) \ { numBytes = (n); val -= MY_UTF8_START(n); } #ifndef Z7_WCHART_IS_16BIT /* if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence, when we convert wchar_t strings to UTF-8: (_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode (_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4 (_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack) */ #define MY_UTF8_NUM_TAIL_BYTES_MAX 5 #endif /* #define MY_UTF8_HEAD_PARSE \ UInt32 val = c; \ MY_UTF8_HEAD_PARSE2(1) \ else MY_UTF8_HEAD_PARSE2(2) \ else MY_UTF8_HEAD_PARSE2(3) \ else MY_UTF8_HEAD_PARSE2(4) \ else MY_UTF8_HEAD_PARSE2(5) \ #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6 else MY_UTF8_HEAD_PARSE2(6) #endif */ #define MY_UTF8_HEAD_PARSE_MAX_3_BYTES \ UInt32 val = c; \ MY_UTF8_HEAD_PARSE2(1) \ else MY_UTF8_HEAD_PARSE2(2) \ else { numBytes = 3; val -= MY_UTF8_START(3); } #define MY_UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) #define START_POINT_FOR_SURROGATE 0x10000 /* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000) to simplify internal intermediate conversion in Linux: RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8 */ #if defined(Z7_WCHART_IS_16BIT) #define UTF_ESCAPE_PLANE 0 #else /* we can place 128 ESCAPE chars to ef 80 - ee be 80 (3-bytes utf-8) : similar to WSL ef ff - ee bf bf 1f ef 80 - f7 be be 80 (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) 1f ef ff - f7 be bf bf (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) */ // #define UTF_ESCAPE_PLANE_HIGH (0x1f << 16) // #define UTF_ESCAPE_PLANE UTF_ESCAPE_PLANE_HIGH #define UTF_ESCAPE_PLANE 0 /* if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is set) { if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH) { we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane. But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive) So we still need a way to extract 8-bit Escapes and BMP-Escapes-8 from same BMP-Escapes-16 stored in 7z. And if we want to restore any 8-bit from 7z archive, we still must use Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT for (utf-8 -> utf-16) Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21 } else (UTF_ESCAPE_PLANE == 0) { we must convert original 3-bytes utf-8 BMP-Escape point to sequence of 3 BMP-Escape-16 points with Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT so we can extract original RAW-UTF-8 from UTFD-16 later. } } */ #endif #define UTF_ESCAPE_BASE 0xef00 #ifdef UTF_ESCAPE_BASE #define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80) #endif #define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800) #define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffc00) == 0xdc00) #define UTF_ERROR_UTF8_CHECK \ { NonUtf = true; continue; } void CUtf8Check::Check_Buf(const char *src, size_t size) throw() { Clear(); // Byte maxByte = 0; for (;;) { if (size == 0) break; const Byte c = (Byte)(*src++); size--; if (c == 0) { ZeroChar = true; continue; } /* if (c > maxByte) maxByte = c; */ if (c < 0x80) continue; if (c < 0xc0 + 2) UTF_ERROR_UTF8_CHECK unsigned numBytes; UInt32 val = c; MY_UTF8_HEAD_PARSE2(1) else MY_UTF8_HEAD_PARSE2(2) else MY_UTF8_HEAD_PARSE2(3) else MY_UTF8_HEAD_PARSE2(4) else MY_UTF8_HEAD_PARSE2(5) else { UTF_ERROR_UTF8_CHECK } unsigned pos = 0; do { if (pos == size) break; unsigned c2 = (Byte)src[pos]; c2 -= 0x80; if (c2 >= 0x40) break; val <<= 6; val |= c2; if (pos == 0) if (val < (((unsigned)1 << 7) >> numBytes)) break; pos++; } while (--numBytes); if (numBytes != 0) { if (pos == size) Truncated = true; else UTF_ERROR_UTF8_CHECK } #ifdef UTF_ESCAPE_BASE if (IS_ESCAPE_POINT(val, 0)) Escape = true; #endif if (MaxHighPoint < val) MaxHighPoint = val; if (IS_SURROGATE_POINT(val)) SingleSurrogate = true; src += pos; size -= pos; } // MaxByte = maxByte; } bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw() { CUtf8Check check; check.Check_Buf(src, size); return check.IsOK(allowReduced); } /* bool CheckUTF8_chars(const char *src, bool allowReduced) throw() { CUtf8Check check; check.CheckBuf(src, strlen(src)); return check.IsOK(allowReduced); } */ bool CheckUTF8_AString(const AString &s) throw() { CUtf8Check check; check.Check_AString(s); return check.IsOK(); } /* bool CheckUTF8(const char *src, bool allowReduced) throw() { // return Check_UTF8_Buf(src, strlen(src), allowReduced); for (;;) { const Byte c = (Byte)(*src++); if (c == 0) return true; if (c < 0x80) continue; if (c < 0xC0 + 2 || c >= 0xf5) return false; unsigned numBytes; MY_UTF8_HEAD_PARSE else return false; unsigned pos = 0; do { Byte c2 = (Byte)(*src++); if (c2 < 0x80 || c2 >= 0xC0) return allowReduced && c2 == 0; val <<= 6; val |= (c2 - 0x80); pos++; } while (--numBytes); if (val < MY_UTF8_RANGE(pos - 1)) return false; if (val >= 0x110000) return false; } } */ // in case of UTF-8 error we have two ways: // 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version // 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols #define UTF_REPLACEMENT_CHAR 0xfffd #define UTF_ESCAPE(c) \ ((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) ? \ UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR) /* #define UTF_HARD_ERROR_UTF8 { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ destPos++; ok = false; continue; } */ // we ignore utf errors, and don't change (ok) variable! #define UTF_ERROR_UTF8 \ { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ destPos++; continue; } // we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points: // for debug puposes only we can store UTF-32 in wchar_t: // #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1) /* WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found. Ant it can emit single 0xfffd from 2 src bytes. It doesn't emit single 0xfffd from 3-4 src bytes. We can 1) emit Escape point for each incorrect byte. So we can data recover later 2) emit 0xfffd for each incorrect byte. That scheme is similar to Escape scheme, but we emit 0xfffd instead of each Escape point. 3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme */ static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw() { size_t destPos = 0; bool ok = true; for (;;) { if (src == srcLim) { *destLen = destPos; return ok; } const Byte c = (Byte)(*src++); if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xc0 + 2 || c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility { UTF_ERROR_UTF8 } unsigned numBytes; MY_UTF8_HEAD_PARSE_MAX_3_BYTES unsigned pos = 0; do { if (src + pos == srcLim) break; unsigned c2 = (Byte)src[pos]; c2 -= 0x80; if (c2 >= 0x40) break; val <<= 6; val |= c2; pos++; if (pos == 1) { if (val < (((unsigned)1 << 7) >> numBytes)) break; if (numBytes == 2) { if (flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) if ((val & (0xF800 >> 6)) == (0xd800 >> 6)) break; } else if (numBytes == 3 && val >= (0x110000 >> 12)) break; } } while (--numBytes); if (numBytes != 0) { if ((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) == 0) { // the following code to emit the 0xfffd chars as win32 Utf8 function. // disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode src += pos; } UTF_ERROR_UTF8 } /* if (val < MY_UTF8_RANGE(pos - 1)) UTF_ERROR_UTF8 */ #ifdef UTF_ESCAPE_BASE if ((flags & Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT) && IS_ESCAPE_POINT(val, 0)) { // We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes) UTF_ERROR_UTF8 } #endif /* We don't expect virtual Escape-21 points in UTF-8 stream. And we don't check for Escape-21. So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points. Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases? */ if (val < START_POINT_FOR_SURROGATE) { /* if ((flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) && IS_SURROGATE_POINT(val)) { // We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes) UTF_ERROR_UTF8 } */ if (dest) dest[destPos] = (wchar_t)val; destPos++; } else { /* if (val >= 0x110000) { // We will emit utf16-Escape-16-21 point from each source byte UTF_ERROR_UTF8 } */ if (dest) { dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10)); dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff)); } destPos += 2; } src += pos; } } #define MY_UTF8_HEAD(n, val) ((char)(MY_UTF8_START(n) + (val >> (6 * (n))))) #define MY_UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F))) static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags) { size_t size = (size_t)(srcLim - src); for (;;) { if (src == srcLim) return size; UInt32 val = (UInt32)(*src++); if (val < 0x80) continue; if (val < MY_UTF8_RANGE(1)) { size++; continue; } #ifdef UTF_ESCAPE_BASE #if UTF_ESCAPE_PLANE != 0 if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE) if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) continue; #endif if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE) if (IS_ESCAPE_POINT(val, 0)) continue; #endif if (IS_SURROGATE_POINT(val)) { // it's hack to UTF-8 encoding if (val < 0xdc00 && src != srcLim) { const UInt32 c2 = (UInt32)*src; if (c2 >= 0xdc00 && c2 < 0xe000) src++; } size += 2; continue; } #ifdef Z7_WCHART_IS_16BIT size += 2; #else if (val < MY_UTF8_RANGE(2)) size += 2; else if (val < MY_UTF8_RANGE(3)) size += 3; else if (val < MY_UTF8_RANGE(4)) size += 4; else if (val < MY_UTF8_RANGE(5)) size += 5; else #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6 size += 6; #else size += 3; #endif #endif } } static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags) { for (;;) { if (src == srcLim) return dest; UInt32 val = (UInt32)*src++; if (val < 0x80) { *dest++ = (char)val; continue; } if (val < MY_UTF8_RANGE(1)) { dest[0] = MY_UTF8_HEAD(1, val); dest[1] = MY_UTF8_CHAR(0, val); dest += 2; continue; } #ifdef UTF_ESCAPE_BASE #if UTF_ESCAPE_PLANE != 0 /* if (wchar_t is 32-bit) && (Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE is set) && (point is virtual escape plane) we extract 8-bit byte from virtual HIGH-ESCAPE PLANE. */ if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE) if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) { *dest++ = (char)(val); continue; } #endif // UTF_ESCAPE_PLANE != 0 /* if (Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE is defined) we extract 8-bit byte from BMP-ESCAPE PLANE. */ if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE) if (IS_ESCAPE_POINT(val, 0)) { *dest++ = (char)(val); continue; } #endif // UTF_ESCAPE_BASE if (IS_SURROGATE_POINT(val)) { // it's hack to UTF-8 encoding if (val < 0xdc00 && src != srcLim) { const UInt32 c2 = (UInt32)*src; if (IS_LOW_SURROGATE_POINT(c2)) { src++; val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000; dest[0] = MY_UTF8_HEAD(3, val); dest[1] = MY_UTF8_CHAR(2, val); dest[2] = MY_UTF8_CHAR(1, val); dest[3] = MY_UTF8_CHAR(0, val); dest += 4; continue; } } if (flags & Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR) val = UTF_REPLACEMENT_CHAR; // WIN32 function does it } #ifndef Z7_WCHART_IS_16BIT if (val < MY_UTF8_RANGE(2)) #endif { dest[0] = MY_UTF8_HEAD(2, val); dest[1] = MY_UTF8_CHAR(1, val); dest[2] = MY_UTF8_CHAR(0, val); dest += 3; continue; } #ifndef Z7_WCHART_IS_16BIT // we don't expect this case. so we can throw exception // throw 20210407; char b; unsigned numBits; if (val < MY_UTF8_RANGE(3)) { numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); } else if (val < MY_UTF8_RANGE(4)) { numBits = 6 * 4; b = MY_UTF8_HEAD(4, val); } else if (val < MY_UTF8_RANGE(5)) { numBits = 6 * 5; b = MY_UTF8_HEAD(5, val); } #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6 else { numBits = 6 * 6; b = (char)MY_UTF8_START(6); } #else else { val = UTF_REPLACEMENT_CHAR; { numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); } } #endif *dest++ = b; do { numBits -= 6; *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F)); } while (numBits != 0); #endif } } bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags); bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags); dest.ReleaseBuf_SetEnd((unsigned)destLen); return res; } bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags) { return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest, flags); } static unsigned g_UTF8_To_Unicode_Flags = Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE #ifndef Z7_WCHART_IS_16BIT | Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR #ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED | Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT #endif #endif ; /* bool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest) { return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); } */ bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); } void Print_UString(const UString &a); void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags) { /* if (src.Len()== 24) throw "202104"; */ dest.Empty(); const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); char *destStart = dest.GetBuf((unsigned)destLen); const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags); dest.ReleaseBuf_SetEnd((unsigned)destLen); // printf("\nlen = %d\n", src.Len()); if (destLen != (size_t)(destEnd - destStart)) { /* // dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart)); printf("\nlen = %d\n", (unsigned)destLen); printf("\n(destEnd - destStart) = %d\n", (unsigned)(destEnd - destStart)); printf("\n"); // Print_UString(src); printf("\n"); // printf("\nlen = %d\n", destLen); */ throw 20210406; } } unsigned g_Unicode_To_UTF8_Flags = // Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE 0 #ifndef _WIN32 #ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED | Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE #else | Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR #endif #endif ; void ConvertUnicodeToUTF8(const UString &src, AString &dest) { ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags); } void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest) { const unsigned flags = g_Unicode_To_UTF8_Flags; dest.Free(); const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); dest.Alloc(destLen); const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags); if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest)) throw 202104; } /* #ifndef _WIN32 void Convert_UTF16_To_UTF32(const UString &src, UString &dest) { dest.Empty(); for (size_t i = 0; i < src.Len();) { wchar_t c = src[i++]; if (c >= 0xd800 && c < 0xdc00 && i < src.Len()) { const wchar_t c2 = src[i]; if (c2 >= 0xdc00 && c2 < 0xe000) { // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); // printf("%4x\n", (int)c); i++; } } dest += c; } } void Convert_UTF32_To_UTF16(const UString &src, UString &dest) { dest.Empty(); for (size_t i = 0; i < src.Len();) { wchar_t w = src[i++]; if (w >= 0x10000 && w < 0x110000) { w -= 0x10000; dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff)); w = 0xdc00 + (w & 0x3ff); } dest += w; } } bool UTF32_IsThere_BigPoint(const UString &src) { for (size_t i = 0; i < src.Len();) { const UInt32 c = (UInt32)src[i++]; if (c >= 0x110000) return true; } return false; } bool Unicode_IsThere_BmpEscape(const UString &src) { for (size_t i = 0; i < src.Len();) { const UInt32 c = (UInt32)src[i++]; if (IS_ESCAPE_POINT(c, 0)) return true; } return false; } #endif bool Unicode_IsThere_Utf16SurrogateError(const UString &src) { for (size_t i = 0; i < src.Len();) { const UInt32 val = (UInt32)src[i++]; if (IS_SURROGATE_POINT(val)) { // it's hack to UTF-8 encoding if (val >= 0xdc00 || i == src.Len()) return true; const UInt32 c2 = (UInt32)*src; if (!IS_LOW_SURROGATE_POINT(c2)) return true; } } return false; } */ #ifndef Z7_WCHART_IS_16BIT void Convert_UnicodeEsc16_To_UnicodeEscHigh #if UTF_ESCAPE_PLANE == 0 (UString &) {} #else (UString &s) { const unsigned len = s.Len(); for (unsigned i = 0; i < len; i++) { wchar_t c = s[i]; if (IS_ESCAPE_POINT(c, 0)) { c += UTF_ESCAPE_PLANE; s.ReplaceOneCharAtPos(i, c); } } } #endif #endif tmp41wklro_/CPP/Common/UTFConvert.h0000444000175000001440000002530014404421700020157 0ustar nabijaczleweliusers// Common/UTFConvert.h #ifndef ZIP7_INC_COMMON_UTF_CONVERT_H #define ZIP7_INC_COMMON_UTF_CONVERT_H #include "MyBuffer.h" #include "MyString.h" struct CUtf8Check { // Byte MaxByte; // in original src stream bool NonUtf; bool ZeroChar; bool SingleSurrogate; bool Escape; bool Truncated; UInt32 MaxHighPoint; // only for points >= 0x80 CUtf8Check() { Clear(); } void Clear() { // MaxByte = 0; NonUtf = false; ZeroChar = false; SingleSurrogate = false; Escape = false; Truncated = false; MaxHighPoint = 0; } void Update(const CUtf8Check &c) { if (c.NonUtf) NonUtf = true; if (c.ZeroChar) ZeroChar = true; if (c.SingleSurrogate) SingleSurrogate = true; if (c.Escape) Escape = true; if (c.Truncated) Truncated = true; if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint; } void PrintStatus(AString &s) const { s.Empty(); // s.Add_OptSpaced("MaxByte="); // s.Add_UInt32(MaxByte); if (NonUtf) s.Add_OptSpaced("non-UTF8"); if (ZeroChar) s.Add_OptSpaced("ZeroChar"); if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate"); if (Escape) s.Add_OptSpaced("Escape"); if (Truncated) s.Add_OptSpaced("Truncated"); if (MaxHighPoint != 0) { s.Add_OptSpaced("MaxUnicode="); s.Add_UInt32(MaxHighPoint); } } bool IsOK(bool allowReduced = false) const { if (NonUtf || SingleSurrogate || ZeroChar) return false; if (MaxHighPoint >= 0x110000) return false; if (Truncated && !allowReduced) return false; return true; } // it checks full buffer as specified in (size) and it doesn't stop on zero char void Check_Buf(const char *src, size_t size) throw(); void Check_AString(const AString &s) throw() { Check_Buf(s.Ptr(), s.Len()); } }; /* if (allowReduced == false) - all UTF-8 character sequences must be finished. if (allowReduced == true) - it allows truncated last character-Utf8-sequence */ bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw(); bool CheckUTF8_AString(const AString &s) throw(); #define Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR (1 << 0) #define Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE (1 << 1) #define Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT (1 << 2) /* Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR if (flag is NOT set) { it processes SINGLE-SURROGATE-8 as valid Unicode point. it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16 Note: some sequencies of two SINGLE-SURROGATE-8 points will generate correct SURROGATE-16-PAIR, and that SURROGATE-16-PAIR later will be converted to correct UTF8-SURROGATE-21 point. So we don't restore original STR-8 sequence in that case. } if (flag is set) { if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is defined) it generates ESCAPE for SINGLE-SURROGATE-8, if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is not defined) it generates U+fffd for SINGLE-SURROGATE-8, } Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE if (flag is NOT set) it generates (U+fffd) code for non-UTF-8 (invalid) characters if (flag is set) { It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters. And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes. } Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT if (flag is NOT set) { it process ESCAPE-8 points as another Unicode points. In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences, so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW } if (flag is set) { it generates ESCAPE-16-21 for ESCAPE-8 points so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21. } Main USE CASES with UTF-8 <-> UTF-16 conversions: WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW { set Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE Do NOT set Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR Do NOT set Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8. } Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW { we want restore original UTF-8-RAW sequence later from that ESCAPE-16. Set the flags: Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT } MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW { we want to restore correct UTF-8 without any BMP processing: Set the flags: Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE } */ // zero char is not allowed in (src) buf bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0); bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0); bool ConvertUTF8ToUnicode(const AString &src, UString &dest); #define Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR (1 << 8) #define Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE (1 << 9) // #define Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE (1 << 10) /* Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR if (flag is NOT set) { we extract SINGLE-SURROGATE as normal UTF-8 In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in . In Linux : use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE, if (Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) is used. use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux) will generate SINGLE-SURROGATE-UTF-8 here. } if (flag is set) { we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE it can be used for compatibility mode with WIN32 UTF function or if we want UTF-8 stream without any errors } Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16 if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16 in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive): if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane. if (we don't use High-Escape-Plane), we must use Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE. Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE // that flag affects the code only if (wchar_t is 32-bit) // that mode with high-escape can be disabled now in UTFConvert.cpp if (flag is NOT set) it doesn't extract raw 8-bit symbol from High-Escape-Plane if (flag is set) it extracts raw 8-bit symbol from High-Escape-Plane Main use cases: WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW { Do NOT set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE. Do NOT set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR. So we restore original UTF-16-RAW. } Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive set Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE for intermediate UTF-16. Note: high esacape mode can be ignored now in UTFConvert.cpp macOS: the system doesn't support incorrect UTF-8 in file names. set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR */ extern unsigned g_Unicode_To_UTF8_Flags; void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0); void ConvertUnicodeToUTF8(const UString &src, AString &dest); void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest); /* #ifndef _WIN32 void Convert_UTF16_To_UTF32(const UString &src, UString &dest); void Convert_UTF32_To_UTF16(const UString &src, UString &dest); bool UTF32_IsThere_BigPoint(const UString &src); bool Unicode_IsThere_BmpEscape(const UString &src); #endif bool Unicode_IsThere_Utf16SurrogateError(const UString &src); */ #ifdef Z7_WCHART_IS_16BIT #define Convert_UnicodeEsc16_To_UnicodeEscHigh(s) #else void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s); #endif /* // #include "../../C/CpuArch.h" // ---------- Utf16 Little endian functions ---------- // We store 16-bit surrogates even in 32-bit WCHARs in Linux. // So now we don't use the following code: #if WCHAR_MAX > 0xffff // void *p : pointer to src bytes stream // size_t len : num Utf16 characters : it can include or not include NULL character inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len) { #if WCHAR_MAX > 0xffff size_t num_wchars = 0; for (size_t i = 0; i < len; i++) { wchar_t c = GetUi16(p); p = (const void *)((const Byte *)p + 2); if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) { wchar_t c2 = GetUi16(p); if (c2 >= 0xdc00 && c2 < 0xe000) { c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); p = (const void *)((const Byte *)p + 2); i++; } } num_wchars++; } return num_wchars; #else UNUSED_VAR(p) return len; #endif } // #include inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest) { for (size_t i = 0; i < len; i++) { wchar_t c = GetUi16(p); p = (const void *)((const Byte *)p + 2); #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; #endif #if WCHAR_MAX > 0xffff if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) { wchar_t c2 = GetUi16(p); if (c2 >= 0xdc00 && c2 < 0xe000) { // printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2); c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); p = (const void *)((const Byte *)p + 2); i++; // printf("%4x\n", (int)c); } } #endif *dest++ = c; } return dest; } inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p) { size_t num = 0; for (;;) { wchar_t c = *p++; if (c == 0) return num; num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1); } return num; } inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest) { for (;;) { wchar_t c = *p++; if (c == 0) return dest; if (c >= 0x10000 && c < 0x110000) { SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF))); SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF))); dest += 4; } else { SetUi16(dest, c); dest += 2; } } } #endif */ #endif tmp41wklro_/CPP/Common/Wildcard.cpp0000444000175000001440000004440414353576360020272 0ustar nabijaczleweliusers// Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" extern bool g_CaseSensitive; bool g_CaseSensitive = #ifdef _WIN32 false; #elif defined (__APPLE__) #ifdef TARGET_OS_IPHONE true; #else false; #endif #else true; #endif bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) { if (g_CaseSensitive) return IsString1PrefixedByString2(s1, s2); return IsString1PrefixedByString2_NoCase(s1, s2); } // #include /* static int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { if (c1 == 0) return -1; if (c2 == 0) return 1; if (c1 == '/') c1 = 0; if (c2 == '/') c2 = 0; if (c1 < c2) return -1; if (c1 > c2) return 1; continue; } if (c1 == 0) return 0; } } */ static int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { if (c1 == 0) return -1; if (c2 == 0) return 1; if (IS_PATH_SEPAR(c1)) c1 = 0; if (IS_PATH_SEPAR(c2)) c2 = 0; if (c1 < c2) return -1; if (c1 > c2) return 1; continue; } if (c1 == 0) return 0; } } static int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { if (c1 == 0) return -1; if (c2 == 0) return 1; if (IS_PATH_SEPAR(c1)) c1 = 0; if (IS_PATH_SEPAR(c2)) c2 = 0; c1 = MyCharUpper(c1); c2 = MyCharUpper(c2); if (c1 < c2) return -1; if (c1 > c2) return 1; continue; } if (c1 == 0) return 0; } } int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW { /* printf("\nCompareFileNames"); printf("\n S1: %ls", s1); printf("\n S2: %ls", s2); printf("\n"); */ // 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1 if (g_CaseSensitive) return MyStringCompare_Path(s1, s2); return MyStringCompareNoCase_Path(s1, s2); } #ifndef USE_UNICODE_FSTRING int CompareFileNames(const char *s1, const char *s2) { const UString u1 = fs2us(s1); const UString u2 = fs2us(s2); return CompareFileNames(u1, u2); } #endif // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { const wchar_t m = *mask; const wchar_t c = *name; if (m == 0) return (c == 0); if (m == '*') { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == '?') { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); unsigned len = path.Len(); if (len == 0) return; UString name; unsigned prev = 0; for (unsigned i = 0; i < len; i++) if (IsPathSepar(path[i])) { name.SetFrom(path.Ptr(prev), i - prev); pathParts.Add(name); prev = i + 1; } name.SetFrom(path.Ptr(prev), len - prev); pathParts.Add(name); } void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) { const wchar_t *start = path; const wchar_t *p = start + path.Len(); for (; p != start; p--) if (IsPathSepar(*(p - 1))) break; dirPrefix.SetFrom(path, (unsigned)(p - start)); name = p; } void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) { const wchar_t *start = path; const wchar_t *p = start + path.Len(); if (p != start) { if (IsPathSepar(*(p - 1))) p--; for (; p != start; p--) if (IsPathSepar(*(p - 1))) break; } dirPrefix.SetFrom(path, (unsigned)(p - start)); name = p; } /* UString ExtractDirPrefixFromPath(const UString &path) { return path.Left(path.ReverseFind_PathSepar() + 1)); } */ UString ExtractFileNameFromPath(const UString &path) { return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1))); } bool DoesWildcardMatchName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildcard(const UString &path) { for (unsigned i = 0; i < path.Len(); i++) { wchar_t c = path[i]; if (c == '*' || c == '?') return true; } return false; } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile rec M<=N [N-M, N) - !ForDir nonrec M=N [0, M) - ForDir rec M &items = include ? IncludeItems : ExcludeItems; items.Add(item); } void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) { if (item.PathParts.Size() <= 1) { if (item.PathParts.Size() != 0 && item.WildcardMatching) { if (!DoesNameContainWildcard(item.PathParts.Front())) item.WildcardMatching = false; } AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); // WIN32 doesn't support wildcards in file names if (item.WildcardMatching && ignoreWildcardIndex != 0 && DoesNameContainWildcard(front)) { AddItemSimple(include, item); return; } CCensorNode &subNode = Find_SubNode_Or_Add_New(front); item.PathParts.Delete(0); subNode.AddItem(include, item, ignoreWildcardIndex - 1); } /* void CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = props.Recursive; item.ForFile = props.ForFile; item.ForDir = props.ForDir; item.WildcardMatching = props.WildcardMatching; AddItem(include, item); } */ bool CCensorNode::NeedCheckSubDirs() const { FOR_VECTOR (i, IncludeItems) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; FOR_VECTOR (i, SubNodes) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector &items = include ? IncludeItems : ExcludeItems; FOR_VECTOR (i, items) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } if (pathParts.Size() > 1) { int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include)) return true; } } bool finded = CheckPathCurrent(true, pathParts, isFile); include = finded; // if (!finded), then (true) is allowed also return finded; } /* bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); if (CheckPathVect(pathParts, isFile, include)) { if (!include || !isAltStream) return true; } if (isAltStream && !pathParts.IsEmpty()) { UString &back = pathParts.Back(); int pos = back.Find(L':'); if (pos > 0) { back.DeleteFrom(pos); return CheckPathVect(pathParts, isFile, include); } } return false; } bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool include; if (CheckPath2(isAltStream, path, isFile, include)) return include; return false; } */ bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (!Parent) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot_Change(include, pathParts, isFile); } bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (!Parent) return false; UStringVector pathParts2; pathParts2.Add(Name); pathParts2 += pathParts; return Parent->CheckPathToRoot_Change(include, pathParts2, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; FOR_VECTOR (i, fromNodes.SubNodes) { const CCensorNode &node = fromNodes.SubNodes[i]; Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node); } } int CCensor::FindPairForPrefix(const UString &prefix) const { FOR_VECTOR (i, Pairs) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return (int)i; return -1; } #ifdef _WIN32 bool IsDriveColonName(const wchar_t *s) { unsigned c = s[0]; c |= 0x20; c -= 'a'; return c <= (unsigned)('z' - 'a') && s[1] == ':' && s[2] == 0; } unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) { if (pathParts.IsEmpty()) return 0; unsigned testIndex = 0; if (pathParts[0].IsEmpty()) { if (pathParts.Size() < 4 || !pathParts[1].IsEmpty() || pathParts[2] != L"?") return 0; testIndex = 3; } if (NWildcard::IsDriveColonName(pathParts[testIndex])) return testIndex + 1; return 0; } #endif static unsigned GetNumPrefixParts(const UStringVector &pathParts) { if (pathParts.IsEmpty()) return 0; /* empty last part could be removed already from (pathParts), if there was tail path separator (slash) in original full path string. */ #ifdef _WIN32 if (IsDriveColonName(pathParts[0])) return 1; if (!pathParts[0].IsEmpty()) return 0; if (pathParts.Size() == 1) return 1; if (!pathParts[1].IsEmpty()) return 1; if (pathParts.Size() == 2) return 2; if (pathParts[2] == L".") return 3; unsigned networkParts = 2; if (pathParts[2] == L"?") { if (pathParts.Size() == 3) return 3; if (IsDriveColonName(pathParts[3])) return 4; if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC")) return 3; networkParts = 4; } networkParts += // 2; // server/share 1; // server if (pathParts.Size() <= networkParts) return pathParts.Size(); return networkParts; #else return pathParts[0].IsEmpty() ? 1 : 0; #endif } void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props) { if (path.IsEmpty()) throw "Empty file path"; UStringVector pathParts; SplitPathToParts(path, pathParts); CCensorPathProps props2 = props; bool forFile = true; bool forDir = true; const UString &back = pathParts.Back(); if (back.IsEmpty()) { // we have tail path separator. So it's directory. // we delete tail path separator here even for "\" and "c:\" forFile = false; pathParts.DeleteBack(); } else { if (props.MarkMode == kMark_StrictFile || (props.MarkMode == kMark_StrictFile_IfWildcard && DoesNameContainWildcard(back))) forDir = false; } UString prefix; int ignoreWildcardIndex = -1; // #ifdef _WIN32 // we ignore "?" wildcard in "\\?\" prefix. if (pathParts.Size() >= 3 && pathParts[0].IsEmpty() && pathParts[1].IsEmpty() && pathParts[2] == L"?") ignoreWildcardIndex = 2; // #endif if (pathMode != k_AbsPath) { // detection of the number of Skip Parts for prefix ignoreWildcardIndex = -1; const unsigned numPrefixParts = GetNumPrefixParts(pathParts); unsigned numSkipParts = numPrefixParts; if (pathMode != k_FullPath) { // if absolute path, then all parts before last part will be in prefix if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts) numSkipParts = pathParts.Size() - 1; } { int dotsIndex = -1; for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") dotsIndex = (int)i; } if (dotsIndex >= 0) { if (dotsIndex == (int)pathParts.Size() - 1) numSkipParts = pathParts.Size(); else numSkipParts = pathParts.Size() - 1; } } // we split (pathParts) to (prefix) and (pathParts). for (unsigned i = 0; i < numSkipParts; i++) { { const UString &front = pathParts.Front(); // WIN32 doesn't support wildcards in file names if (props.WildcardMatching) if (i >= numPrefixParts && DoesNameContainWildcard(front)) break; prefix += front; prefix.Add_PathSepar(); } pathParts.Delete(0); } } int index = FindPairForPrefix(prefix); if (index < 0) { index = (int)Pairs.Size(); Pairs.AddNew().Prefix = prefix; } if (pathMode != k_AbsPath) { if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty())) { // we create universal item, if we skip all parts as prefix (like \ or L:\ ) pathParts.Clear(); pathParts.Add(UString("*")); forFile = true; forDir = true; props2.WildcardMatching = true; props2.Recursive = false; } } /* // not possible now if (!forDir && !forFile) { UString s ("file path was blocked for files and directories: "); s += path; throw s; // return; // for debug : ignore item (don't create Item) } */ CItem item; item.PathParts = pathParts; item.ForDir = forDir; item.ForFile = forFile; item.Recursive = props2.Recursive; item.WildcardMatching = props2.WildcardMatching; Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex); } /* bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool finded = false; FOR_VECTOR (i, Pairs) { bool include; if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } */ void CCensor::ExtendExclude() { unsigned i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; unsigned index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) { FOR_VECTOR(i, CensorPaths) { const CCensorPath &cp = CensorPaths[i]; AddItem(censorPathMode, cp.Include, cp.Path, cp.Props); } CensorPaths.Clear(); } void CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props) { CCensorPath &cp = CensorPaths.AddNew(); cp.Path = path; cp.Include = include; cp.Props = props; } } tmp41wklro_/CPP/Common/Wildcard.h0000444000175000001440000001411114357314620017720 0ustar nabijaczleweliusers// Common/Wildcard.h #ifndef ZIP7_INC_COMMON_WILDCARD_H #define ZIP7_INC_COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW; #ifndef USE_UNICODE_FSTRING int CompareFileNames(const char *s1, const char *s2); #endif bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name); void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path) UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildcard(const UString &path); bool DoesWildcardMatchName(const UString &mask, const UString &name); namespace NWildcard { #ifdef _WIN32 // returns true, if name is like "a:", "c:", ... bool IsDriveColonName(const wchar_t *s); unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts); #endif struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool WildcardMatching; #ifdef _WIN32 bool IsDriveItem() const { return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]); } #endif // CItem(): WildcardMatching(true) {} bool AreAllAllowed() const; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; const Byte kMark_FileOrDir = 0; const Byte kMark_StrictFile = 1; const Byte kMark_StrictFile_IfWildcard = 2; struct CCensorPathProps { bool Recursive; bool WildcardMatching; Byte MarkMode; CCensorPathProps(): Recursive(false), WildcardMatching(true), MarkMode(kMark_FileOrDir) {} }; class CCensorNode MY_UNCOPYABLE { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); public: // bool ExcludeDirItems; CCensorNode(): Parent(NULL) // , ExcludeDirItems(false) {} CCensorNode(const UString &name, CCensorNode *parent): Parent(parent) // , ExcludeDirItems(false) , Name(name) {} UString Name; // WIN32 doesn't support wildcards in file names CObjectVector SubNodes; CObjectVector IncludeItems; CObjectVector ExcludeItems; CCensorNode &Find_SubNode_Or_Add_New(const UString &name) { int i = FindSubNode(name); if (i >= 0) return SubNodes[(unsigned)i]; // return SubNodes.Add(CCensorNode(name, this)); CCensorNode &node = SubNodes.AddNew(); node.Parent = this; node.Name = name; return node; } bool AreAllAllowed() const; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1); // void AddItem(bool include, const UString &path, const CCensorPathProps &props); void Add_Wildcard() { CItem item; item.PathParts.Add(L"*"); item.Recursive = false; item.ForFile = true; item.ForDir = true; item.WildcardMatching = true; AddItem( true // include , item); } // NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; /* CheckPathVect() doesn't check path in Parent CCensorNode so use CheckPathVect() for root CCensorNode OUT: returns (true) && (include = false) - file in exlude list returns (true) && (include = true) - file in include list and is not in exlude list returns (false) - file is not in (include/exlude) list */ bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; // CheckPathToRoot_Change() changes pathParts !!! bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const; bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair MY_UNCOPYABLE { UString Prefix; CCensorNode Head; // CPair(const UString &prefix): Prefix(prefix) { }; }; enum ECensorPathMode { k_RelatPath, // absolute prefix as Prefix, remain path in Tree k_FullPath, // drive prefix as Prefix, remain path in Tree k_AbsPath // full path in Tree }; struct CCensorPath { UString Path; bool Include; CCensorPathProps Props; CCensorPath(): Include(true) {} }; class CCensor MY_UNCOPYABLE { int FindPairForPrefix(const UString &prefix) const; public: CObjectVector Pairs; bool ExcludeDirItems; bool ExcludeFileItems; CCensor(): ExcludeDirItems(false), ExcludeFileItems(false) {} CObjectVector CensorPaths; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props); // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; void ExtendExclude(); void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode); void AddPreItem(bool include, const UString &path, const CCensorPathProps &props); void AddPreItem_NoWildcard(const UString &path) { CCensorPathProps props; props.WildcardMatching = false; AddPreItem( true, // include path, props); } void AddPreItem_Wildcard() { CCensorPathProps props; // props.WildcardMatching = true; AddPreItem( true, // include UString("*"), props); } }; } #endif tmp41wklro_/CPP/Common/XzCrc64Init.cpp0000444000175000001440000000024213043677427020561 0ustar nabijaczleweliusers// XzCrc64Init.cpp #include "StdAfx.h" #include "../../C/XzCrc64.h" static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; tmp41wklro_/CPP/Common/XzCrc64Reg.cpp0000444000175000001440000000143514404672500020365 0ustar nabijaczleweliusers// XzCrc64Reg.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #include "../../C/XzCrc64.h" #include "../Common/MyCom.h" #include "../7zip/Common/RegisterCodec.h" Z7_CLASS_IMP_COM_1( CXzCrc64Hasher , IHasher ) UInt64 _crc; public: Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {} }; Z7_COM7F_IMF2(void, CXzCrc64Hasher::Init()) { _crc = CRC64_INIT_VAL; } Z7_COM7F_IMF2(void, CXzCrc64Hasher::Update(const void *data, UInt32 size)) { _crc = Crc64Update(_crc, data, size); } Z7_COM7F_IMF2(void, CXzCrc64Hasher::Final(Byte *digest)) { const UInt64 val = CRC64_GET_DIGEST(_crc); SetUi64(digest, val) } REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8) tmp41wklro_/CPP/Windows/0000700000175000001440000000000014706260545016216 5ustar nabijaczleweliuserstmp41wklro_/CPP/Windows/Clipboard.cpp0000444000175000001440000000531513046600331020620 0ustar nabijaczleweliusers// Windows/Clipboard.cpp #include "StdAfx.h" #ifdef UNDER_CE #include #endif #include "../Common/StringConvert.h" #include "Clipboard.h" #include "Defs.h" #include "MemoryGlobal.h" #include "Shell.h" namespace NWindows { bool CClipboard::Open(HWND wndNewOwner) throw() { m_Open = BOOLToBool(::OpenClipboard(wndNewOwner)); return m_Open; } bool CClipboard::Close() throw() { if (!m_Open) return true; m_Open = !BOOLToBool(CloseClipboard()); return !m_Open; } bool ClipboardIsFormatAvailableHDROP() { return BOOLToBool(IsClipboardFormatAvailable(CF_HDROP)); } /* bool ClipboardGetTextString(AString &s) { s.Empty(); if (!IsClipboardFormatAvailable(CF_TEXT)) return false; CClipboard clipboard; if (!clipboard.Open(NULL)) return false; HGLOBAL h = ::GetClipboardData(CF_TEXT); if (h != NULL) { NMemory::CGlobalLock globalLock(h); const char *p = (const char *)globalLock.GetPointer(); if (p != NULL) { s = p; return true; } } return false; } */ /* bool ClipboardGetFileNames(UStringVector &names) { names.Clear(); if (!IsClipboardFormatAvailable(CF_HDROP)) return false; CClipboard clipboard; if (!clipboard.Open(NULL)) return false; HGLOBAL h = ::GetClipboardData(CF_HDROP); if (h != NULL) { NMemory::CGlobalLock globalLock(h); void *p = (void *)globalLock.GetPointer(); if (p != NULL) { NShell::CDrop drop(false); drop.Attach((HDROP)p); drop.QueryFileNames(names); return true; } } return false; } */ static bool ClipboardSetData(UINT uFormat, const void *data, size_t size) throw() { NMemory::CGlobal global; if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size)) return false; { NMemory::CGlobalLock globalLock(global); LPVOID p = globalLock.GetPointer(); if (!p) return false; memcpy(p, data, size); } if (::SetClipboardData(uFormat, global) == NULL) return false; global.Detach(); return true; } bool ClipboardSetText(HWND owner, const UString &s) { CClipboard clipboard; if (!clipboard.Open(owner)) return false; if (!::EmptyClipboard()) return false; bool res; res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Len() + 1) * sizeof(wchar_t)); #ifndef _UNICODE AString a (UnicodeStringToMultiByte(s, CP_ACP)); if (ClipboardSetData(CF_TEXT, (const char *)a, (a.Len() + 1) * sizeof(char))) res = true; a = UnicodeStringToMultiByte(s, CP_OEMCP); if (ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Len() + 1) * sizeof(char))) res = true; #endif return res; } } tmp41wklro_/CPP/Windows/Clipboard.h0000444000175000001440000000103314357314620020267 0ustar nabijaczleweliusers// Windows/Clipboard.h #ifndef ZIP7_INC_CLIPBOARD_H #define ZIP7_INC_CLIPBOARD_H #include "../Common/MyString.h" namespace NWindows { class CClipboard { bool m_Open; public: CClipboard(): m_Open(false) {} ~CClipboard() { Close(); } bool Open(HWND wndNewOwner) throw(); bool Close() throw(); }; bool ClipboardIsFormatAvailableHDROP(); // bool ClipboardGetFileNames(UStringVector &names); // bool ClipboardGetTextString(AString &s); bool ClipboardSetText(HWND owner, const UString &s); } #endif tmp41wklro_/CPP/Windows/COM.h0000444000175000001440000000313514405107200016777 0ustar nabijaczleweliusers// Windows/COM.h #ifndef ZIP7_INC_WINDOWS_COM_H #define ZIP7_INC_WINDOWS_COM_H // #include "../Common/MyString.h" namespace NWindows { namespace NCOM { #ifdef _WIN32 class CComInitializer { public: CComInitializer() { #ifdef UNDER_CE CoInitializeEx(NULL, COINIT_MULTITHREADED); #else // it's single thread. Do we need multithread? CoInitialize(NULL); #endif } ~CComInitializer() { CoUninitialize(); } }; /* class CStgMedium2 { STGMEDIUM _object; bool _mustBeReleased; public: CStgMedium2(): _mustBeReleased(false) {} ~CStgMedium2() { Free(); } void Free() { if (_mustBeReleased) ReleaseStgMedium(&_object); _mustBeReleased = false; } const STGMEDIUM* operator->() const { return &_object;} STGMEDIUM* operator->() { return &_object;} STGMEDIUM* operator&() { return &_object; } }; */ struct CStgMedium: public STGMEDIUM { CStgMedium() { tymed = TYMED_NULL; // 0 hGlobal = NULL; pUnkForRelease = NULL; } ~CStgMedium() { ReleaseStgMedium(this); } }; #endif /* ////////////////////////////////// // GUID <--> String Conversions UString GUIDToStringW(REFGUID guid); AString GUIDToStringA(REFGUID guid); #ifdef UNICODE #define GUIDToString GUIDToStringW #else #define GUIDToString GUIDToStringA #endif HRESULT StringToGUIDW(const wchar_t *string, GUID &classID); HRESULT StringToGUIDA(const char *string, GUID &classID); #ifdef UNICODE #define StringToGUID StringToGUIDW #else #define StringToGUID StringToGUIDA #endif */ }} #endif tmp41wklro_/CPP/Windows/CommonDialog.cpp0000444000175000001440000002021414405107200021261 0ustar nabijaczleweliusers// Windows/CommonDialog.cpp #include "StdAfx.h" #include "../Common/MyBuffer.h" #ifdef UNDER_CE #include #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #include "CommonDialog.h" #include "Defs.h" // #include "FileDir.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { /* GetSaveFileName() GetOpenFileName() OPENFILENAME (lpstrInitialDir) : the initial directory. DOCs: the algorithm for selecting the initial directory varies on different platforms: { Win2000/XP/Vista: 1. If lpstrFile contains a path, that path is the initial directory. 2. Otherwise, lpstrInitialDir specifies the initial directory. Win7: If lpstrInitialDir has the same value as was passed the first time the application used an Open or Save As dialog box, the path most recently selected by the user is used as the initial directory. } Win10: in: function supports (lpstrInitialDir) path with super prefix "\\\\?\\" function supports (lpstrInitialDir) path with long path function doesn't support absolute (lpstrFile) path with super prefix "\\\\?\\" function doesn't support absolute (lpstrFile) path with long path out: the path with super prefix "\\\\?\\" will be returned, if selected path is long WinXP-64 and Win10: if no filters, the system shows all files. but DOCs say: If all three members are zero or NULL, the system does not use any filters and does not show any files in the file list control of the dialog box. in Win7+: GetOpenFileName() and GetSaveFileName() do not support pstrCustomFilter feature anymore */ #ifdef UNDER_CE #define MY_OFN_PROJECT 0x00400000 #define MY_OFN_SHOW_ALL 0x01000000 #endif /* structures OPENFILENAMEW OPENFILENAMEA contain additional members: #if (_WIN32_WINNT >= 0x0500) void *pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions will not work at NT 4.0, if we use sizeof(OPENFILENAME). We try to use reduced structure OPENFILENAME_NT4. */ // #if defined(_WIN64) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500) #if defined(__GNUC__) && (__GNUC__ <= 9) || defined(Z7_OLD_WIN_SDK) #ifndef _UNICODE #define my_compatib_OPENFILENAMEA OPENFILENAMEA #endif #define my_compatib_OPENFILENAMEW OPENFILENAMEW // MinGW doesn't support some required macros. So we define them here: #ifndef CDSIZEOF_STRUCT #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) #endif #ifndef _UNICODE #ifndef OPENFILENAME_SIZE_VERSION_400A #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) #endif #endif #ifndef OPENFILENAME_SIZE_VERSION_400W #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) #endif #ifndef _UNICODE #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A #endif #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W #else #ifndef _UNICODE #define my_compatib_OPENFILENAMEA OPENFILENAME_NT4A #define my_compatib_OPENFILENAMEA_size sizeof(my_compatib_OPENFILENAMEA) #endif #define my_compatib_OPENFILENAMEW OPENFILENAME_NT4W #define my_compatib_OPENFILENAMEW_size sizeof(my_compatib_OPENFILENAMEW) #endif /* #elif defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) // || !defined(WINVER) #ifndef _UNICODE #define my_compatib_OPENFILENAMEA OPENFILENAMEA #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) #endif #define my_compatib_OPENFILENAMEW OPENFILENAMEW #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) #else #endif */ #ifndef _UNICODE #define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } #endif bool CCommonDialogInfo::CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters) { /* GetSaveFileName() and GetOpenFileName() could change current dir, if OFN_NOCHANGEDIR is not used. We can restore current dir manually, if it's required. 22.02: we use OFN_NOCHANGEDIR. So we don't need to restore current dir manually. */ // NFile::NDir::CCurrentDirRestorer curDirRestorer; #ifndef _UNICODE if (!g_IsNT) { AString tempPath; AStringVector f; unsigned i; for (i = 0; i < filters.Size(); i++) f.Add(GetSystemString(filters[i])); unsigned size = f.Size() + 1; for (i = 0; i < f.Size(); i++) size += f[i].Len(); CObjArray filterBuf(size); // memset(filterBuf, 0, size * sizeof(char)); { char *dest = filterBuf; for (i = 0; i < f.Size(); i++) { const AString &s = f[i]; MyStringCopy(dest, s); dest += s.Len() + 1; } *dest = 0; } my_compatib_OPENFILENAMEA p; memset(&p, 0, sizeof(p)); p.lStructSize = my_compatib_OPENFILENAMEA_size; p.hwndOwner = hwndOwner; if (size > 1) { p.lpstrFilter = filterBuf; p.nFilterIndex = (DWORD)(FilterIndex + 1); } CONV_U_To_A(p.lpstrInitialDir, lpstrInitialDir, initialDir_a) CONV_U_To_A(p.lpstrTitle, lpstrTitle, title_a) const AString filePath_a = GetSystemString(FilePath); const unsigned bufSize = MAX_PATH * 8 + filePath_a.Len() + initialDir_a.Len(); p.nMaxFile = bufSize; p.lpstrFile = tempPath.GetBuf(bufSize); MyStringCopy(p.lpstrFile, filePath_a); p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; const BOOL b = SaveMode ? ::GetSaveFileNameA((LPOPENFILENAMEA)(void *)&p) : ::GetOpenFileNameA((LPOPENFILENAMEA)(void *)&p); if (!b) return false; { tempPath.ReleaseBuf_CalcLen(bufSize); FilePath = GetUnicodeString(tempPath); FilterIndex = (int)p.nFilterIndex - 1; return true; } } else #endif { UString tempPath; unsigned size = filters.Size() + 1; unsigned i; for (i = 0; i < filters.Size(); i++) size += filters[i].Len(); CObjArray filterBuf(size); // memset(filterBuf, 0, size * sizeof(wchar_t)); { wchar_t *dest = filterBuf; for (i = 0; i < filters.Size(); i++) { const UString &s = filters[i]; MyStringCopy(dest, s); dest += s.Len() + 1; } *dest = 0; // if ((unsigned)(dest + 1 - filterBuf) != size) return false; } my_compatib_OPENFILENAMEW p; memset(&p, 0, sizeof(p)); p.lStructSize = my_compatib_OPENFILENAMEW_size; p.hwndOwner = hwndOwner; if (size > 1) { p.lpstrFilter = filterBuf; p.nFilterIndex = (DWORD)(FilterIndex + 1); } unsigned bufSize = MAX_PATH * 8 + FilePath.Len(); if (lpstrInitialDir) { p.lpstrInitialDir = lpstrInitialDir; bufSize += MyStringLen(lpstrInitialDir); } p.nMaxFile = bufSize; p.lpstrFile = tempPath.GetBuf(bufSize); MyStringCopy(p.lpstrFile, FilePath); p.lpstrTitle = lpstrTitle; p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR // | OFN_FORCESHOWHIDDEN // Win10 shows hidden items even without this flag // | OFN_PATHMUSTEXIST #ifdef UNDER_CE | (OpenFolderMode ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0) #endif ; const BOOL b = SaveMode ? ::GetSaveFileNameW((LPOPENFILENAMEW)(void *)&p) : ::GetOpenFileNameW((LPOPENFILENAMEW)(void *)&p); /* DOCs: lpstrFile : if the buffer is too small, then: - the function returns FALSE - the CommDlgExtendedError() returns FNERR_BUFFERTOOSMALL - the first two bytes of the lpstrFile buffer contain the required size, in bytes or characters. */ if (!b) return false; { tempPath.ReleaseBuf_CalcLen(bufSize); FilePath = tempPath; FilterIndex = (int)p.nFilterIndex - 1; return true; } } } } tmp41wklro_/CPP/Windows/CommonDialog.h0000444000175000001440000000200314357314620020736 0ustar nabijaczleweliusers// Windows/CommonDialog.h #ifndef ZIP7_INC_WINDOWS_COMMON_DIALOG_H #define ZIP7_INC_WINDOWS_COMMON_DIALOG_H #include "../Common/MyString.h" namespace NWindows { struct CCommonDialogInfo { /* (FilterIndex == -1) means no selected filter. and (-1) also is reserved for unsupported custom filter. if (FilterIndex >= 0), then FilterIndex is index of filter */ int FilterIndex; // [in / out] bool SaveMode; #ifdef UNDER_CE bool OpenFolderMode; #endif HWND hwndOwner; // LPCWSTR lpstrInitialDir; LPCWSTR lpstrTitle; UString FilePath; // [in / out] CCommonDialogInfo() { FilterIndex = -1; SaveMode = false; #ifdef UNDER_CE OpenFolderMode = false; #endif hwndOwner = NULL; // lpstrInitialDir = NULL; lpstrTitle = NULL; } /* (filters) : 2 sequential vector strings (Description, Masks) represent each filter */ bool CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters); }; } #endif tmp41wklro_/CPP/Windows/Control/0000700000175000001440000000000014706260545017636 5ustar nabijaczleweliuserstmp41wklro_/CPP/Windows/Control/ComboBox.cpp0000444000175000001440000000265114362320500022050 0ustar nabijaczleweliusers// Windows/Control/ComboBox.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif #include "ComboBox.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NControl { LRESULT CComboBox::GetLBText(int index, CSysString &s) { s.Empty(); LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character if (len == CB_ERR) return len; LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len)); if (len2 == CB_ERR) return len; if (len > len2) len = len2; s.ReleaseBuf_CalcLen((unsigned)len); return len; } #ifndef _UNICODE LRESULT CComboBox::AddString(LPCWSTR s) { if (g_IsNT) return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s); return AddString(GetSystemString(s)); } LRESULT CComboBox::GetLBText(int index, UString &s) { s.Empty(); if (g_IsNT) { LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY_int_TO_WPARAM(index), 0); if (len == CB_ERR) return len; LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY_int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len)); if (len2 == CB_ERR) return len; if (len > len2) len = len2; s.ReleaseBuf_CalcLen((unsigned)len); return len; } AString sa; const LRESULT len = GetLBText(index, sa); if (len == CB_ERR) return len; s = GetUnicodeString(sa); return (LRESULT)s.Len(); } #endif }} tmp41wklro_/CPP/Windows/Control/ComboBox.h0000444000175000001440000000565014405100160021513 0ustar nabijaczleweliusers// Windows/Control/ComboBox.h #ifndef ZIP7_INC_WINDOWS_CONTROL_COMBOBOX_H #define ZIP7_INC_WINDOWS_CONTROL_COMBOBOX_H #include "../../Common/MyWindows.h" #include #include "../Window.h" namespace NWindows { namespace NControl { class CComboBox: public CWindow { public: void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); } LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); } #ifndef _UNICODE LRESULT AddString(LPCWSTR s); #endif /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); } LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); } /* If no item is selected, it returns CB_ERR (-1) */ int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); } /* If an error occurs, it is CB_ERR (-1) */ int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); } LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY_int_TO_WPARAM(index), 0); } LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY_int_TO_WPARAM(index), (LPARAM)s); } LRESULT GetLBText(int index, CSysString &s); #ifndef _UNICODE LRESULT GetLBText(int index, UString &s); #endif LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY_int_TO_WPARAM(index), lParam); } LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY_int_TO_WPARAM(index), 0); } LRESULT GetItemData(unsigned index) { return SendMsg(CB_GETITEMDATA, index, 0); } LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } }; #ifndef UNDER_CE class CComboBoxEx: public CComboBox { public: bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } /* Returns: an INT value that represents the number of items remaining in the control. If (index) is invalid, the message returns CB_ERR. */ LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY_int_TO_WPARAM(index), 0); } LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); } #ifndef _UNICODE LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); } #endif LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); } DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, (LPARAM)exStyle); } HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); } HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } }; #endif }} #endif tmp41wklro_/CPP/Windows/Control/CommandBar.h0000444000175000001440000000443714405053100022011 0ustar nabijaczleweliusers// Windows/Control/CommandBar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_COMMANDBAR_H #define ZIP7_INC_WINDOWS_CONTROL_COMMANDBAR_H #ifdef UNDER_CE #include "../../Common/MyWindows.h" #include #include "../Window.h" namespace NWindows { namespace NControl { class CCommandBar: public NWindows::CWindow { public: bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar) { _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar); return (_window != NULL); } // Macros // void Destroy() { CommandBar_Destroy(_window); } // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } // bool InsertButton(unsigned iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } // BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } // bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); } // int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); } bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); } HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); } int Height() { return CommandBar_Height(_window); } HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); } bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); } bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); } bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); } // CE 4.0 void AlignAdornments() { CommandBar_AlignAdornments(_window); } }; }} #endif #endif tmp41wklro_/CPP/Windows/Control/Dialog.cpp0000444000175000001440000002741214572037240021552 0ustar nabijaczleweliusers// Windows/Control/Dialog.cpp #include "StdAfx.h" // #include "../../Windows/DLL.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif #include "Dialog.h" extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NControl { static #ifdef Z7_OLD_WIN_SDK BOOL #else INT_PTR #endif APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) { CWindow tempDialog(dialogHWND); if (message == WM_INITDIALOG) tempDialog.SetUserDataLongPtr(lParam); CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); if (dialog == NULL) return FALSE; if (message == WM_INITDIALOG) dialog->Attach(dialogHWND); /* MSDN: The dialog box procedure should return TRUE - if it processed the message FALSE - if it did not process the message If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message. */ try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } catch(...) { return TRUE; } } bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return OnInit(); case WM_COMMAND: return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam); case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam); case WM_TIMER: return OnTimer(wParam, lParam); case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); case WM_DESTROY: return OnDestroy(); case WM_HELP: OnHelp(); return true; /* OnHelp( #ifdef UNDER_CE (void *) #else (LPHELPINFO) #endif lParam); return true; */ default: return false; } } /* bool CDialog::OnCommand2(WPARAM wParam, LPARAM lParam) { return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam); } */ bool CDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam) { if (code == BN_CLICKED) return OnButtonClicked(itemID, (HWND)lParam); return false; } bool CDialog::OnButtonClicked(unsigned buttonID, HWND /* buttonHWND */) { switch (buttonID) { case IDOK: OnOK(); break; case IDCANCEL: OnCancel(); break; case IDCLOSE: OnClose(); break; case IDCONTINUE: OnContinue(); break; case IDHELP: OnHelp(); break; default: return false; } return true; } #ifndef UNDER_CE /* in win2000/win98 : monitor functions are supported. We need dynamic linking, if we want nt4/win95 support in program. Even if we compile the code with low (WINVER) value, we still want to use monitor functions. So we declare missing functions here */ // #if (WINVER < 0x0500) #ifndef MONITOR_DEFAULTTOPRIMARY extern "C" { DECLARE_HANDLE(HMONITOR); #define MONITOR_DEFAULTTOPRIMARY 0x00000001 typedef struct tagMONITORINFO { DWORD cbSize; RECT rcMonitor; RECT rcWork; DWORD dwFlags; } MONITORINFO, *LPMONITORINFO; WINUSERAPI HMONITOR WINAPI MonitorFromWindow(HWND hwnd, DWORD dwFlags); WINUSERAPI BOOL WINAPI GetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpmi); } #endif #endif static bool GetWorkAreaRect(RECT *rect, HWND hwnd) { if (hwnd) { #ifndef UNDER_CE /* MonitorFromWindow() is supported in Win2000+ MonitorFromWindow() : retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle of a specified window. dwFlags: Determines the function's return value if the window does not intersect any display monitor. MONITOR_DEFAULTTONEAREST : Returns display that is nearest to the window. MONITOR_DEFAULTTONULL : Returns NULL. MONITOR_DEFAULTTOPRIMARY : Returns the primary display monitor. */ const HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); if (hmon) { MONITORINFO mi; memset(&mi, 0, sizeof(mi)); mi.cbSize = sizeof(mi); if (GetMonitorInfoA(hmon, &mi)) { *rect = mi.rcWork; return true; } } #endif } /* Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen not obscured by the system taskbar or by application desktop toolbars. Any DPI virtualization mode of the caller has no effect on this output. */ return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0)); } bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd) { // it returns for system font. Real font uses another values const LONG v = GetDialogBaseUnits(); const int x = LOWORD(v); const int y = HIWORD(v); RECT rect; GetWorkAreaRect(&rect, hwnd); const int wx = RECT_SIZE_X(rect); const int wy = RECT_SIZE_Y(rect); return xSize / 4 * x <= wx && ySize / 8 * y <= wy; } bool CDialog::GetMargins(int margin, int &x, int &y) { x = margin; y = margin; RECT rect; rect.left = 0; rect.top = 0; rect.right = margin; rect.bottom = margin; if (!MapRect(&rect)) return false; x = rect.right - rect.left; y = rect.bottom - rect.top; return true; } int CDialog::Units_To_Pixels_X(int units) { RECT rect; rect.left = 0; rect.top = 0; rect.right = units; rect.bottom = units; if (!MapRect(&rect)) return units * 3 / 2; return rect.right - rect.left; } bool CDialog::GetItemSizes(unsigned id, int &x, int &y) { RECT rect; if (!::GetWindowRect(GetItem(id), &rect)) return false; x = RECT_SIZE_X(rect); y = RECT_SIZE_Y(rect); return true; } void CDialog::GetClientRectOfItem(unsigned id, RECT &rect) { ::GetWindowRect(GetItem(id), &rect); ScreenToClient(&rect); } bool CDialog::MoveItem(unsigned id, int x, int y, int width, int height, bool repaint) { return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); } /* typedef BOOL (WINAPI * Func_DwmGetWindowAttribute)( HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute); static bool GetWindowsRect_DWM(HWND hwnd, RECT *rect) { // dll load and free is too slow : 300 calls in second. NDLL::CLibrary dll; if (!dll.Load(FTEXT("dwmapi.dll"))) return false; Func_DwmGetWindowAttribute f = (Func_DwmGetWindowAttribute)dll.GetProc("DwmGetWindowAttribute" ); if (f) { #define MY__DWMWA_EXTENDED_FRAME_BOUNDS 9 // 30000 per second RECT r; if (f(hwnd, MY__DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK) { *rect = r; return true; } } return false; } */ static bool IsRect_Small_Inside_Big(const RECT &sm, const RECT &big) { return sm.left >= big.left && sm.right <= big.right && sm.top >= big.top && sm.bottom <= big.bottom; } static bool AreRectsOverlapped(const RECT &r1, const RECT &r2) { return r1.left < r2.right && r1.right > r2.left && r1.top < r2.bottom && r1.bottom > r2.top; } static bool AreRectsEqual(const RECT &r1, const RECT &r2) { return r1.left == r2.left && r1.right == r2.right && r1.top == r2.top && r1.bottom == r2.bottom; } void CDialog::NormalizeSize(bool fullNormalize) { RECT workRect; if (!GetWorkAreaRect(&workRect, *this)) return; RECT rect; if (!GetWindowRect(&rect)) return; int xs = RECT_SIZE_X(rect); int ys = RECT_SIZE_Y(rect); // we don't want to change size using workRect, if window is outside of WorkArea if (!AreRectsOverlapped(rect, workRect)) return; /* here rect and workRect are overlapped, but it can be false overlapping of small shadow when window in another display. */ const int xsW = RECT_SIZE_X(workRect); const int ysW = RECT_SIZE_Y(workRect); if (xs <= xsW && ys <= ysW) return; // size of window is OK if (fullNormalize) { Show(SW_SHOWMAXIMIZED); return; } int x = workRect.left; int y = workRect.top; if (xs < xsW) x += (xsW - xs) / 2; else xs = xsW; if (ys < ysW) y += (ysW - ys) / 2; else ys = ysW; Move(x, y, xs, ys, true); } void CDialog::NormalizePosition() { RECT workRect; if (!GetWorkAreaRect(&workRect, *this)) return; RECT rect2 = workRect; bool useWorkArea = true; const HWND parentHWND = GetParent(); if (parentHWND) { RECT workRectParent; if (!GetWorkAreaRect(&workRectParent, parentHWND)) return; // if windows are in different monitors, we use only workArea of current window if (AreRectsEqual(workRectParent, workRect)) { // RECT rect3; if (GetWindowsRect_DWM(parentHWND, &rect3)) {} CWindow wnd(parentHWND); if (wnd.GetWindowRect(&rect2)) { // it's same monitor. So we try to use parentHWND rect. /* we don't want to change position, if parent window is not inside work area. In Win10 : parent window rect is 8 pixels larger for each corner than window size for shadow. In maximize mode : window is outside of workRect. if parent window is inside workRect, we will use parent window instead of workRect */ if (IsRect_Small_Inside_Big(rect2, workRect)) useWorkArea = false; } } } RECT rect; if (!GetWindowRect(&rect)) return; if (useWorkArea) { // we don't want to move window, if it's already inside. if (IsRect_Small_Inside_Big(rect, workRect)) return; // we don't want to move window, if it's outside of workArea if (!AreRectsOverlapped(rect, workRect)) return; rect2 = workRect; } { const int xs = RECT_SIZE_X(rect); const int ys = RECT_SIZE_Y(rect); const int xs2 = RECT_SIZE_X(rect2); const int ys2 = RECT_SIZE_Y(rect2); // we don't want to change position if parent is smaller. if (xs <= xs2 && ys <= ys2) { const int x = rect2.left + (xs2 - xs) / 2; const int y = rect2.top + (ys2 - ys) / 2; if (x != rect.left || y != rect.top) Move(x, y, xs, ys, true); // SetWindowPos(*this, HWND_TOP, x, y, 0, 0, SWP_NOSIZE); return; } } } bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow) { const HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); if (!aHWND) return false; Attach(aHWND); return true; } INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow) { return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); } #ifndef _UNICODE bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow) { HWND aHWND; if (g_IsNT) aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); else { AString name; LPCSTR templateNameA; if (IS_INTRESOURCE(templateName)) templateNameA = (LPCSTR)templateName; else { name = GetSystemString(templateName); templateNameA = name; } aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); } if (aHWND == 0) return false; Attach(aHWND); return true; } INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow) { if (g_IsNT) return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); AString name; LPCSTR templateNameA; if (IS_INTRESOURCE(templateName)) templateNameA = (LPCSTR)templateName; else { name = GetSystemString(templateName); templateNameA = name; } return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); } #endif }} tmp41wklro_/CPP/Windows/Control/Dialog.h0000444000175000001440000001655014615132640021216 0ustar nabijaczleweliusers// Windows/Control/Dialog.h #ifndef ZIP7_INC_WINDOWS_CONTROL_DIALOG_H #define ZIP7_INC_WINDOWS_CONTROL_DIALOG_H #include "../Window.h" namespace NWindows { namespace NControl { #ifndef IDCONTINUE #define IDCONTINUE 11 #endif class CDialog: public CWindow { // Z7_CLASS_NO_COPY(CDialog) public: CDialog(HWND wnd = NULL): CWindow(wnd) {} virtual ~CDialog() {} HWND GetItem(unsigned itemID) const { return GetDlgItem(_window, (int)itemID); } bool EnableItem(unsigned itemID, bool enable) const { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); } bool ShowItem(unsigned itemID, int cmdShow) const { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); } bool ShowItem_Bool(unsigned itemID, bool show) const { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); } bool HideItem(unsigned itemID) const { return ShowItem(itemID, SW_HIDE); } bool SetItemText(unsigned itemID, LPCTSTR s) { return BOOLToBool(SetDlgItemText(_window, (int)itemID, s)); } bool SetItemTextA(unsigned itemID, LPCSTR s) { return BOOLToBool(SetDlgItemTextA(_window, (int)itemID, s)); } bool SetItemText_Empty(unsigned itemID) { return SetItemText(itemID, TEXT("")); } #ifndef _UNICODE bool SetItemText(unsigned itemID, LPCWSTR s) { CWindow window(GetItem(itemID)); return window.SetText(s); } #endif UINT GetItemText(unsigned itemID, LPTSTR string, unsigned maxCount) { return GetDlgItemText(_window, (int)itemID, string, (int)maxCount); } #ifndef _UNICODE /* bool GetItemText(unsigned itemID, LPWSTR string, int maxCount) { CWindow window(GetItem(unsigned)); return window.GetText(string, maxCount); } */ #endif bool GetItemText(unsigned itemID, UString &s) { CWindow window(GetItem(itemID)); return window.GetText(s); } /* bool SetItemInt(unsigned itemID, UINT value, bool isSigned) { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, BoolToBOOL(isSigned))); } */ bool SetItemUInt(unsigned itemID, UINT value) { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, FALSE)); } /* bool GetItemInt(unsigned itemID, bool isSigned, UINT &value) { BOOL result; value = GetDlgItemInt(_window, (int)itemID, &result, BoolToBOOL(isSigned)); return BOOLToBool(result); } */ bool GetItemUInt(unsigned itemID, UINT &value) { BOOL result; value = GetDlgItemInt(_window, (int)itemID, &result, FALSE); return BOOLToBool(result); } HWND GetNextGroupItem(HWND control, bool previous) { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); } HWND GetNextTabItem(HWND control, bool previous) { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); } LRESULT SendMsg_NextDlgCtl(WPARAM wParam, LPARAM lParam) { return SendMsg(WM_NEXTDLGCTL, wParam, lParam); } LRESULT SendMsg_NextDlgCtl_HWND(HWND hwnd) { return SendMsg_NextDlgCtl((WPARAM)hwnd, TRUE); } LRESULT SendMsg_NextDlgCtl_CtlId(unsigned id) { return SendMsg_NextDlgCtl_HWND(GetItem(id)); } LRESULT SendMsg_NextDlgCtl_Next() { return SendMsg_NextDlgCtl(0, FALSE); } LRESULT SendMsg_NextDlgCtl_Prev() { return SendMsg_NextDlgCtl(1, FALSE); } bool MapRect(LPRECT rect) { return BOOLToBool(MapDialogRect(_window, rect)); } bool IsMessage(LPMSG message) { return BOOLToBool(IsDialogMessage(_window, message)); } LRESULT SendItemMessage(unsigned itemID, UINT message, WPARAM wParam, LPARAM lParam) { return SendDlgItemMessage(_window, (int)itemID, message, wParam, lParam); } bool CheckButton(unsigned buttonID, UINT checkState) { return BOOLToBool(CheckDlgButton(_window, (int)buttonID, checkState)); } bool CheckButton(unsigned buttonID, bool checkState) { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); } UINT IsButtonChecked_BST(unsigned buttonID) const { return IsDlgButtonChecked(_window, (int)buttonID); } bool IsButtonCheckedBool(unsigned buttonID) const { return (IsButtonChecked_BST(buttonID) == BST_CHECKED); } bool CheckRadioButton(unsigned firstButtonID, unsigned lastButtonID, unsigned checkButtonID) { return BOOLToBool(::CheckRadioButton(_window, (int)firstButtonID, (int)lastButtonID, (int)checkButtonID)); } virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); virtual bool OnInit() { return true; } // virtual bool OnCommand2(WPARAM wParam, LPARAM lParam); virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam); virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } virtual bool OnDestroy() { return false; } /* #ifdef UNDER_CE virtual void OnHelp(void *) { OnHelp(); } #else virtual void OnHelp(LPHELPINFO) { OnHelp(); } #endif */ virtual void OnHelp() {} virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND); virtual void OnOK() {} virtual void OnContinue() {} virtual void OnCancel() {} virtual void OnClose() {} virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; } virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; } LONG_PTR SetMsgResult(LONG_PTR newLongPtr ) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); } bool GetMargins(int margin, int &x, int &y); int Units_To_Pixels_X(int units); bool GetItemSizes(unsigned id, int &x, int &y); void GetClientRectOfItem(unsigned id, RECT &rect); bool MoveItem(unsigned id, int x, int y, int width, int height, bool repaint = true); bool MoveItem_RECT(unsigned id, const RECT &r, bool repaint = true) { return MoveItem(id, r.left, r.top, RECT_SIZE_X(r), RECT_SIZE_Y(r), repaint); } void NormalizeSize(bool fullNormalize = false); void NormalizePosition(); }; class CModelessDialog: public CDialog { public: bool Create(LPCTSTR templateName, HWND parentWindow); bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } #ifndef _UNICODE bool Create(LPCWSTR templateName, HWND parentWindow); #endif virtual void OnOK() Z7_override { Destroy(); } virtual void OnContinue() Z7_override { Destroy(); } virtual void OnCancel() Z7_override { Destroy(); } virtual void OnClose() Z7_override { Destroy(); } }; class CModalDialog: public CDialog { public: INT_PTR Create(LPCTSTR templateName, HWND parentWindow); INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } #ifndef _UNICODE INT_PTR Create(LPCWSTR templateName, HWND parentWindow); #endif bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); } virtual void OnOK() Z7_override { End(IDOK); } virtual void OnContinue() Z7_override { End(IDCONTINUE); } virtual void OnCancel() Z7_override { End(IDCANCEL); } virtual void OnClose() Z7_override { End(IDCLOSE); } }; class CDialogChildControl: public NWindows::CWindow { // unsigned m_ID; public: void Init(const NWindows::NControl::CDialog &parentDialog, unsigned id) { // m_ID = id; Attach(parentDialog.GetItem(id)); } }; bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd = NULL); }} #endif tmp41wklro_/CPP/Windows/Control/Edit.h0000444000175000001440000000047414357314620020705 0ustar nabijaczleweliusers// Windows/Control/Edit.h #ifndef ZIP7_INC_WINDOWS_CONTROL_EDIT_H #define ZIP7_INC_WINDOWS_CONTROL_EDIT_H #include "../Window.h" namespace NWindows { namespace NControl { class CEdit: public CWindow { public: void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); } }; }} #endif tmp41wklro_/CPP/Windows/Control/ImageList.cpp0000444000175000001440000000020712450565044022223 0ustar nabijaczleweliusers// Windows/Control/ImageList.cpp #include "StdAfx.h" #include "ImageList.h" namespace NWindows { namespace NControl { }} tmp41wklro_/CPP/Windows/Control/ImageList.h0000444000175000001440000000452514357314620021677 0ustar nabijaczleweliusers// Windows/Control/ImageList.h #ifndef ZIP7_INC_WINDOWS_CONTROL_IMAGE_LIST_H #define ZIP7_INC_WINDOWS_CONTROL_IMAGE_LIST_H #include #include "../Defs.h" namespace NWindows { namespace NControl { class CImageList { HIMAGELIST m_Object; public: operator HIMAGELIST() const {return m_Object; } CImageList(): m_Object(NULL) {} bool Attach(HIMAGELIST imageList) { if (imageList == NULL) return false; m_Object = imageList; return true; } HIMAGELIST Detach() { HIMAGELIST imageList = m_Object; m_Object = NULL; return imageList; } bool Create(int width, int height, UINT flags, int initialNumber, int grow) { HIMAGELIST a = ImageList_Create(width, height, flags, initialNumber, grow); if (a == NULL) return false; return Attach(a); } bool Destroy() // DeleteImageList() in MFC { if (m_Object == NULL) return false; return BOOLToBool(ImageList_Destroy(Detach())); } ~CImageList() { Destroy(); } int GetImageCount() const { return ImageList_GetImageCount(m_Object); } bool GetImageInfo(int index, IMAGEINFO* imageInfo) const { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); } int Add(HBITMAP hbmImage, HBITMAP hbmMask = NULL) { return ImageList_Add(m_Object, hbmImage, hbmMask); } int AddMasked(HBITMAP hbmImage, COLORREF mask) { return ImageList_AddMasked(m_Object, hbmImage, mask); } int AddIcon(HICON icon) { return ImageList_AddIcon(m_Object, icon); } int Replace(int index, HICON icon) { return ImageList_ReplaceIcon(m_Object, index, icon); } // If index is -1, the function removes all images. bool Remove(int index) { return BOOLToBool(ImageList_Remove(m_Object, index)); } bool RemoveAll() { return BOOLToBool(ImageList_RemoveAll(m_Object)); } HICON ExtractIcon(int index) { return ImageList_ExtractIcon(NULL, m_Object, index); } HICON GetIcon(int index, UINT flags) { return ImageList_GetIcon(m_Object, index, flags); } bool GetIconSize(int &width, int &height) const { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); } bool SetIconSize(int width, int height) { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); } }; }} #endif tmp41wklro_/CPP/Windows/Control/ListView.cpp0000444000175000001440000001010614405053100022075 0ustar nabijaczleweliusers// Windows/Control/ListView.cpp #include "StdAfx.h" #include "ListView.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NControl { bool CListView::CreateEx(DWORD exStyle, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam) { return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); } /* note: LVITEM and LVCOLUMN structures contain optional fields depending from preprocessor macros: #if (_WIN32_IE >= 0x0300) #if (_WIN32_WINNT >= 0x0501) #if (_WIN32_WINNT >= 0x0600) */ bool CListView::GetItemParam(unsigned index, LPARAM ¶m) const { LVITEM item; item.iItem = (int)index; item.iSubItem = 0; item.mask = LVIF_PARAM; const bool res = GetItem(&item); param = item.lParam; return res; } int CListView::InsertColumn(unsigned columnIndex, LPCTSTR text, int width) { LVCOLUMN ci; ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; ci.pszText = (LPTSTR)(void *)text; ci.iSubItem = (int)columnIndex; ci.cx = width; return InsertColumn(columnIndex, &ci); } int CListView::InsertItem(unsigned index, LPCTSTR text) { LVITEM item; item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = (int)index; item.lParam = (LPARAM)index; item.pszText = (LPTSTR)(void *)text; item.iSubItem = 0; return InsertItem(&item); } int CListView::SetSubItem(unsigned index, unsigned subIndex, LPCTSTR text) { LVITEM item; item.mask = LVIF_TEXT; item.iItem = (int)index; item.pszText = (LPTSTR)(void *)text; item.iSubItem = (int)subIndex; return SetItem(&item); } #ifndef _UNICODE int CListView::InsertColumn(unsigned columnIndex, LPCWSTR text, int width) { LVCOLUMNW ci; ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; ci.pszText = (LPWSTR)(void *)text; ci.iSubItem = (int)columnIndex; ci.cx = width; return InsertColumn(columnIndex, &ci); } int CListView::InsertItem(unsigned index, LPCWSTR text) { LVITEMW item; item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = (int)index; item.lParam = (LPARAM)index; item.pszText = (LPWSTR)(void *)text; item.iSubItem = 0; return InsertItem(&item); } int CListView::SetSubItem(unsigned index, unsigned subIndex, LPCWSTR text) { LVITEMW item; item.mask = LVIF_TEXT; item.iItem = (int)index; item.pszText = (LPWSTR)(void *)text; item.iSubItem = (int)subIndex; return SetItem(&item); } #endif static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { CWindow window(hwnd); CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr()); if (w == NULL) return 0; return w->OnMessage(message, wParam, lParam); } LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { #ifndef _UNICODE if (g_IsNT) return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); else #endif return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); } void CListView2::SetWindowProc() { SetUserDataLongPtr((LONG_PTR)this); #ifndef _UNICODE if (g_IsNT) _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); else #endif _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); } /* LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res = CListView2::OnMessage(message, wParam, lParam); if (message == WM_GETDLGCODE) { // when user presses RETURN, windows sends default (first) button command to parent dialog. // we disable this: MSG *msg = (MSG *)lParam; WPARAM key = wParam; bool change = false; if (msg) { if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) change = true; } else if (wParam == VK_RETURN) change = true; if (change) res |= DLGC_WANTALLKEYS; } return res; } */ }} tmp41wklro_/CPP/Windows/Control/ListView.h0000444000175000001440000001551014405107200021547 0ustar nabijaczleweliusers// Windows/Control/ListView.h #ifndef ZIP7_INC_WINDOWS_CONTROL_LISTVIEW_H #define ZIP7_INC_WINDOWS_CONTROL_LISTVIEW_H #include "../../Common/MyWindows.h" #include #include "../Window.h" namespace NWindows { namespace NControl { class CListView: public NWindows::CWindow { public: bool CreateEx(DWORD exStyle, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam); void SetUnicodeFormat() { #ifndef UNDER_CE ListView_SetUnicodeFormat(_window, TRUE); #endif } bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); } bool DeleteColumn(unsigned columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); } int InsertColumn(unsigned columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); } int InsertColumn(unsigned columnIndex, LPCTSTR text, int width); bool SetColumnOrderArray(unsigned count, const int *columns) { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); } /* int GetNumColumns() { HWND header = ListView_GetHeader(_window); if (!header) return -1; return Header_GetItemCount(header); } */ int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); } int InsertItem(unsigned index, LPCTSTR text); bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); } int SetSubItem(unsigned index, unsigned subIndex, LPCTSTR text); #ifndef _UNICODE int InsertColumn(unsigned columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } int InsertColumn(unsigned columnIndex, LPCWSTR text, int width); int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); } int InsertItem(unsigned index, LPCWSTR text); bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); } int SetSubItem(unsigned index, unsigned subIndex, LPCWSTR text); #endif bool DeleteItem(unsigned itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); } UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); } int GetItemCount() const { return ListView_GetItemCount(_window); } INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); } void SetItemCount(unsigned numItems) { ListView_SetItemCount(_window, numItems); } void SetItemCountEx(unsigned numItems, DWORD flags) { ListView_SetItemCountEx(_window, numItems, flags); } /* startIndex : The index of the item with which to begin the search, or -1 to find the first item that matches the specified flags. The specified item itself is excluded from the search. */ int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); } int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); } int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); } bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); } bool GetItemParam(unsigned itemIndex, LPARAM ¶m) const; /* void GetItemText(unsigned itemIndex, unsigned subItemIndex, LPTSTR text, unsigned textSizeMax) const { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax) } */ bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam) { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); } // If (index == -1), then the state change is applied to all items. void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask) } void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); } void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); } void SelectAll() { SetItemState_Selected(-1); } void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); } UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); } bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; } bool GetColumn(unsigned columnIndex, LVCOLUMN* columnInfo) const { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); } HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType) { return ListView_SetImageList(_window, imageList, imageListType); } // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3) DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); } void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); } void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); } void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)) } bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); } bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); } bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); } HWND GetEditControl() { return ListView_GetEditControl(_window) ; } HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; } bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); } bool RedrawAllItems() { if (GetItemCount() > 0) return RedrawItems(0, GetItemCount() - 1); return true; } bool RedrawItem(int index) { return RedrawItems(index, index); } int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); } COLORREF GetBkColor() { return ListView_GetBkColor(_window); } bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); } bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); } }; class CListView2: public CListView { WNDPROC _origWindowProc; // ~CListView2() ZIP7_eq_delete; public: virtual ~CListView2() {} CListView2() {} void SetWindowProc(); virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; /* class CListView3: public CListView2 { public: virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; */ }} #endif tmp41wklro_/CPP/Windows/Control/ProgressBar.h0000444000175000001440000000251614362320500022236 0ustar nabijaczleweliusers// Windows/Control/ProgressBar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_PROGRESSBAR_H #define ZIP7_INC_WINDOWS_CONTROL_PROGRESSBAR_H #include "../../Common/MyWindows.h" #include #include "../Window.h" namespace NWindows { namespace NControl { class CProgressBar: public CWindow { public: LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, (unsigned)pos, 0); } // LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); } // UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); } // LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, (unsigned)minValue, (LPARAM)(unsigned)maxValue); } // int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); } // LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); } // INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } #ifndef UNDER_CE COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, (LPARAM)color); } COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, (LPARAM)color); } #endif }; }} #endif tmp41wklro_/CPP/Windows/Control/PropertyPage.cpp0000444000175000001440000001113414504607020022760 0ustar nabijaczleweliusers// Windows/Control/PropertyPage.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif #include "PropertyPage.h" extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NControl { static #ifdef Z7_OLD_WIN_SDK BOOL #else INT_PTR #endif APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) { CWindow tempDialog(dialogHWND); if (message == WM_INITDIALOG) tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam); CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); if (dialog == NULL) return FALSE; if (message == WM_INITDIALOG) dialog->Attach(dialogHWND); try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } catch(...) { return TRUE; } } bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam) { switch (lParam->code) { case PSN_APPLY: SetMsgResult(OnApply2(LPPSHNOTIFY(lParam))); break; case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive2(LPPSHNOTIFY(lParam)))); break; case PSN_SETACTIVE: SetMsgResult(OnSetActive2(LPPSHNOTIFY(lParam))); break; case PSN_RESET: OnReset2(LPPSHNOTIFY(lParam)); break; case PSN_HELP: OnNotifyHelp2(LPPSHNOTIFY(lParam)); break; default: return false; } return true; } /* PROPSHEETPAGE fields depend from #if (_WIN32_WINNT >= 0x0600) #elif (_WIN32_WINNT >= 0x0501) #elif (_WIN32_IE >= 0x0400) PROPSHEETHEADER fields depend from #if (_WIN32_IE >= 0x0400) */ #if defined(PROPSHEETPAGEA_V1_SIZE) && !defined(Z7_OLD_WIN_SDK) #ifndef _UNICODE #define my_compatib_PROPSHEETPAGEA PROPSHEETPAGEA_V1 #endif #define my_compatib_PROPSHEETPAGEW PROPSHEETPAGEW_V1 #else // for old mingw: #ifndef _UNICODE #define my_compatib_PROPSHEETPAGEA PROPSHEETPAGEA #endif #define my_compatib_PROPSHEETPAGEW PROPSHEETPAGEW #endif INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title) { unsigned i; #ifndef _UNICODE AStringVector titles; for (i = 0; i < pagesInfo.Size(); i++) titles.Add(GetSystemString(pagesInfo[i].Title)); CRecordVector pagesA; #endif CRecordVector pagesW; for (i = 0; i < pagesInfo.Size(); i++) { const CPageInfo &pageInfo = pagesInfo[i]; #ifndef _UNICODE { my_compatib_PROPSHEETPAGEA page; memset(&page, 0, sizeof(page)); page.dwSize = sizeof(page); page.dwFlags = PSP_HASHELP; page.hInstance = g_hInstance; page.pszTemplate = MAKEINTRESOURCEA(pageInfo.ID); // page.pszIcon = NULL; page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; if (!titles[i].IsEmpty()) { page.pszTitle = titles[i]; page.dwFlags |= PSP_USETITLE; } // else page.pszTitle = NULL; page.lParam = (LPARAM)pageInfo.Page; // page.pfnCallback = NULL; pagesA.Add(page); } #endif { my_compatib_PROPSHEETPAGEW page; memset(&page, 0, sizeof(page)); page.dwSize = sizeof(page); page.dwFlags = PSP_HASHELP; page.hInstance = g_hInstance; page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID); // page.pszIcon = NULL; page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; if (!pageInfo.Title.IsEmpty()) { page.pszTitle = pageInfo.Title; page.dwFlags |= PSP_USETITLE; } // else page.pszTitle = NULL; page.lParam = (LPARAM)pageInfo.Page; // page.pfnCallback = NULL; pagesW.Add(page); } } #ifndef _UNICODE if (!g_IsNT) { PROPSHEETHEADERA sheet; sheet.dwSize = sizeof(sheet); sheet.dwFlags = PSH_PROPSHEETPAGE; sheet.hwndParent = hwndParent; sheet.hInstance = g_hInstance; AString titleA (GetSystemString(title)); sheet.pszCaption = titleA; sheet.nPages = pagesA.Size(); sheet.nStartPage = 0; sheet.ppsp = (LPCPROPSHEETPAGEA)(const void *)pagesA.ConstData(); sheet.pfnCallback = NULL; return ::PropertySheetA(&sheet); } else #endif { PROPSHEETHEADERW sheet; sheet.dwSize = sizeof(sheet); sheet.dwFlags = PSH_PROPSHEETPAGE; sheet.hwndParent = hwndParent; sheet.hInstance = g_hInstance; sheet.pszCaption = title; sheet.nPages = pagesW.Size(); sheet.nStartPage = 0; sheet.ppsp = (LPCPROPSHEETPAGEW)(const void *)pagesW.ConstData(); sheet.pfnCallback = NULL; return ::PropertySheetW(&sheet); } } }} tmp41wklro_/CPP/Windows/Control/PropertyPage.h0000444000175000001440000000272014405100160022417 0ustar nabijaczleweliusers// Windows/Control/PropertyPage.h #ifndef ZIP7_INC_WINDOWS_CONTROL_PROPERTYPAGE_H #define ZIP7_INC_WINDOWS_CONTROL_PROPERTYPAGE_H #include "../../Common/MyWindows.h" #include #include "Dialog.h" namespace NWindows { namespace NControl { INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam); class CPropertyPage: public CDialog { public: CPropertyPage(HWND window = NULL): CDialog(window) {} void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); } void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); } virtual bool OnNotify(UINT controlID, LPNMHDR lParam) Z7_override; virtual bool OnKillActive() { return false; } // false = OK virtual bool OnKillActive2(const PSHNOTIFY *) { return OnKillActive(); } virtual LONG OnSetActive() { return false; } // false = OK virtual LONG OnSetActive2(const PSHNOTIFY *) { return OnSetActive(); } virtual LONG OnApply() { return PSNRET_NOERROR; } virtual LONG OnApply2(const PSHNOTIFY *) { return OnApply(); } virtual void OnNotifyHelp() {} virtual void OnNotifyHelp2(const PSHNOTIFY *) { OnNotifyHelp(); } virtual void OnReset() {} virtual void OnReset2(const PSHNOTIFY *) { OnReset(); } }; struct CPageInfo { CPropertyPage *Page; UString Title; UINT ID; }; INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title); }} #endif tmp41wklro_/CPP/Windows/Control/ReBar.h0000444000175000001440000000214014362255360021004 0ustar nabijaczleweliusers// Windows/Control/ReBar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_REBAR_H #define ZIP7_INC_WINDOWS_CONTROL_REBAR_H #include "../Window.h" namespace NWindows { namespace NControl { class CReBar: public NWindows::CWindow { public: bool SetBarInfo(LPREBARINFO barInfo) { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); } bool InsertBand(int index, LPREBARBANDINFO bandInfo) { return LRESULTToBool(SendMsg(RB_INSERTBAND, MY_int_TO_WPARAM(index), (LPARAM)bandInfo)); } bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo) { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } void MaximizeBand(unsigned index, bool ideal) { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } bool SizeToRect(LPRECT rect) { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); } UINT GetHeight() { return (UINT)SendMsg(RB_GETBARHEIGHT); } UINT GetBandCount() { return (UINT)SendMsg(RB_GETBANDCOUNT); } bool DeleteBand(UINT index) { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); } }; }} #endif tmp41wklro_/CPP/Windows/Control/Static.h0000444000175000001440000000143114357314620021241 0ustar nabijaczleweliusers// Windows/Control/Static.h #ifndef ZIP7_INC_WINDOWS_CONTROL_STATIC_H #define ZIP7_INC_WINDOWS_CONTROL_STATIC_H #include "../Window.h" namespace NWindows { namespace NControl { class CStatic: public CWindow { public: HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); } HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); } #ifdef UNDER_CE HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); } HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); } #else HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); } HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); } #endif }; }} #endif tmp41wklro_/CPP/Windows/Control/StatusBar.h0000444000175000001440000000264214362255360021730 0ustar nabijaczleweliusers// Windows/Control/StatusBar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_STATUSBAR_H #define ZIP7_INC_WINDOWS_CONTROL_STATUSBAR_H #include "../Window.h" namespace NWindows { namespace NControl { class CStatusBar: public NWindows::CWindow { public: bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id) { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != NULL; } bool SetText(LPCTSTR text) { return CWindow::SetText(text); } bool SetText(unsigned index, LPCTSTR text, UINT type) { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); } bool SetText(unsigned index, LPCTSTR text) { return SetText(index, text, 0); } #ifndef _UNICODE bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id) { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != NULL; } bool SetText(LPCWSTR text) { return CWindow::SetText(text); } bool SetText(unsigned index, LPCWSTR text, UINT type) { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); } bool SetText(unsigned index, LPCWSTR text) { return SetText(index, text, 0); } #endif bool SetParts(unsigned numParts, const int *edgePostions) { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } void Simple(bool simple) { SendMsg(SB_SIMPLE, (WPARAM)BoolToBOOL(simple), 0); } }; }} #endif tmp41wklro_/CPP/Windows/Control/StdAfx.h0000444000175000001440000000035614360505460021206 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../../Common/Common.h" #endif tmp41wklro_/CPP/Windows/Control/ToolBar.h0000444000175000001440000000256714405053100021352 0ustar nabijaczleweliusers// Windows/Control/ToolBar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_TOOLBAR_H #define ZIP7_INC_WINDOWS_CONTROL_TOOLBAR_H #include "../Window.h" namespace NWindows { namespace NControl { class CToolBar: public NWindows::CWindow { public: void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); } bool GetMaxSize(LPSIZE size) #ifdef UNDER_CE { // maybe it must be fixed for more than 1 buttons const DWORD val = GetButtonSize(); size->cx = LOWORD(val); size->cy = HIWORD(val); return true; } #else { return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size)); } #endif bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } #ifndef _UNICODE bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } #endif }; }} #endif tmp41wklro_/CPP/Windows/Control/Trackbar.h0000444000175000001440000000117314357314620021546 0ustar nabijaczleweliusers// Windows/Control/Trackbar.h #ifndef ZIP7_INC_WINDOWS_CONTROL_TRACKBAR_H #define ZIP7_INC_WINDOWS_CONTROL_TRACKBAR_H #include "../Window.h" namespace NWindows { namespace NControl { class CTrackbar: public CWindow { public: void SetRange(int minimum, int maximum, bool redraw = true) { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } void SetPos(int pos, bool redraw = true) { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); } void SetTicFreq(int freq) { SendMsg(TBM_SETTICFREQ, freq); } int GetPos() { return (int)SendMsg(TBM_GETPOS); } }; }} #endif tmp41wklro_/CPP/Windows/Control/Window2.cpp0000444000175000001440000001200714405026020021663 0ustar nabijaczleweliusers// Windows/Control/Window2.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif #include "Window2.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { #ifndef _UNICODE ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); #endif namespace NControl { #ifdef UNDER_CE #define MY_START_WM_CREATE WM_CREATE #else #define MY_START_WM_CREATE WM_NCCREATE #endif static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, WPARAM wParam, LPARAM lParam) { CWindow tempWindow(aHWND); if (message == MY_START_WM_CREATE) tempWindow.SetUserDataLongPtr((LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams)); CWindow2 *window = (CWindow2 *)(tempWindow.GetUserDataLongPtr()); if (window && message == MY_START_WM_CREATE) window->Attach(aHWND); if (!window) { #ifndef _UNICODE if (g_IsNT) return DefWindowProcW(aHWND, message, wParam, lParam); else #endif return DefWindowProc(aHWND, message, wParam, lParam); } return window->OnMessage(message, wParam, lParam); } bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) { WNDCLASS wc; if (!::GetClassInfo(instance, className, &wc)) { // wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = 0; wc.lpfnWndProc = WindowProcedure; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = instance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = className; if (::RegisterClass(&wc) == 0) return false; } return CWindow::CreateEx(exStyle, className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, this); } #ifndef _UNICODE bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) { bool needRegister; if (g_IsNT) { WNDCLASSW wc; needRegister = ::GetClassInfoW(instance, className, &wc) == 0; } else { WNDCLASSA windowClassA; AString classNameA; LPCSTR classNameP; if (IS_INTRESOURCE(className)) classNameP = (LPCSTR)className; else { classNameA = GetSystemString(className); classNameP = classNameA; } needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0; } if (needRegister) { WNDCLASSW wc; // wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = 0; wc.lpfnWndProc = WindowProcedure; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = instance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = className; if (MyRegisterClass(&wc) == 0) return false; } return CWindow::CreateEx(exStyle, className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, this); } #endif LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam) { #ifndef _UNICODE if (g_IsNT) return DefWindowProcW(_window, message, wParam, lParam); else #endif return DefWindowProc(_window, message, wParam, lParam); } LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { LRESULT result; switch (message) { case WM_CREATE: if (!OnCreate((CREATESTRUCT *)lParam)) return -1; break; case WM_COMMAND: if (OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result)) return result; break; case WM_NOTIFY: if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result)) return result; break; case WM_DESTROY: OnDestroy(); break; case WM_CLOSE: OnClose(); return 0; case WM_SIZE: if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam))) return 0; } return DefProc(message, wParam, lParam); } /* bool CWindow2::OnCommand2(WPARAM wParam, LPARAM lParam, LRESULT &result) { return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result); } */ bool CWindow2::OnCommand(unsigned /* code */, unsigned /* itemID */, LPARAM /* lParam */, LRESULT & /* result */) { return false; // return DefProc(message, wParam, lParam); /* if (code == BN_CLICKED) return OnButtonClicked(itemID, (HWND)lParam); */ } /* bool CDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) { switch (buttonID) { case IDOK: OnOK(); break; case IDCANCEL: OnCancel(); break; case IDHELP: OnHelp(); break; default: return false; } return true; } */ }} tmp41wklro_/CPP/Windows/Control/Window2.h0000444000175000001440000000362514405035040021340 0ustar nabijaczleweliusers// Windows/Control/Window2.h #ifndef ZIP7_INC_WINDOWS_CONTROL_WINDOW2_H #define ZIP7_INC_WINDOWS_CONTROL_WINDOW2_H #include "../Window.h" namespace NWindows { namespace NControl { class CWindow2: public CWindow { // Z7_CLASS_NO_COPY(CWindow2) LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam); public: CWindow2(HWND newWindow = NULL): CWindow(newWindow) {} virtual ~CWindow2() {} bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); #ifndef _UNICODE bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); #endif virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; } // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam); // bool OnCommand2(WPARAM wParam, LPARAM lParam, LRESULT &result); virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam, LRESULT &result); virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; } virtual void OnDestroy() { PostQuitMessage(0); } virtual void OnClose() { Destroy(); } /* virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); } virtual LRESULT OnHelp() {}; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND); virtual void OnOK() {}; virtual void OnCancel() {}; */ LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); } }; }} #endif tmp41wklro_/CPP/Windows/Defs.h0000444000175000001440000000071014364465500017254 0ustar nabijaczleweliusers// Windows/Defs.h #ifndef ZIP7_INC_WINDOWS_DEFS_H #define ZIP7_INC_WINDOWS_DEFS_H #include "../Common/MyWindows.h" #ifdef _WIN32 inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); } #endif inline bool BOOLToBool(BOOL v) { return (v != FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); } #endif tmp41wklro_/CPP/Windows/DLL.cpp0000444000175000001440000000570114554753400017346 0ustar nabijaczleweliusers// Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #ifdef _WIN32 #ifndef _UNICODE extern bool g_IsNT; #endif extern HINSTANCE g_hInstance; namespace NWindows { namespace NDLL { bool CLibrary::Free() throw() { if (_module == NULL) return true; if (!::FreeLibrary(_module)) return false; _module = NULL; return true; } bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw() { if (!Free()) return false; #ifndef _UNICODE if (!g_IsNT) { _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); } else #endif { _module = ::LoadLibraryExW(fs2us(path), NULL, flags); } return (_module != NULL); } bool CLibrary::Load(CFSTR path) throw() { if (!Free()) return false; #ifndef _UNICODE if (!g_IsNT) { _module = ::LoadLibrary(fs2fas(path)); } else #endif { _module = ::LoadLibraryW(fs2us(path)); } return (_module != NULL); } bool MyGetModuleFileName(FString &path) { const HMODULE hModule = g_hInstance; path.Empty(); #ifndef _UNICODE if (!g_IsNT) { TCHAR s[MAX_PATH + 2]; s[0] = 0; const DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { path = fas2fs(s); return true; } } else #endif { WCHAR s[MAX_PATH + 2]; s[0] = 0; const DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { path = us2fs(s); return true; } } return false; } #ifndef Z7_SFX FString GetModuleDirPrefix() { FString s; if (MyGetModuleFileName(s)) { const int pos = s.ReverseFind_PathSepar(); if (pos >= 0) s.DeleteFrom((unsigned)(pos + 1)); } if (s.IsEmpty()) s = "." STRING_PATH_SEPARATOR; return s; } #endif }} #else // _WIN32 #include #include // FARPROC void *GetProcAddress(HMODULE module, LPCSTR procName) { void *ptr = NULL; if (module) ptr = dlsym(module, procName); return ptr; } namespace NWindows { namespace NDLL { bool CLibrary::Free() throw() { if (!_module) return true; const int ret = dlclose(_module); if (ret != 0) return false; _module = NULL; return true; } bool CLibrary::Load(CFSTR path) throw() { if (!Free()) return false; int options = 0; #ifdef RTLD_LOCAL options |= RTLD_LOCAL; #endif #ifdef RTLD_NOW options |= RTLD_NOW; #endif #ifdef RTLD_GROUP #if ! (defined(hpux) || defined(__hpux)) options |= RTLD_GROUP; // mainly for solaris but not for HPUX #endif #endif _module = dlopen(path, options); return (_module != NULL); } /* // FARPROC void * CLibrary::GetProc(LPCSTR procName) const { // return My_GetProcAddress(_module, procName); return local_GetProcAddress(_module, procName); // return NULL; } */ }} #endif tmp41wklro_/CPP/Windows/DLL.h0000444000175000001440000000430314407301260016776 0ustar nabijaczleweliusers// Windows/DLL.h #ifndef ZIP7_INC_WINDOWS_DLL_H #define ZIP7_INC_WINDOWS_DLL_H #include "../Common/MyString.h" #ifndef _WIN32 typedef void * HMODULE; // typedef int (*FARPROC)(); // typedef void *FARPROC; void *GetProcAddress(HMODULE module, LPCSTR procName); #endif namespace NWindows { namespace NDLL { #ifdef _WIN32 /* #ifdef UNDER_CE #define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName) #else #define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName) #endif */ /* Win32: Don't call CLibrary::Free() and FreeLibrary() from another FreeLibrary() code: detaching code in DLL entry-point or in destructors of global objects in DLL module. */ class CLibrary { HMODULE _module; // Z7_CLASS_NO_COPY(CLibrary); // copy constructor is required here public: CLibrary(): _module(NULL) {} ~CLibrary() { Free(); } CLibrary(const CLibrary &c): _module(NULL) { if (c._module) { // we need non const to reference from original item // c._module = NULL; throw 20230102; } } HMODULE Get_HMODULE() const { return _module; } // operator HMODULE() const { return _module; } // HMODULE* operator&() { return &_module; } bool IsLoaded() const { return (_module != NULL); } void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { const HMODULE m = _module; _module = NULL; return m; } bool Free() throw(); bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); bool Load(CFSTR path) throw(); // FARPROC // void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; #else class CLibrary { HMODULE _module; // Z7_CLASS_NO_COPY(CLibrary); public: CLibrary(): _module(NULL) {} ~CLibrary() { Free(); } HMODULE Get_HMODULE() const { return _module; } bool Free() throw(); bool Load(CFSTR path) throw(); // FARPROC // void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); } }; #endif bool MyGetModuleFileName(FString &path); FString GetModuleDirPrefix(); }} #endif tmp41wklro_/CPP/Windows/ErrorMsg.cpp0000444000175000001440000000652114365514000020463 0ustar nabijaczleweliusers// Windows/ErrorMsg.h #include "StdAfx.h" #if !defined(_UNICODE) || !defined(_WIN32) #include "../Common/StringConvert.h" #endif #include "ErrorMsg.h" #ifdef _WIN32 #if !defined(_UNICODE) extern bool g_IsNT; #endif #endif namespace NWindows { namespace NError { static bool MyFormatMessage(DWORD errorCode, UString &message) { #ifndef Z7_SFX if ((HRESULT)errorCode == MY_HRES_ERROR_INTERNAL_ERROR) { message = "Internal Error: The failure in hardware (RAM or CPU), OS or program"; return true; } #endif #ifdef _WIN32 LPVOID msgBuf; #ifndef _UNICODE if (!g_IsNT) { if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) return false; message = GetUnicodeString((LPCTSTR)msgBuf); } else #endif { if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; } ::LocalFree(msgBuf); return true; #else // _WIN32 AString m; const char *s = NULL; switch ((Int32)errorCode) { // case ERROR_NO_MORE_FILES : s = "No more files"; break; // case ERROR_DIRECTORY : s = "Error Directory"; break; case E_NOTIMPL : s = "E_NOTIMPL : Not implemented"; break; case E_NOINTERFACE : s = "E_NOINTERFACE : No such interface supported"; break; case E_ABORT : s = "E_ABORT : Operation aborted"; break; case E_FAIL : s = "E_FAIL : Unspecified error"; break; case STG_E_INVALIDFUNCTION : s = "STG_E_INVALIDFUNCTION"; break; case CLASS_E_CLASSNOTAVAILABLE : s = "CLASS_E_CLASSNOTAVAILABLE"; break; case E_OUTOFMEMORY : s = "E_OUTOFMEMORY : Can't allocate required memory"; break; case E_INVALIDARG : s = "E_INVALIDARG : One or more arguments are invalid"; break; // case MY_E_ERROR_NEGATIVE_SEEK : s = "MY_E_ERROR_NEGATIVE_SEEK"; break; default: break; } /* strerror() for unknown errors still shows message "Unknown error -12345678") So we must transfer error codes before strerror() */ if (!s) { if ((errorCode & 0xFFFF0000) == (UInt32)((MY_FACILITY_WRes << 16) | 0x80000000)) errorCode &= 0xFFFF; else if ((errorCode & ((UInt32)1 << 31))) return false; // we will show hex error later for that case s = strerror((int)errorCode); // if (!s) { m += "errno="; m.Add_UInt32(errorCode); if (s) m += " : "; } } if (s) m += s; MultiByteToUnicodeString2(message, m); return true; #endif } UString MyFormatMessage(DWORD errorCode) { UString m; if (!MyFormatMessage(errorCode, m) || m.IsEmpty()) { char s[16]; for (int i = 0; i < 8; i++) { unsigned t = errorCode & 0xF; errorCode >>= 4; s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[8] = 0; m += "Error #"; m += s; } else if (m.Len() >= 2 && m[m.Len() - 1] == 0x0A && m[m.Len() - 2] == 0x0D) m.DeleteFrom(m.Len() - 2); return m; } }} tmp41wklro_/CPP/Windows/ErrorMsg.h0000444000175000001440000000052214357314620020132 0ustar nabijaczleweliusers// Windows/ErrorMsg.h #ifndef ZIP7_INC_WINDOWS_ERROR_MSG_H #define ZIP7_INC_WINDOWS_ERROR_MSG_H #include "../Common/MyString.h" namespace NWindows { namespace NError { UString MyFormatMessage(DWORD errorCode); inline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); } }} #endif tmp41wklro_/CPP/Windows/FileDir.cpp0000444000175000001440000006611214563351220020246 0ustar nabijaczleweliusers// Windows/FileDir.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include #include #include #include #include #include #include #include #include "../Common/StringConvert.h" #include "../Common/C_FileIO.h" #endif #include "FileDir.h" #include "FileFind.h" #include "FileName.h" #ifndef _UNICODE extern bool g_IsNT; #endif using namespace NWindows; using namespace NFile; using namespace NName; #ifndef _WIN32 static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) { if (ft) { #if defined(_AIX) ts.tv_sec = ft->tv_sec; ts.tv_nsec = ft->tv_nsec; #else ts = *ft; #endif return true; } // else { ts.tv_sec = 0; ts.tv_nsec = #ifdef UTIME_OMIT UTIME_OMIT; // -2 keep old timesptamp #else // UTIME_NOW; -1 // set to the current time 0; #endif return false; } } #endif namespace NWindows { namespace NFile { namespace NDir { #ifdef _WIN32 #ifndef UNDER_CE bool GetWindowsDir(FString &path) { const unsigned kBufSize = MAX_PATH + 16; UINT len; #ifndef _UNICODE if (!g_IsNT) { TCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetWindowsDirectory(s, kBufSize); path = fas2fs(s); } else #endif { WCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetWindowsDirectoryW(s, kBufSize); path = us2fs(s); } return (len != 0 && len < kBufSize); } /* new DOCs for GetSystemDirectory: returned path does not end with a backslash unless the system directory is the root directory. */ bool GetSystemDir(FString &path) { const unsigned kBufSize = MAX_PATH + 16; UINT len; #ifndef _UNICODE if (!g_IsNT) { TCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetSystemDirectory(s, kBufSize); path = fas2fs(s); } else #endif { WCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetSystemDirectoryW(s, kBufSize); path = us2fs(s); } return (len != 0 && len < kBufSize); } #endif // UNDER_CE bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = INVALID_HANDLE_VALUE; IF_USE_MAIN_PATH hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef Z7_LONG_PATH if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool SetFileAttrib(CFSTR path, DWORD attrib) { #ifndef _UNICODE if (!g_IsNT) { if (::SetFileAttributes(fs2fas(path), attrib)) return true; } else #endif { IF_USE_MAIN_PATH if (::SetFileAttributesW(fs2us(path), attrib)) return true; #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::SetFileAttributesW(superPath, attrib)); } #endif } return false; } bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { #ifdef _WIN32 if ((attrib & 0xF0000000) != 0) attrib &= 0x3FFF; #endif return SetFileAttrib(path, attrib); } bool RemoveDir(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) { if (::RemoveDirectory(fs2fas(path))) return true; } else #endif { IF_USE_MAIN_PATH if (::RemoveDirectoryW(fs2us(path))) return true; #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::RemoveDirectoryW(superPath)); } #endif } return false; } bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { #ifndef _UNICODE if (!g_IsNT) { if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) return true; } else #endif { IF_USE_MAIN_PATH_2(oldFile, newFile) { if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) return true; } #ifdef Z7_LONG_PATH if (USE_SUPER_PATH_2) { UString d1, d2; if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) return BOOLToBool(::MoveFileW(d1, d2)); } #endif } return false; } #ifndef UNDER_CE #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 #define Z7_USE_DYN_CreateHardLink #endif #ifdef Z7_USE_DYN_CreateHardLink EXTERN_C_BEGIN typedef BOOL (WINAPI *Func_CreateHardLinkW)( LPCWSTR lpFileName, LPCWSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes ); EXTERN_C_END #endif #endif // UNDER_CE bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { #ifndef _UNICODE if (!g_IsNT) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; /* if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) return true; */ } else #endif { #ifdef Z7_USE_DYN_CreateHardLink const Func_CreateHardLinkW my_CreateHardLinkW = Z7_GET_PROC_ADDRESS( Func_CreateHardLinkW, ::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); if (!my_CreateHardLinkW) return false; #define MY_CreateHardLinkW my_CreateHardLinkW #else #define MY_CreateHardLinkW CreateHardLinkW #endif IF_USE_MAIN_PATH_2(newFileName, existFileName) { if (MY_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) return true; } #ifdef Z7_LONG_PATH if (USE_SUPER_PATH_2) { UString d1, d2; if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) return BOOLToBool(MY_CreateHardLinkW(d1, d2, NULL)); } #endif } return false; } /* WinXP-64 CreateDir(): "" - ERROR_PATH_NOT_FOUND \ - ERROR_ACCESS_DENIED C:\ - ERROR_ACCESS_DENIED, if there is such drive, D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive, C:\nonExistent\folder - ERROR_PATH_NOT_FOUND C:\existFolder - ERROR_ALREADY_EXISTS C:\existFolder\ - ERROR_ALREADY_EXISTS C:\folder - OK C:\folder\ - OK \\Server\nonExistent - ERROR_BAD_NETPATH \\Server\Share_Readonly - ERROR_ACCESS_DENIED \\Server\Share - ERROR_ALREADY_EXISTS \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS */ bool CreateDir(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) { if (::CreateDirectory(fs2fas(path), NULL)) return true; } else #endif { IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) return true; #ifdef Z7_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::CreateDirectoryW(superPath, NULL)); } #endif } return false; } /* CreateDir2 returns true, if directory can contain files after the call (two cases): 1) the directory already exists 2) the directory was created path must be WITHOUT trailing path separator. We need CreateDir2, since fileInfo.Find() for reserved names like "com8" returns FILE instead of DIRECTORY. And we need to use SuperPath */ static bool CreateDir2(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) { if (::CreateDirectory(fs2fas(path), NULL)) return true; } else #endif { IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) return true; #ifdef Z7_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) { if (::CreateDirectoryW(superPath, NULL)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; NFind::CFileInfo fi; if (!fi.Find(us2fs(superPath))) return false; return fi.IsDir(); } } #endif } if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; NFind::CFileInfo fi; if (!fi.Find(path)) return false; return fi.IsDir(); } #endif // _WIN32 static bool CreateDir2(CFSTR path); bool CreateComplexDir(CFSTR _path) { #ifdef _WIN32 { const DWORD attrib = NFind::GetFileAttrib(_path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) return true; } #ifndef UNDER_CE if (IsDriveRootPath_SuperAllowed(_path)) return false; const unsigned prefixSize = GetRootPrefixSize(_path); #endif // UNDER_CE #else // _WIN32 // Posix NFind::CFileInfo fi; if (fi.Find(_path)) { if (fi.IsDir()) return true; } #endif // _WIN32 FString path (_path); int pos = path.ReverseFind_PathSepar(); if (pos >= 0 && (unsigned)pos == path.Len() - 1) { if (path.Len() == 1) return true; path.DeleteBack(); } const FString path2 (path); pos = (int)path.Len(); for (;;) { if (CreateDir2(path)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) return false; pos = path.ReverseFind_PathSepar(); if (pos < 0 || pos == 0) return false; #if defined(_WIN32) && !defined(UNDER_CE) if (pos == 1 && IS_PATH_SEPAR(path[0])) return false; if (prefixSize >= (unsigned)pos + 1) return false; #endif path.DeleteFrom((unsigned)pos); } while (pos < (int)path2.Len()) { int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1)); if (pos2 < 0) pos = (int)path2.Len(); else pos += 1 + pos2; path.SetFrom(path2, (unsigned)pos); if (!CreateDir(path)) return false; } return true; } #ifdef _WIN32 bool DeleteFileAlways(CFSTR path) { /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete. SetFileAttrib("name:stream", ) changes attributes of main file. */ { DWORD attrib = NFind::GetFileAttrib(path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0 && (attrib & FILE_ATTRIBUTE_READONLY) != 0) { if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY)) return false; } } #ifndef _UNICODE if (!g_IsNT) { if (::DeleteFile(fs2fas(path))) return true; } else #endif { /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")). Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */ IF_USE_MAIN_PATH if (::DeleteFileW(fs2us(path))) return true; #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::DeleteFileW(superPath)); } #endif } return false; } bool RemoveDirWithSubItems(const FString &path) { bool needRemoveSubItems = true; { NFind::CFileInfo fi; if (!fi.Find(path)) return false; if (!fi.IsDir()) { ::SetLastError(ERROR_DIRECTORY); return false; } if (fi.HasReparsePoint()) needRemoveSubItems = false; } if (needRemoveSubItems) { FString s (path); s.Add_PathSepar(); const unsigned prefixSize = s.Len(); NFind::CEnumerator enumerator; enumerator.SetDirPrefix(s); NFind::CDirEntry fi; bool isError = false; DWORD lastError = 0; while (enumerator.Next(fi)) { s.DeleteFrom(prefixSize); s += fi.Name; if (fi.IsDir()) { if (!RemoveDirWithSubItems(s)) { lastError = GetLastError(); isError = true; } } else if (!DeleteFileAlways(s)) { lastError = GetLastError(); isError = false; } } if (isError) { SetLastError(lastError); return false; } } // we clear read-only attrib to remove read-only dir if (!SetFileAttrib(path, 0)) return false; return RemoveDir(path); } #endif // _WIN32 #ifdef UNDER_CE bool MyGetFullPathName(CFSTR path, FString &resFullPath) { resFullPath = path; return true; } #else bool MyGetFullPathName(CFSTR path, FString &resFullPath) { return GetFullPath(path, resFullPath); } #ifdef _WIN32 /* Win10: SetCurrentDirectory() doesn't support long paths and doesn't support super prefix "\\?\", if long path behavior is not enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */ bool SetCurrentDir(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) { return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); } else #endif { return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); } } /* we use system function GetCurrentDirectory() new GetCurrentDirectory() DOCs: - If the function fails, the return value is zero. - If the function succeeds, the return value specifies the number of characters that are written to the buffer, not including the terminating null character. - If the buffer is not large enough, the return value specifies the required size of the buffer, in characters, including the null-terminating character. GetCurrentDir() calls GetCurrentDirectory(). GetCurrentDirectory() in win10 in tests: the returned (path) does not end with a backslash, if current directory is not root directory of drive. But that behavior is not guarantied in specification docs. */ bool GetCurrentDir(FString &path) { const unsigned kBufSize = MAX_PATH + 16; path.Empty(); #ifndef _UNICODE if (!g_IsNT) { TCHAR s[kBufSize + 1]; s[0] = 0; const DWORD len = ::GetCurrentDirectory(kBufSize, s); if (len == 0 || len >= kBufSize) return false; s[kBufSize] = 0; // optional guard path = fas2fs(s); return true; } else #endif { DWORD len; { WCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetCurrentDirectoryW(kBufSize, s); if (len == 0) return false; if (len < kBufSize) { s[kBufSize] = 0; // optional guard path = us2fs(s); return true; } } UString temp; const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len)); if (len2 == 0) return false; temp.ReleaseBuf_CalcLen(len); if (temp.Len() != len2 || len - 1 != len2) { /* it's unexpected case, if current dir of process was changed between two function calls, or some unexpected function implementation */ // SetLastError((DWORD)E_FAIL); // we can set some error code return false; } path = us2fs(temp); return true; } } #endif // _WIN32 #endif // UNDER_CE bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { bool res = MyGetFullPathName(path, resDirPrefix); if (!res) resDirPrefix = path; int pos = resDirPrefix.ReverseFind_PathSepar(); pos++; resFileName = resDirPrefix.Ptr((unsigned)pos); resDirPrefix.DeleteFrom((unsigned)pos); return res; } bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) { FString resFileName; return GetFullPathAndSplit(path, resDirPrefix, resFileName); } bool MyGetTempPath(FString &path) { #ifdef _WIN32 /* new DOCs for GetTempPathW(): - The returned string ends with a backslash. - The maximum possible return value is MAX_PATH+1 (261). */ const unsigned kBufSize = MAX_PATH + 16; DWORD len; #ifndef _UNICODE if (!g_IsNT) { TCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetTempPath(kBufSize, s); path = fas2fs(s); } else #endif { WCHAR s[kBufSize + 1]; s[0] = 0; len = ::GetTempPathW(kBufSize, s); path = us2fs(s); } /* win10: GetTempPathW() doesn't set backslash at the end of path, if (buffer_size == len_of(path_with_backslash)). So we normalize path here: */ NormalizeDirPathPrefix(path); return (len != 0 && len < kBufSize); #else // !_WIN32 // FIXME: improve that code path = STRING_PATH_SEPARATOR "tmp"; const char *s; if (NFind::DoesDirExist_FollowLink(path)) s = STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR; else s = "." STRING_PATH_SEPARATOR; path = s; return true; #endif } bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile) { UInt32 d = #ifdef _WIN32 (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); #else (UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid()); #endif for (unsigned i = 0; i < 100; i++) { postfix.Empty(); if (addRandom) { char s[16]; UInt32 val = d; unsigned k; for (k = 0; k < 8; k++) { const unsigned t = (unsigned)val & 0xF; val >>= 4; s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; if (outFile) postfix.Add_Dot(); postfix += s; UInt32 step = GetTickCount() + 2; if (step == 0) step = 1; d += step; } addRandom = true; if (outFile) postfix += ".tmp"; FString path (prefix); path += postfix; if (NFind::DoesFileOrDirExist(path)) { SetLastError(ERROR_ALREADY_EXISTS); continue; } if (outFile) { if (outFile->Create_NEW(path)) return true; } else { if (CreateDir(path)) return true; } const DWORD error = GetLastError(); if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) break; } postfix.Empty(); return false; } bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { if (!Remove()) return false; _path.Empty(); AString postfix; if (!CreateTempFile2(prefix, false, postfix, outFile)) return false; _path = prefix; _path += postfix; _mustBeDeleted = true; return true; } bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) { if (!Remove()) return false; _path.Empty(); FString tempPath; if (!MyGetTempPath(tempPath)) return false; AString postfix; tempPath += namePrefix; if (!CreateTempFile2(tempPath, true, postfix, outFile)) return false; _path = tempPath; _path += postfix; _mustBeDeleted = true; return true; } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_path); return !_mustBeDeleted; } bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { // DWORD attrib = 0; if (deleteDestBefore) { if (NFind::DoesFileExist_Raw(name)) { // attrib = NFind::GetFileAttrib(name); if (!DeleteFileAlways(name)) return false; } } DisableDeleting(); return MyMoveFile(_path, name); /* if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) { DWORD attrib2 = NFind::GetFileAttrib(name); if (attrib2 != INVALID_FILE_ATTRIBUTES) SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY); } */ } #ifdef _WIN32 bool CTempDir::Create(CFSTR prefix) { if (!Remove()) return false; _path.Empty(); FString tempPath; if (!MyGetTempPath(tempPath)) return false; tempPath += prefix; AString postfix; if (!CreateTempFile2(tempPath, true, postfix, NULL)) return false; _path = tempPath; _path += postfix; _mustBeDeleted = true; return true; } bool CTempDir::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirWithSubItems(_path); return !_mustBeDeleted; } #endif #ifndef _WIN32 bool RemoveDir(CFSTR path) { return (rmdir(path) == 0); } static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) { NWindows::NFile::NIO::COutFile outFile; if (!outFile.Create_NEW(newFile)) return FALSE; NWindows::NFile::NIO::CInFile inFile; if (!inFile.Open(oldFile)) return FALSE; char buf[1 << 14]; for (;;) { const ssize_t num = inFile.read_part(buf, sizeof(buf)); if (num == 0) return TRUE; if (num < 0) return FALSE; size_t processed; const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); if (num2 != num || processed != (size_t)num) return FALSE; } } bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { int res = rename(oldFile, newFile); if (res == 0) return true; if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) return false; if (My_CopyFile(oldFile, newFile) == FALSE) return false; struct stat info_file; res = stat(oldFile, &info_file); if (res != 0) return false; /* ret = chmod(dst,info_file.st_mode & g_umask.mask); */ return (unlink(oldFile) == 0); } bool CreateDir(CFSTR path) { return (mkdir(path, 0777) == 0); // change it } static bool CreateDir2(CFSTR path) { return (mkdir(path, 0777) == 0); // change it } bool DeleteFileAlways(CFSTR path) { return (remove(path) == 0); } bool SetCurrentDir(CFSTR path) { return (chdir(path) == 0); } bool GetCurrentDir(FString &path) { path.Empty(); #define MY_PATH_MAX PATH_MAX // #define MY_PATH_MAX 1024 char s[MY_PATH_MAX + 1]; char *res = getcwd(s, MY_PATH_MAX); if (res) { path = fas2fs(s); return true; } { // if (errno != ERANGE) return false; #if defined(__GLIBC__) || defined(__APPLE__) /* As an extension to the POSIX.1-2001 standard, glibc's getcwd() allocates the buffer dynamically using malloc(3) if buf is NULL. */ res = getcwd(NULL, 0); if (res) { path = fas2fs(res); ::free(res); return true; } #endif return false; } } // #undef UTIME_OMIT // to debug #ifndef UTIME_OMIT /* we can define UTIME_OMIT for debian and another systems. Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */ // #define UTIME_OMIT -2 #endif bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) { // need testing /* struct utimbuf buf; struct stat st; UNUSED_VAR(cTime) printf("\nstat = %s\n", path); int ret = stat(path, &st); if (ret == 0) { buf.actime = st.st_atime; buf.modtime = st.st_mtime; } else { time_t cur_time = time(0); buf.actime = cur_time; buf.modtime = cur_time; } if (aTime) { UInt32 ut; if (NTime::FileTimeToUnixTime(*aTime, ut)) buf.actime = ut; } if (mTime) { UInt32 ut; if (NTime::FileTimeToUnixTime(*mTime, ut)) buf.modtime = ut; } return utime(path, &buf) == 0; */ // if (!aTime && !mTime) return true; struct timespec times[2]; UNUSED_VAR(cTime) bool needChange; needChange = FiTime_To_timespec(aTime, times[0]); needChange |= FiTime_To_timespec(mTime, times[1]); /* if (mTime) { printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); } */ if (!needChange) return true; const int flags = 0; // follow link // = AT_SYMLINK_NOFOLLOW; // don't follow link return utimensat(AT_FDCWD, path, times, flags) == 0; } struct C_umask { mode_t mask; C_umask() { /* by security reasons we restrict attributes according with process's file mode creation mask (umask) */ const mode_t um = umask(0); // octal :0022 is expected mask = 0777 & (~um); // octal: 0755 is expected umask(um); // restore the umask // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); // mask = 0777; // debug we can disable the restriction: } }; static C_umask g_umask; // #define PRF(x) x; #define PRF(x) #define TRACE_SetFileAttrib(msg) \ PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg);) #define TRACE_chmod(s, mode) \ PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode));) int my_chown(CFSTR path, uid_t owner, gid_t group) { return chown(path, owner, group); } bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { TRACE_SetFileAttrib("") struct stat st; bool use_lstat = true; if (use_lstat) { if (lstat(path, &st) != 0) { TRACE_SetFileAttrib("bad lstat()") return false; } // TRACE_chmod("lstat", st.st_mode); } else { if (stat(path, &st) != 0) { TRACE_SetFileAttrib("bad stat()") return false; } } if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) { TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") st.st_mode = attrib >> 16; if (S_ISDIR(st.st_mode)) { // user/7z must be able to create files in this directory st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); } else if (!S_ISREG(st.st_mode)) return true; } else if (S_ISLNK(st.st_mode)) { /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. so we don't need chmod() for symlinks. */ return true; // SetLastError(ENOSYS); // return false; } else { TRACE_SetFileAttrib("Only Windows Attributes") // Only Windows Attributes if (S_ISDIR(st.st_mode) || (attrib & FILE_ATTRIBUTE_READONLY) == 0) return true; st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions } int res; /* if (S_ISLNK(st.st_mode)) { printf("\nfchmodat()\n"); TRACE_chmod(path, (st.st_mode) & g_umask.mask) // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); } else */ { TRACE_chmod(path, (st.st_mode) & g_umask.mask) res = chmod(path, (st.st_mode) & g_umask.mask); } // TRACE_SetFileAttrib("End") return (res == 0); } bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName);) return (link(existFileName, newFileName) == 0); } #endif // !_WIN32 // #endif }}} tmp41wklro_/CPP/Windows/FileDir.h0000444000175000001440000000643014357314620017714 0ustar nabijaczleweliusers// Windows/FileDir.h #ifndef ZIP7_INC_WINDOWS_FILE_DIR_H #define ZIP7_INC_WINDOWS_FILE_DIR_H #include "../Common/MyString.h" #include "FileIO.h" namespace NWindows { namespace NFile { namespace NDir { bool GetWindowsDir(FString &path); bool GetSystemDir(FString &path); /* WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file but linux : allows unix time = 0 in filesystem */ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); #ifdef _WIN32 bool SetFileAttrib(CFSTR path, DWORD attrib); /* Some programs store posix attributes in high 16 bits of windows attributes field. Also some programs use additional flag markers: 0x8000 or 0x4000. SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute bits that are related to current system only. */ #else int my_chown(CFSTR path, uid_t owner, gid_t group); #endif bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); #ifndef UNDER_CE bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); #endif bool RemoveDir(CFSTR path); bool CreateDir(CFSTR path); /* CreateComplexDir returns true, if directory can contain files after the call (two cases): 1) the directory already exists (network shares and drive paths are supported) 2) the directory was created path can be WITH or WITHOUT trailing path separator. */ bool CreateComplexDir(CFSTR path); bool DeleteFileAlways(CFSTR name); bool RemoveDirWithSubItems(const FString &path); bool MyGetFullPathName(CFSTR path, FString &resFullPath); bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); #ifndef UNDER_CE bool SetCurrentDir(CFSTR path); bool GetCurrentDir(FString &resultPath); #endif bool MyGetTempPath(FString &resultPath); bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile); class CTempFile MY_UNCOPYABLE { bool _mustBeDeleted; FString _path; void DisableDeleting() { _mustBeDeleted = false; } public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } const FString &GetPath() const { return _path; } bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); bool Remove(); bool MoveTo(CFSTR name, bool deleteDestBefore); }; #ifdef _WIN32 class CTempDir MY_UNCOPYABLE { bool _mustBeDeleted; FString _path; public: CTempDir(): _mustBeDeleted(false) {} ~CTempDir() { Remove(); } const FString &GetPath() const { return _path; } void DisableDeleting() { _mustBeDeleted = false; } bool Create(CFSTR namePrefix) ; bool Remove(); }; #endif #if !defined(UNDER_CE) class CCurrentDirRestorer MY_UNCOPYABLE { FString _path; public: bool NeedRestore; CCurrentDirRestorer(): NeedRestore(true) { GetCurrentDir(_path); } ~CCurrentDirRestorer() { if (!NeedRestore) return; FString s; if (GetCurrentDir(s)) if (s != _path) SetCurrentDir(_path); } }; #endif }}} #endif tmp41wklro_/CPP/Windows/FileFind.cpp0000444000175000001440000010640414562373444020422 0ustar nabijaczleweliusers// Windows/FileFind.cpp #include "StdAfx.h" // #include #ifndef _WIN32 #include /* Definition of AT_* constants */ #include "TimeUtils.h" // for major // #include #endif #include "FileFind.h" #include "FileIO.h" #include "FileName.h" #ifndef _UNICODE extern bool g_IsNT; #endif using namespace NWindows; using namespace NFile; using namespace NName; #if defined(_WIN32) && !defined(UNDER_CE) #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502 // Win2003 #define Z7_USE_DYN_FindFirstStream #endif #ifdef Z7_USE_DYN_FindFirstStream Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION EXTERN_C_BEGIN typedef enum { My_FindStreamInfoStandard, My_FindStreamInfoMaxInfoLevel } MY_STREAM_INFO_LEVELS; typedef struct { LARGE_INTEGER StreamSize; WCHAR cStreamName[MAX_PATH + 36]; } MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; typedef HANDLE (WINAPI *Func_FindFirstStreamW)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, LPVOID findStreamData, DWORD flags); typedef BOOL (APIENTRY *Func_FindNextStreamW)(HANDLE findStream, LPVOID findStreamData); EXTERN_C_END #else #define MY_WIN32_FIND_STREAM_DATA WIN32_FIND_STREAM_DATA #define My_FindStreamInfoStandard FindStreamInfoStandard #endif #endif // defined(_WIN32) && !defined(UNDER_CE) namespace NWindows { namespace NFile { #ifdef _WIN32 #ifdef Z7_DEVICE_FILE namespace NSystem { bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif #endif namespace NFind { /* #ifdef _WIN32 #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; #else #define MY_CLEAR_FILETIME(ft) ft.tv_sec = 0; ft.tv_nsec = 0; #endif */ void CFileInfoBase::ClearBase() throw() { Size = 0; FiTime_Clear(CTime); FiTime_Clear(ATime); FiTime_Clear(MTime); #ifdef _WIN32 Attrib = 0; // ReparseTag = 0; IsAltStream = false; IsDevice = false; #else dev = 0; ino = 0; mode = 0; nlink = 0; uid = 0; gid = 0; rdev = 0; #endif } bool CFileInfoBase::SetAs_StdInFile() { ClearBase(); Size = (UInt64)(Int64)-1; NTime::GetCurUtc_FiTime(MTime); CTime = ATime = MTime; #ifdef _WIN32 /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL, and it doesn't set LastError. */ #if 1 SetLastError(0); const HANDLE h = GetStdHandle(STD_INPUT_HANDLE); if (!h || h == INVALID_HANDLE_VALUE) { if (GetLastError() == 0) SetLastError(ERROR_INVALID_HANDLE); return false; } BY_HANDLE_FILE_INFORMATION info; if (GetFileInformationByHandle(h, &info) && info.dwVolumeSerialNumber) { Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; // FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; // NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; Attrib = info.dwFileAttributes; CTime = info.ftCreationTime; ATime = info.ftLastAccessTime; MTime = info.ftLastWriteTime; } #if 0 printf( "\ndwFileAttributes = %8x" "\nftCreationTime = %8x" "\nftLastAccessTime = %8x" "\nftLastWriteTime = %8x" "\ndwVolumeSerialNumber = %8x" "\nnFileSizeHigh = %8x" "\nnFileSizeLow = %8x" "\nnNumberOfLinks = %8x" "\nnFileIndexHigh = %8x" "\nnFileIndexLow = %8x \n", (unsigned)info.dwFileAttributes, (unsigned)info.ftCreationTime.dwHighDateTime, (unsigned)info.ftLastAccessTime.dwHighDateTime, (unsigned)info.ftLastWriteTime.dwHighDateTime, (unsigned)info.dwVolumeSerialNumber, (unsigned)info.nFileSizeHigh, (unsigned)info.nFileSizeLow, (unsigned)info.nNumberOfLinks, (unsigned)info.nFileIndexHigh, (unsigned)info.nFileIndexLow); #endif #endif #else // non-Wiondow mode = S_IFIFO | 0777; // 0755 : 0775 : 0664 : 0644 : #if 1 struct stat st; if (fstat(0, &st) == 0) { SetFrom_stat(st); if (!S_ISREG(st.st_mode) // S_ISFIFO(st->st_mode) || st.st_size == 0) { Size = (UInt64)(Int64)-1; // mode = S_IFIFO | 0777; } } #endif #endif return true; } bool CFileInfo::IsDots() const throw() { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != '.') return false; return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); } #ifdef _WIN32 #define WIN_FD_TO_MY_FI(fi, fd) \ fi.Attrib = fd.dwFileAttributes; \ fi.CTime = fd.ftCreationTime; \ fi.ATime = fd.ftLastAccessTime; \ fi.MTime = fd.ftLastWriteTime; \ fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ /* fi.ReparseTag = fd.dwReserved0; */ \ fi.IsAltStream = false; \ fi.IsDevice = false; /* #ifdef UNDER_CE fi.ObjectID = fd.dwOID; #else fi.ReparseTag = fd.dwReserved0; #endif */ static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd) fi.Name = us2fs(fd.cFileName); #if defined(_WIN32) && !defined(UNDER_CE) // fi.ShortName = us2fs(fd.cAlternateFileName); #endif } #ifndef _UNICODE static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd) fi.Name = fas2fs(fd.cFileName); #if defined(_WIN32) && !defined(UNDER_CE) // fi.ShortName = fas2fs(fd.cAlternateFileName); #endif } #endif //////////////////////////////// // CFindFile bool CFindFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } /* WinXP-64 FindFirstFile(): "" - ERROR_PATH_NOT_FOUND folder\ - ERROR_FILE_NOT_FOUND \ - ERROR_FILE_NOT_FOUND c:\ - ERROR_FILE_NOT_FOUND c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ ) c: - OK, if current dir is NOT ROOT ( c:\folder ) folder - OK \\ - ERROR_INVALID_NAME \\Server - ERROR_INVALID_NAME \\Server\ - ERROR_INVALID_NAME \\Server\Share - ERROR_BAD_NETPATH \\Server\Share - ERROR_BAD_NET_NAME (Win7). !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon), when we call it for "\\Server\Share" \\Server\Share\ - ERROR_FILE_NOT_FOUND \\?\UNC\Server\Share - ERROR_INVALID_NAME \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7) \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND \\Server\Share_RootDrive - ERROR_INVALID_NAME \\Server\Share_RootDrive\ - ERROR_INVALID_NAME e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w: */ bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) { if (!Close()) return false; #ifndef _UNICODE if (!g_IsNT) { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(fs2fas(path), &fd); if (_handle == INVALID_HANDLE_VALUE) return false; Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } else #endif { WIN32_FIND_DATAW fd; IF_USE_MAIN_PATH _handle = ::FindFirstFileW(fs2us(path), &fd); #ifdef Z7_LONG_PATH if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) _handle = ::FindFirstFileW(superPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } return true; } bool CFindFile::FindNext(CFileInfo &fi) { #ifndef _UNICODE if (!g_IsNT) { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } else #endif { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } return true; } #if defined(_WIN32) && !defined(UNDER_CE) //////////////////////////////// // AltStreams #ifdef Z7_USE_DYN_FindFirstStream static Func_FindFirstStreamW g_FindFirstStreamW; static Func_FindNextStreamW g_FindNextStreamW; #define MY_FindFirstStreamW g_FindFirstStreamW #define MY_FindNextStreamW g_FindNextStreamW static struct CFindStreamLoader { CFindStreamLoader() { const HMODULE hm = ::GetModuleHandleA("kernel32.dll"); g_FindFirstStreamW = Z7_GET_PROC_ADDRESS( Func_FindFirstStreamW, hm, "FindFirstStreamW"); g_FindNextStreamW = Z7_GET_PROC_ADDRESS( Func_FindNextStreamW, hm, "FindNextStreamW"); } } g_FindStreamLoader; #else #define MY_FindFirstStreamW FindFirstStreamW #define MY_FindNextStreamW FindNextStreamW #endif bool CStreamInfo::IsMainStream() const throw() { return StringsAreEqualNoCase_Ascii(Name, "::$DATA"); } UString CStreamInfo::GetReducedName() const { // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA" UString s (Name); if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA")) s.DeleteFrom(s.Len() - 6); return s; } /* UString CStreamInfo::GetReducedName2() const { UString s = GetReducedName(); if (!s.IsEmpty() && s[0] == ':') s.Delete(0); return s; } */ static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) { si.Size = (UInt64)sd.StreamSize.QuadPart; si.Name = sd.cStreamName; } /* WinXP-64 FindFirstStream(): "" - ERROR_PATH_NOT_FOUND folder\ - OK folder - OK \ - OK c:\ - OK c: - OK, if current dir is ROOT ( c:\ ) c: - OK, if current dir is NOT ROOT ( c:\folder ) \\Server\Share - OK \\Server\Share\ - OK \\ - ERROR_INVALID_NAME \\Server - ERROR_INVALID_NAME \\Server\ - ERROR_INVALID_NAME */ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) { if (!Close()) return false; #ifdef Z7_USE_DYN_FindFirstStream if (!g_FindFirstStreamW) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif { MY_WIN32_FIND_STREAM_DATA sd; SetLastError(0); IF_USE_MAIN_PATH _handle = MY_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); if (_handle == INVALID_HANDLE_VALUE) { if (::GetLastError() == ERROR_HANDLE_EOF) return false; // long name can be tricky for path like ".\dirName". #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) _handle = MY_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0); } #endif } if (_handle == INVALID_HANDLE_VALUE) return false; Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } return true; } bool CFindStream::FindNext(CStreamInfo &si) { #ifdef Z7_USE_DYN_FindFirstStream if (!g_FindNextStreamW) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif { MY_WIN32_FIND_STREAM_DATA sd; if (!MY_FindNextStreamW(_handle, &sd)) return false; Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } return true; } bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) { bool res; if (_find.IsHandleAllocated()) res = _find.FindNext(si); else res = _find.FindFirst(_filePath, si); if (res) { found = true; return true; } found = false; return (::GetLastError() == ERROR_HANDLE_EOF); } #endif /* WinXP-64 GetFileAttributes(): If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code \ - OK C:\ - OK, if there is such drive, D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive, C:\folder - OK C:\folder\ - OK C:\folderBad - ERROR_FILE_NOT_FOUND \\Server\BadShare - ERROR_BAD_NETPATH \\Server\Share - WORKS OK, but MSDN says: GetFileAttributes for a network share, the function fails, and GetLastError returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share. */ DWORD GetFileAttrib(CFSTR path) { #ifndef _UNICODE if (!g_IsNT) return ::GetFileAttributes(fs2fas(path)); else #endif { IF_USE_MAIN_PATH { DWORD dw = ::GetFileAttributesW(fs2us(path)); if (dw != INVALID_FILE_ATTRIBUTES) return dw; } #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return ::GetFileAttributesW(superPath); } #endif return INVALID_FILE_ATTRIBUTES; } } /* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk so instead of absolute path we have relative path in Name. That is not good in some calls */ /* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */ /* CFileInfo::Find() We alow the following paths (as FindFirstFile): C:\folder c: - if current dir is NOT ROOT ( c:\folder ) also we support paths that are not supported by FindFirstFile: \ \\.\c: c:\ - Name will be without tail slash ( c: ) \\?\c:\ - Name will be without tail slash ( c: ) \\Server\Share \\?\UNC\Server\Share c:\folder:stream - Name = folder:stream c:\:stream - Name = :stream c::stream - Name = c::stream */ bool CFileInfo::Find(CFSTR path, bool followLink) { #ifdef Z7_DEVICE_FILE if (IS_PATH_SEPAR(path[0]) && IS_PATH_SEPAR(path[1]) && path[2] == '.' && path[3] == 0) { // 22.00 : it's virtual directory for devices // IsDevice = true; ClearBase(); Name = path + 2; Attrib = FILE_ATTRIBUTE_DIRECTORY; return true; } if (IsDevicePath(path)) { ClearBase(); Name = path + 4; IsDevice = true; if (NName::IsDrivePath2(path + 4) && path[6] == 0) { FChar drive[4] = { path[4], ':', '\\', 0 }; UInt64 clusterSize, totalSize, freeSize; if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) { Size = totalSize; return true; } } NIO::CInFile inFile; // ::OutputDebugStringW(path); if (!inFile.Open(path)) return false; // ::OutputDebugStringW(L"---"); if (inFile.SizeDefined) Size = inFile.Size; return true; } #endif #if defined(_WIN32) && !defined(UNDER_CE) const int colonPos = FindAltStreamColon(path); if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) { UString streamName = fs2us(path + (unsigned)colonPos); FString filePath (path); filePath.DeleteFrom((unsigned)colonPos); /* we allow both cases: name:stream name:stream:$DATA */ const unsigned kPostfixSize = 6; if (streamName.Len() <= kPostfixSize || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA")) streamName += ":$DATA"; bool isOk = true; if (IsDrivePath2(filePath) && (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\'))) { // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT) ClearBase(); Name.Empty(); if (colonPos == 2) Name = filePath; } else isOk = Find(filePath, followLink); // check it (followLink) if (isOk) { Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); Size = 0; CStreamEnumerator enumerator(filePath); for (;;) { CStreamInfo si; bool found; if (!enumerator.Next(si, found)) return false; if (!found) { ::SetLastError(ERROR_FILE_NOT_FOUND); return false; } if (si.Name.IsEqualTo_NoCase(streamName)) { // we delete postfix, if alt stream name is not "::$DATA" if (si.Name.Len() > kPostfixSize + 1) si.Name.DeleteFrom(si.Name.Len() - kPostfixSize); Name += us2fs(si.Name); Size = si.Size; IsAltStream = true; return true; } } } } #endif CFindFile finder; #if defined(_WIN32) && !defined(UNDER_CE) { /* DWORD lastError = GetLastError(); if (lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share" || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share" || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share" || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share" ) */ unsigned rootSize = 0; if (IsSuperPath(path)) rootSize = kSuperPathPrefixSize; if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0) { DWORD attrib = GetFileAttrib(path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) { ClearBase(); Attrib = attrib; Name = path + rootSize; Name.DeleteFrom(2); if (!Fill_From_ByHandleFileInfo(path)) { } return true; } } else if (IS_PATH_SEPAR(path[0])) { if (path[1] == 0) { DWORD attrib = GetFileAttrib(path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) { ClearBase(); Name.Empty(); Attrib = attrib; return true; } } else { const unsigned prefixSize = GetNetworkServerPrefixSize(path); if (prefixSize > 0 && path[prefixSize] != 0) { if (NName::FindSepar(path + prefixSize) < 0) { if (Fill_From_ByHandleFileInfo(path)) { Name = path + prefixSize; return true; } FString s (path); s.Add_PathSepar(); s.Add_Char('*'); // CHAR_ANY_MASK bool isOK = false; if (finder.FindFirst(s, *this)) { if (Name == FTEXT(".")) { Name = path + prefixSize; return true; } isOK = true; /* if "\\server\share" maps to root folder "d:\", there is no "." item. But it's possible that there are another items */ } { const DWORD attrib = GetFileAttrib(path); if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)) { ClearBase(); if (attrib != INVALID_FILE_ATTRIBUTES) Attrib = attrib; else SetAsDir(); Name = path + prefixSize; return true; } } // ::SetLastError(lastError); } } } } } #endif bool res = finder.FindFirst(path, *this); if (!followLink || !res || !HasReparsePoint()) return res; // return FollowReparse(path, IsDir()); return Fill_From_ByHandleFileInfo(path); } bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path) { BY_HANDLE_FILE_INFORMATION info; if (!NIO::CFileBase::GetFileInformation(path, &info)) return false; { Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; CTime = info.ftCreationTime; ATime = info.ftLastAccessTime; MTime = info.ftLastWriteTime; Attrib = info.dwFileAttributes; return true; } } /* bool CFileInfo::FollowReparse(CFSTR path, bool isDir) { if (isDir) { FString prefix = path; prefix.Add_PathSepar(); // "folder/." refers to folder itself. So we can't use that path // we must use enumerator and search "." item CEnumerator enumerator; enumerator.SetDirPrefix(prefix); for (;;) { CFileInfo fi; if (!enumerator.NextAny(fi)) break; if (fi.Name.IsEqualTo_Ascii_NoCase(".")) { // we can copy preperies; CTime = fi.CTime; ATime = fi.ATime; MTime = fi.MTime; Attrib = fi.Attrib; Size = fi.Size; return true; } break; } // LastError(lastError); return false; } { NIO::CInFile inFile; if (inFile.Open(path)) { BY_HANDLE_FILE_INFORMATION info; if (inFile.GetFileInformation(&info)) { ClearBase(); Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; CTime = info.ftCreationTime; ATime = info.ftLastAccessTime; MTime = info.ftLastWriteTime; Attrib = info.dwFileAttributes; return true; } } return false; } } */ bool DoesFileExist_Raw(CFSTR name) { CFileInfo fi; return fi.Find(name) && !fi.IsDir(); } bool DoesFileExist_FollowLink(CFSTR name) { CFileInfo fi; return fi.Find_FollowLink(name) && !fi.IsDir(); } bool DoesDirExist(CFSTR name, bool followLink) { CFileInfo fi; return fi.Find(name, followLink) && fi.IsDir(); } bool DoesFileOrDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name); } void CEnumerator::SetDirPrefix(const FString &dirPrefix) { _wildcard = dirPrefix; _wildcard.Add_Char('*'); } bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fi); else return _findFile.FindFirst(_wildcard, fi); } bool CEnumerator::Next(CFileInfo &fi) { for (;;) { if (!NextAny(fi)) return false; if (!fi.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fi, bool &found) { /* for (;;) { if (!NextAny(fi)) break; if (!fi.IsDots()) { found = true; return true; } } */ if (Next(fi)) { found = true; return true; } found = false; DWORD lastError = ::GetLastError(); if (_findFile.IsHandleAllocated()) return (lastError == ERROR_NO_MORE_FILES); // we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND if (lastError == ERROR_FILE_NOT_FOUND) return true; if (lastError == ERROR_ACCESS_DENIED) { // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*"; const int len = (int)strlen(s); const int delta = (int)_wildcard.Len() - len; if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1]))) if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s)) return true; } return false; } //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() throw() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) { #ifndef _UNICODE if (!g_IsNT) _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); else #endif { IF_USE_MAIN_PATH _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); #ifdef Z7_LONG_PATH if (!IsHandleAllocated()) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif } return _handle; } #ifndef UNDER_CE bool MyGetLogicalDriveStrings(CObjectVector &driveStrings) { driveStrings.Clear(); #ifndef _UNICODE if (!g_IsNT) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CObjArray buf(size); UINT32 newSize = GetLogicalDriveStrings(size, buf); if (newSize == 0 || newSize > size) return false; AString s; UINT32 prev = 0; for (UINT32 i = 0; i < newSize; i++) { if (buf[i] == 0) { s = buf + prev; prev = i + 1; driveStrings.Add(fas2fs(s)); } } return prev == newSize; } else #endif { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; CObjArray buf(size); UINT32 newSize = GetLogicalDriveStringsW(size, buf); if (newSize == 0 || newSize > size) return false; UString s; UINT32 prev = 0; for (UINT32 i = 0; i < newSize; i++) { if (buf[i] == 0) { s = buf + prev; prev = i + 1; driveStrings.Add(us2fs(s)); } } return prev == newSize; } } #endif // UNDER_CE #else // _WIN32 // ---------- POSIX ---------- static int MY_lstat(CFSTR path, struct stat *st, bool followLink) { memset(st, 0, sizeof(*st)); int res; // #ifdef ENV_HAVE_LSTAT if (/* global_use_lstat && */ !followLink) { // printf("\nlstat\n"); res = lstat(path, st); } else // #endif { // printf("\nstat\n"); res = stat(path, st); } #if 0 #if defined(__clang__) && __clang_major__ >= 14 #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" #endif printf("\n st_dev = %lld", (long long)(st->st_dev)); printf("\n st_ino = %lld", (long long)(st->st_ino)); printf("\n st_mode = %llx", (long long)(st->st_mode)); printf("\n st_nlink = %lld", (long long)(st->st_nlink)); printf("\n st_uid = %lld", (long long)(st->st_uid)); printf("\n st_gid = %lld", (long long)(st->st_gid)); printf("\n st_size = %lld", (long long)(st->st_size)); printf("\n st_blksize = %lld", (long long)(st->st_blksize)); printf("\n st_blocks = %lld", (long long)(st->st_blocks)); printf("\n st_ctim = %lld", (long long)(ST_CTIME((*st)).tv_sec)); printf("\n st_mtim = %lld", (long long)(ST_MTIME((*st)).tv_sec)); printf("\n st_atim = %lld", (long long)(ST_ATIME((*st)).tv_sec)); printf(S_ISFIFO(st->st_mode) ? "\n FIFO" : "\n NO FIFO"); printf("\n"); #endif return res; } static const char *Get_Name_from_Path(CFSTR path) throw() { size_t len = strlen(path); if (len == 0) return path; const char *p = path + len - 1; { if (p == path) return path; p--; } for (;;) { char c = *p; if (IS_PATH_SEPAR(c)) return p + 1; if (p == path) return path; p--; } } UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) { UInt32 attrib = S_ISDIR(mode) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE; if ((mode & 0222) == 0) // S_IWUSR in p7zip attrib |= FILE_ATTRIBUTE_READONLY; return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16); } /* UInt32 Get_WinAttrib_From_stat(const struct stat &st) { UInt32 attrib = S_ISDIR(st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE; if ((st.st_mode & 0222) == 0) // check it !!! attrib |= FILE_ATTRIBUTE_READONLY; attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16); return attrib; } */ void CFileInfoBase::SetFrom_stat(const struct stat &st) { // IsDevice = false; if (S_ISDIR(st.st_mode)) { Size = 0; } else { Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename } // Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); // NTime::UnixTimeToFileTime(st.st_ctime, CTime); // NTime::UnixTimeToFileTime(st.st_mtime, MTime); // NTime::UnixTimeToFileTime(st.st_atime, ATime); #ifdef __APPLE__ // #ifdef _DARWIN_FEATURE_64_BIT_INODE /* here we can use birthtime instead of st_ctimespec. but we use st_ctimespec for compatibility with previous versions and p7zip. st_birthtimespec in OSX st_birthtim : at FreeBSD, NetBSD */ // timespec_To_FILETIME(st.st_birthtimespec, CTime); // #else // timespec_To_FILETIME(st.st_ctimespec, CTime); // #endif // timespec_To_FILETIME(st.st_mtimespec, MTime); // timespec_To_FILETIME(st.st_atimespec, ATime); CTime = st.st_ctimespec; MTime = st.st_mtimespec; ATime = st.st_atimespec; #else // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); // timespec_To_FILETIME(st.st_atim, ATime, &ATime_ns100); CTime = st.st_ctim; MTime = st.st_mtim; ATime = st.st_atim; #endif dev = st.st_dev; ino = st.st_ino; mode = st.st_mode; nlink = st.st_nlink; uid = st.st_uid; gid = st.st_gid; rdev = st.st_rdev; /* printf("\n sizeof timespec = %d", (int)sizeof(timespec)); printf("\n sizeof st_rdev = %d", (int)sizeof(rdev)); printf("\n sizeof st_ino = %d", (int)sizeof(ino)); printf("\n sizeof mode_t = %d", (int)sizeof(mode_t)); printf("\n sizeof nlink_t = %d", (int)sizeof(nlink_t)); printf("\n sizeof uid_t = %d", (int)sizeof(uid_t)); printf("\n"); */ /* printf("\n st_rdev = %llx", (long long)rdev); printf("\n st_dev = %llx", (long long)dev); printf("\n dev : major = %5x minor = %5x", (unsigned)major(dev), (unsigned)minor(dev)); printf("\n st_ino = %lld", (long long)(ino)); printf("\n rdev : major = %5x minor = %5x", (unsigned)major(rdev), (unsigned)minor(rdev)); printf("\n size = %lld \n", (long long)(Size)); printf("\n"); */ } /* int Uid_To_Uname(uid_t uid, AString &name) { name.Empty(); struct passwd *passwd; if (uid != 0 && uid == cached_no_such_uid) { *uname = xstrdup (""); return; } if (!cached_uname || uid != cached_uid) { passwd = getpwuid (uid); if (passwd) { cached_uid = uid; assign_string (&cached_uname, passwd->pw_name); } else { cached_no_such_uid = uid; *uname = xstrdup (""); return; } } *uname = xstrdup (cached_uname); } */ bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) { struct stat st; if (MY_lstat(path, &st, followLink) != 0) return false; // printf("\nFind_DontFill_Name : name=%s\n", path); SetFrom_stat(st); return true; } bool CFileInfo::Find(CFSTR path, bool followLink) { // printf("\nCEnumerator::Find() name = %s\n", path); if (!Find_DontFill_Name(path, followLink)) return false; // printf("\nOK\n"); Name = Get_Name_from_Path(path); if (!Name.IsEmpty()) { char c = Name.Back(); if (IS_PATH_SEPAR(c)) Name.DeleteBack(); } return true; } bool DoesFileExist_Raw(CFSTR name) { // FIXME for symbolic links. struct stat st; if (MY_lstat(name, &st, false) != 0) return false; return !S_ISDIR(st.st_mode); } bool DoesFileExist_FollowLink(CFSTR name) { // FIXME for symbolic links. struct stat st; if (MY_lstat(name, &st, true) != 0) return false; return !S_ISDIR(st.st_mode); } bool DoesDirExist(CFSTR name, bool followLink) { struct stat st; if (MY_lstat(name, &st, followLink) != 0) return false; return S_ISDIR(st.st_mode); } bool DoesFileOrDirExist(CFSTR name) { struct stat st; if (MY_lstat(name, &st, false) != 0) return false; return true; } CEnumerator::~CEnumerator() { if (_dir) closedir(_dir); } void CEnumerator::SetDirPrefix(const FString &dirPrefix) { _wildcard = dirPrefix; } bool CDirEntry::IsDots() const throw() { /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) we can call fstatat() for that case, but we use only (Name) check here */ #if !defined(_AIX) && !defined(__sun) if (Type != DT_DIR && Type != DT_UNKNOWN) return false; #endif return Name.Len() != 0 && Name.Len() <= 2 && Name[0] == '.' && (Name.Len() == 1 || Name[1] == '.'); } bool CEnumerator::NextAny(CDirEntry &fi, bool &found) { found = false; if (!_dir) { const char *w = "./"; if (!_wildcard.IsEmpty()) w = _wildcard.Ptr(); _dir = ::opendir((const char *)w); if (_dir == NULL) return false; } // To distinguish end of stream from an error, we must set errno to zero before readdir() errno = 0; struct dirent *de = readdir(_dir); if (!de) { if (errno == 0) return true; // it's end of stream, and we report it with (found = false) // it's real error return false; } fi.iNode = de->d_ino; #if !defined(_AIX) && !defined(__sun) fi.Type = de->d_type; /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) we can set (Type) from fstatat() in that case. But (Type) is not too important. So we don't set it here with slow fstatat() */ /* // fi.Type = DT_UNKNOWN; // for debug if (fi.Type == DT_UNKNOWN) { struct stat st; if (fstatat(dirfd(_dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0) if (S_ISDIR(st.st_mode)) fi.Type = DT_DIR; } */ #endif /* if (de->d_type == DT_DIR) fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16); else if (de->d_type < 16) fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12)); */ fi.Name = de->d_name; /* printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr()); for (unsigned i = 0; i < fi.Name.Len(); i++) printf (" %02x", (unsigned)(Byte)de->d_name[i]); printf("\n"); */ found = true; return true; } bool CEnumerator::Next(CDirEntry &fi, bool &found) { // printf("\nCEnumerator::Next()\n"); // PrintName("Next", ""); for (;;) { if (!NextAny(fi, found)) return false; if (!found) return true; if (!fi.IsDots()) { /* if (!NeedFullStat) return true; // we silently skip error file here - it can be wrong link item if (fi.Find_DontFill_Name(path)) return true; */ return true; } } } /* bool CEnumerator::Next(CDirEntry &fileInfo, bool &found) { bool found; if (!Next(fi, found)) return false; return found; } */ bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const { // printf("\nCEnumerator::Fill_FileInfo()\n"); struct stat st; // probably it's OK to use fstatat() even if it changes file position dirfd(_dir) int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW); // if fstatat() is not supported, we can use stat() / lstat() /* const FString path = _wildcard + s; int res = MY_lstat(path, &st, followLink); */ if (res != 0) return false; // printf("\nname=%s\n", de.Name.Ptr()); fileInfo.SetFrom_stat(st); fileInfo.Name = de.Name; return true; } #endif // _WIN32 }}} tmp41wklro_/CPP/Windows/FileFind.h0000444000175000001440000002165214562077200020057 0ustar nabijaczleweliusers// Windows/FileFind.h #ifndef ZIP7_INC_WINDOWS_FILE_FIND_H #define ZIP7_INC_WINDOWS_FILE_FIND_H #ifndef _WIN32 #include #include #include #endif #include "../Common/MyLinux.h" #include "../Common/MyString.h" #include "../Common/MyWindows.h" #include "Defs.h" #include "FileIO.h" namespace NWindows { namespace NFile { namespace NFind { // bool DoesFileExist(CFSTR name, bool followLink); bool DoesFileExist_Raw(CFSTR name); bool DoesFileExist_FollowLink(CFSTR name); bool DoesDirExist(CFSTR name, bool followLink); inline bool DoesDirExist(CFSTR name) { return DoesDirExist(name, false); } inline bool DoesDirExist_FollowLink(CFSTR name) { return DoesDirExist(name, true); } // it's always _Raw bool DoesFileOrDirExist(CFSTR name); DWORD GetFileAttrib(CFSTR path); #ifdef _WIN32 namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } inline UInt32 Get_PosixMode_From_WinAttrib(DWORD attrib) { UInt32 v = IsDir(attrib) ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY). So extracting at Linux will be allowed to write files inside (0777) directories. */ v |= ((IsReadOnly(attrib) && !IsDir(attrib)) ? 0555 : 0777); return v; } } #else UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode); #endif class CFileInfoBase { #ifdef _WIN32 bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } #endif public: UInt64 Size; CFiTime CTime; CFiTime ATime; CFiTime MTime; #ifdef _WIN32 DWORD Attrib; bool IsAltStream; bool IsDevice; /* #ifdef UNDER_CE DWORD ObjectID; #else UINT32 ReparseTag; #endif */ #else dev_t dev; /* ID of device containing file */ ino_t ino; mode_t mode; nlink_t nlink; uid_t uid; /* user ID of owner */ gid_t gid; /* group ID of owner */ dev_t rdev; /* device ID (defined, if S_ISCHR(mode) || S_ISBLK(mode)) */ // bool Use_lstat; #endif CFileInfoBase() { ClearBase(); } void ClearBase() throw(); bool SetAs_StdInFile(); #ifdef _WIN32 bool Fill_From_ByHandleFileInfo(CFSTR path); void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } UInt32 GetWinAttrib() const { return Attrib; } UInt32 GetPosixAttrib() const { return NAttributes::Get_PosixMode_From_WinAttrib(Attrib); } bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } #else UInt32 GetPosixAttrib() const { return mode; } UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); } bool IsDir() const { return S_ISDIR(mode); } void SetAsDir() { mode = S_IFDIR | 0777; } void SetFrom_stat(const struct stat &st); bool IsReadOnly() const { // does linux support writing to ReadOnly files? if ((mode & 0222) == 0) // S_IWUSR in p7zip return true; return false; } bool IsPosixLink() const { return S_ISLNK(mode); } #endif bool IsOsSymLink() const { #ifdef _WIN32 return HasReparsePoint(); #else return IsPosixLink(); #endif } }; struct CFileInfo: public CFileInfoBase { FString Name; #if defined(_WIN32) && !defined(UNDER_CE) // FString ShortName; #endif bool IsDots() const throw(); bool Find(CFSTR path, bool followLink = false); bool Find_FollowLink(CFSTR path) { return Find(path, true); } #ifdef _WIN32 // bool Fill_From_ByHandleFileInfo(CFSTR path); // bool FollowReparse(CFSTR path, bool isDir); #else bool Find_DontFill_Name(CFSTR path, bool followLink = false); #endif }; #ifdef _WIN32 class CFindFileBase MY_UNCOPYABLE { protected: HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFileBase() { Close(); } bool Close() throw(); }; class CFindFile: public CFindFileBase { public: bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); }; #if defined(_WIN32) && !defined(UNDER_CE) struct CStreamInfo { UString Name; UInt64 Size; UString GetReducedName() const; // returns ":Name" // UString GetReducedName2() const; // returns "Name" bool IsMainStream() const throw(); }; class CFindStream: public CFindFileBase { public: bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); bool FindNext(CStreamInfo &streamInfo); }; class CStreamEnumerator MY_UNCOPYABLE { CFindStream _find; FString _filePath; bool NextAny(CFileInfo &fileInfo, bool &found); public: CStreamEnumerator(const FString &filePath): _filePath(filePath) {} bool Next(CStreamInfo &streamInfo, bool &found); }; #endif // defined(_WIN32) && !defined(UNDER_CE) class CEnumerator MY_UNCOPYABLE { CFindFile _findFile; FString _wildcard; bool NextAny(CFileInfo &fileInfo); public: void SetDirPrefix(const FString &dirPrefix); bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; class CFindChangeNotification MY_UNCOPYABLE { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { /* at least on win2000/XP (undocumented): if pathName is "" or NULL, FindFirstChangeNotification() could return NULL. So we check for INVALID_HANDLE_VALUE and NULL. */ return _handle != INVALID_HANDLE_VALUE && _handle != NULL; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close() throw(); HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef UNDER_CE bool MyGetLogicalDriveStrings(CObjectVector &driveStrings); #endif typedef CFileInfo CDirEntry; #else // WIN32 struct CDirEntry { ino_t iNode; #if !defined(_AIX) && !defined(__sun) Byte Type; #endif FString Name; /* #if !defined(_AIX) && !defined(__sun) bool IsDir() const { // (Type == DT_UNKNOWN) on some systems return Type == DT_DIR; } #endif */ bool IsDots() const throw(); }; class CEnumerator MY_UNCOPYABLE { DIR *_dir; FString _wildcard; bool NextAny(CDirEntry &fileInfo, bool &found); public: CEnumerator(): _dir(NULL) {} ~CEnumerator(); void SetDirPrefix(const FString &dirPrefix); bool Next(CDirEntry &fileInfo, bool &found); bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const { #if !defined(_AIX) && !defined(__sun) if (de.Type == DT_DIR) return true; if (de.Type != DT_UNKNOWN) return false; #endif CFileInfo fileInfo; if (Fill_FileInfo(de, fileInfo, followLink)) { return fileInfo.IsDir(); } return false; // change it } }; /* inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode) { UInt32 attrib = S_ISDIR(mode) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE; if ((st.st_mode & 0222) == 0) // check it !!! attrib |= FILE_ATTRIBUTE_READONLY; return attrib; } */ // UInt32 Get_WinAttrib_From_stat(const struct stat &st); #endif // WIN32 }}} #endif tmp41wklro_/CPP/Windows/FileIO.cpp0000444000175000001440000006172314562366040020047 0ustar nabijaczleweliusers// Windows/FileIO.cpp #include "StdAfx.h" #ifdef Z7_DEVICE_FILE #include "../../C/Alloc.h" #endif // #include /* #ifndef _WIN32 // for ioctl BLKGETSIZE64 #include #include #endif */ #include "FileIO.h" #include "FileName.h" HRESULT GetLastError_noZero_HRESULT() { const DWORD res = ::GetLastError(); if (res == 0) return E_FAIL; return HRESULT_FROM_WIN32(res); } #ifdef _WIN32 #ifndef _UNICODE extern bool g_IsNT; #endif using namespace NWindows; using namespace NFile; using namespace NName; namespace NWindows { namespace NFile { #ifdef Z7_DEVICE_FILE namespace NSystem { bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif namespace NIO { /* WinXP-64 CreateFile(): "" - ERROR_PATH_NOT_FOUND :stream - OK .:stream - ERROR_PATH_NOT_FOUND .\:stream - OK folder\:stream - ERROR_INVALID_NAME folder:stream - OK c:\:stream - OK c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) c::stream - OK, if current dir is ROOT ( c:\ ) */ bool CFileBase::Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; #ifdef Z7_DEVICE_FILE IsDeviceFile = false; #endif #ifndef _UNICODE if (!g_IsNT) { _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } else #endif { IF_USE_MAIN_PATH _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef Z7_LONG_PATH if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) _handle = ::CreateFileW(superPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif } /* #ifndef UNDER_CE #ifndef Z7_SFX if (_handle == INVALID_HANDLE_VALUE) { // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10 DWORD lastError = GetLastError(); if (lastError == ERROR_CANT_ACCESS_FILE) { CByteBuffer buf; if (NIO::GetReparseData(path, buf, NULL)) { CReparseAttr attr; if (attr.Parse(buf, buf.Size())) { FString dirPrefix, fileName; if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName)) { FString fullPath; if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath)) { // FIX IT: recursion levels must be restricted return Create(fullPath, desiredAccess, shareMode, creationDisposition, flagsAndAttributes); } } } } SetLastError(lastError); } } #endif #endif */ return (_handle != INVALID_HANDLE_VALUE); } bool CFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; #if 0 if (!IsStdStream) #endif { if (!::CloseHandle(_handle)) return false; } #if 0 IsStdStream = false; IsStdPipeStream = false; #endif _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetLength(UInt64 &length) const throw() { #ifdef Z7_DEVICE_FILE if (IsDeviceFile && SizeDefined) { length = Size; return true; } #endif DWORD high = 0; const DWORD low = ::GetFileSize(_handle, &high); if (low == INVALID_FILE_SIZE) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)high) << 32) + low; return true; /* LARGE_INTEGER fileSize; // GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+ if (!GetFileSizeEx(_handle, &fileSize)) return false; length = (UInt64)fileSize.QuadPart; return true; */ } /* Specification for SetFilePointer(): If a new file pointer is a negative value, { the function fails, the file pointer is not moved, the code returned by GetLastError() is ERROR_NEGATIVE_SEEK. } If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set { an application can move the file pointer only to sector-aligned positions. A sector-aligned position is a position that is a whole number multiple of the volume sector size. An application can obtain a volume sector size by calling the GetDiskFreeSpace. } It is not an error to set a file pointer to a position beyond the end of the file. The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function. If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL, an application must call GetLastError to determine whether or not the function has succeeded or failed. */ bool CFileBase::GetPosition(UInt64 &position) const throw() { LONG high = 0; const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT); if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { // for error case we can set (position) to (-1) or (0) or leave (position) unchanged. // position = (UInt64)(Int64)-1; // for debug position = 0; return false; } position = (((UInt64)(UInt32)high) << 32) + low; return true; // we don't want recursed GetPosition() // return Seek(0, FILE_CURRENT, position); } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() { #ifdef Z7_DEVICE_FILE if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) { distanceToMove += Size; moveMethod = FILE_BEGIN; } #endif LONG high = (LONG)(distanceToMove >> 32); const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); if (low == INVALID_SET_FILE_POINTER) { const DWORD lastError = ::GetLastError(); if (lastError != NO_ERROR) { // 21.07: we set (newPosition) to real position even after error. GetPosition(newPosition); SetLastError(lastError); // restore LastError return false; } } newPosition = (((UInt64)(UInt32)high) << 32) + low; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() { return Seek((Int64)position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() const throw() { UInt64 newPosition = 0; return Seek(0, newPosition) && (newPosition == 0); } bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() { return Seek(0, FILE_END, newPosition); } // ---------- CInFile --------- #ifdef Z7_DEVICE_FILE void CInFile::CorrectDeviceSize() { // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail const UInt32 kClusterSize = 1 << 14; UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); UInt64 realNewPosition; if (!Seek(pos, realNewPosition)) return; Byte *buf = (Byte *)MidAlloc(kClusterSize); bool needbackward = true; for (;;) { UInt32 processed = 0; // up test is slow for "PhysicalDrive". // processed size for latest block for "PhysicalDrive0" is 0. if (!Read1(buf, kClusterSize, processed)) break; if (processed == 0) break; needbackward = false; Size = pos + processed; if (processed != kClusterSize) break; pos += kClusterSize; } if (needbackward && pos != 0) { pos -= kClusterSize; for (;;) { // break; if (!Seek(pos, realNewPosition)) break; if (!buf) { buf = (Byte *)MidAlloc(kClusterSize); if (!buf) break; } UInt32 processed = 0; // that code doesn't work for "PhysicalDrive0" if (!Read1(buf, kClusterSize, processed)) break; if (processed != 0) { Size = pos + processed; break; } if (pos == 0) break; pos -= kClusterSize; } } MidFree(buf); } void CInFile::CalcDeviceSize(CFSTR s) { SizeDefined = false; Size = 0; if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) return; #ifdef UNDER_CE SizeDefined = true; Size = 128 << 20; #else PARTITION_INFORMATION partInfo; bool needCorrectSize = true; /* WinXP 64-bit: HDD \\.\PhysicalDrive0 (MBR): GetPartitionInfo == GeometryEx : corrrect size? (includes tail) Geometry : smaller than GeometryEx (no tail, maybe correct too?) MyGetDiskFreeSpace : FAIL Size correction is slow and block size (kClusterSize) must be small? HDD partition \\.\N: (NTFS): MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) CD-ROM drive (ISO): MyGetDiskFreeSpace : correct size. Same size can be calculated after correction Geometry == CdRomGeometry : smaller than corrrect size GetPartitionInfo == GeometryEx : larger than corrrect size Floppy \\.\a: (FAT): Geometry : correct size. CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL correction works OK for FAT. correction works OK for non-FAT, if kClusterSize = 512. */ if (GetPartitionInfo(&partInfo)) { Size = (UInt64)partInfo.PartitionLength.QuadPart; SizeDefined = true; needCorrectSize = false; if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) { FChar path[4] = { s[4], ':', '\\', 0 }; UInt64 clusterSize, totalSize, freeSize; if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) Size = totalSize; else needCorrectSize = true; } } if (!SizeDefined) { my_DISK_GEOMETRY_EX geomEx; SizeDefined = GetGeometryEx(&geomEx); if (SizeDefined) Size = (UInt64)geomEx.DiskSize.QuadPart; else { DISK_GEOMETRY geom; SizeDefined = GetGeometry(&geom); if (!SizeDefined) SizeDefined = GetCdRomGeometry(&geom); if (SizeDefined) Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; } } if (needCorrectSize && SizeDefined && Size != 0) { CorrectDeviceSize(); SeekToBegin(); } // SeekToBegin(); #endif } // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && #define MY_DEVICE_EXTRA_CODE \ IsDeviceFile = IsDevicePath(fileName); \ CalcDeviceSize(fileName); #else #define MY_DEVICE_EXTRA_CODE #endif bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { DWORD desiredAccess = GENERIC_READ; #ifdef _WIN32 if (PreserveATime) desiredAccess |= FILE_WRITE_ATTRIBUTES; #endif bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes); #ifdef _WIN32 if (res && PreserveATime) { FILETIME ft; ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF; ::SetFileTime(_handle, NULL, &ft, NULL); } #endif MY_DEVICE_EXTRA_CODE return res; } bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(CFSTR fileName) { return OpenShared(fileName, false); } // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static const UInt32 kChunkSizeMax = 1 << 22; bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() { DWORD processedLoc = 0; const bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() { #if 0 const UInt32 chunkSizeMax = (0 || IsStdStream) ? (1 << 20) : kChunkSizeMax; if (size > chunkSizeMax) size = chunkSizeMax; #else if (size > kChunkSizeMax) size = kChunkSizeMax; #endif return Read1(data, size, processedSize); } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do { UInt32 processedLoc = 0; const bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((Byte *)data + processedLoc); size -= processedLoc; } while (size); return true; } bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw() { processedSize = 0; do { UInt32 processedLoc = 0; const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size); const bool res = Read1(data, sizeLoc, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((Byte *)data + processedLoc); size -= processedLoc; } while (size); return true; } // ---------- COutFile --------- bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes) { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); } bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do { UInt32 processedLoc = 0; const bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const Byte *)data + processedLoc); size -= processedLoc; } while (size); return true; } bool COutFile::WriteFull(const void *data, size_t size) throw() { do { UInt32 processedLoc = 0; const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size); if (!WritePart(data, sizeCur, processedLoc)) return false; if (processedLoc == 0) return (size == 0); data = (const void *)((const Byte *)data + processedLoc); size -= processedLoc; } while (size); return true; } bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) throw() { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } bool COutFile::SetLength_KeepPosition(UInt64 length) throw() { UInt64 currentPos = 0; if (!GetPosition(currentPos)) return false; DWORD lastError = 0; const bool result = SetLength(length); if (!result) lastError = GetLastError(); UInt64 currentPos2; const bool result2 = Seek(currentPos, currentPos2); if (lastError != 0) SetLastError(lastError); return (result && result2); } }}} #else // _WIN32 // POSIX #include #include namespace NWindows { namespace NFile { namespace NDir { bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); } namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags, mode_t mode) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, mode); return _handle != -1; /* if (_handle == -1) return false; if (IsString1PrefixedByString2(name, "/dev/")) { // /dev/sda // IsDeviceFile = true; // for debug // SizeDefined = false; // SizeDefined = (GetDeviceSize_InBytes(Size) == 0); } return true; */ } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; /* IsDeviceFile = false; SizeDefined = false; */ return true; } bool CFileBase::GetLength(UInt64 &length) const { length = 0; // length = (UInt64)(Int64)-1; // for debug const off_t curPos = seekToCur(); if (curPos == -1) return false; const off_t lengthTemp = seek(0, SEEK_END); seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; /* // 22.00: if (lengthTemp == 1) if (IsDeviceFile && SizeDefined) { length = Size; return true; } */ return (lengthTemp != -1); } off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const { /* if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END) { printf("\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); distanceToMove += Size; moveMethod = SEEK_SET; } */ // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); // off_t res = ::lseek(_handle, distanceToMove, moveMethod); // printf("\n lseek : moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); return ::lseek(_handle, distanceToMove, moveMethod); // return res; } off_t CFileBase::seekToBegin() const throw() { return seek(0, SEEK_SET); } off_t CFileBase::seekToCur() const throw() { return seek(0, SEEK_CUR); } /* bool CFileBase::SeekToBegin() const throw() { return (::seek(0, SEEK_SET) != -1); } */ ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } /* int CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks) { // we can read "/sys/block/sda/size" "/sys/block/sda/sda1/size" - partition // #include return ioctl(_handle, BLKGETSIZE64, numBlocks); // in block size } int CFileBase::GetDeviceSize_InBytes(UInt64 &size) { size = 0; unsigned long long numBlocks; int res = my_ioctl_BLKGETSIZE64(&numBlocks); if (res == 0) size = numBlocks; // another blockSize s possible? printf("\nGetDeviceSize_InBytes res = %d, size = %lld\n", res, (long long)size); return res; } */ /* On Linux (32-bit and 64-bit): read(), write() (and similar system calls) will transfer at most 0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred. */ static const size_t kChunkSizeMax = ((size_t)1 << 22); ssize_t CInFile::read_part(void *data, size_t size) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; return ::read(_handle, data, size); } bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw() { processed = 0; do { const ssize_t res = read_part(data, size); if (res < 0) return false; if (res == 0) break; data = (void *)((Byte *)data + (size_t)res); processed += (size_t)res; size -= (size_t)res; } while (size); return true; } ///////////////////////// // COutFile bool COutFile::OpenBinary_forWrite_oflag(const char *name, int oflag) { Path = name; // change it : set it only if open is success. return OpenBinary(name, oflag, mode_for_Create); } /* windows exist non-exist posix CREATE_NEW Fail Create O_CREAT | O_EXCL CREATE_ALWAYS Trunc Create O_CREAT | O_TRUNC OPEN_ALWAYS Open Create O_CREAT OPEN_EXISTING Open Fail 0 TRUNCATE_EXISTING Trunc Fail O_TRUNC ??? // O_CREAT = If the file exists, this flag has no effect except as noted under O_EXCL below. // If O_CREAT and O_EXCL are set, open() shall fail if the file exists. // O_TRUNC : If the file exists and the file is successfully opened, its length shall be truncated to 0. */ bool COutFile::Open_EXISTING(const char *name) { return OpenBinary_forWrite_oflag(name, O_WRONLY); } bool COutFile::Create_ALWAYS(const char *name) { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_TRUNC); } bool COutFile::Create_NEW(const char *name) { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_EXCL); } bool COutFile::Create_ALWAYS_or_Open_ALWAYS(const char *name, bool createAlways) { return OpenBinary_forWrite_oflag(name, createAlways ? O_WRONLY | O_CREAT | O_TRUNC : O_WRONLY | O_CREAT); } /* bool COutFile::Create_ALWAYS_or_NEW(const char *name, bool createAlways) { return OpenBinary_forWrite_oflag(name, createAlways ? O_WRONLY | O_CREAT | O_TRUNC : O_WRONLY | O_CREAT | O_EXCL); } bool COutFile::Open_Disposition(const char *name, DWORD creationDisposition) { int flag; switch (creationDisposition) { case CREATE_NEW: flag = O_WRONLY | O_CREAT | O_EXCL; break; case CREATE_ALWAYS: flag = O_WRONLY | O_CREAT | O_TRUNC; break; case OPEN_ALWAYS: flag = O_WRONLY | O_CREAT; break; case OPEN_EXISTING: flag = O_WRONLY; break; case TRUNCATE_EXISTING: flag = O_WRONLY | O_TRUNC; break; default: SetLastError(EINVAL); return false; } return OpenBinary_forWrite_oflag(name, flag); } */ ssize_t COutFile::write_part(const void *data, size_t size) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; return ::write(_handle, data, size); } ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw() { processed = 0; do { const ssize_t res = write_part(data, size); if (res < 0) return res; if (res == 0) break; data = (const void *)((const Byte *)data + (size_t)res); processed += (size_t)res; size -= (size_t)res; } while (size); return (ssize_t)processed; } bool COutFile::SetLength(UInt64 length) throw() { const off_t len2 = (off_t)length; if ((Int64)length != len2) { SetLastError(EFBIG); return false; } // The value of the seek pointer shall not be modified by a call to ftruncate(). const int iret = ftruncate(_handle, len2); return (iret == 0); } bool COutFile::Close() { const bool res = CFileBase::Close(); if (!res) return res; if (CTime_defined || ATime_defined || MTime_defined) { /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, CTime_defined ? &CTime : NULL, ATime_defined ? &ATime : NULL, MTime_defined ? &MTime : NULL); } return res; } bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw() { // On some OS (cygwin, MacOSX ...), you must close the file before updating times // return true; if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false; if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; return true; /* struct timespec times[2]; UNUSED_VAR(cTime) if (!aTime && !mTime) return true; bool needChange; needChange = FiTime_To_timespec(aTime, times[0]); needChange |= FiTime_To_timespec(mTime, times[1]); if (!needChange) return true; return futimens(_handle, times) == 0; */ } bool COutFile::SetMTime(const CFiTime *mTime) throw() { if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; return true; } }}} #endif tmp41wklro_/CPP/Windows/FileIO.h0000444000175000001440000003143414561716600017510 0ustar nabijaczleweliusers// Windows/FileIO.h #ifndef ZIP7_INC_WINDOWS_FILE_IO_H #define ZIP7_INC_WINDOWS_FILE_IO_H #include "../Common/MyWindows.h" #define Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) #define Z7_WIN_IO_REPARSE_TAG_SYMLINK (0xA000000CL) #define Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL) #define Z7_WIN_SYMLINK_FLAG_RELATIVE 1 // what the meaning of that FLAG or field (2)? #define Z7_WIN_LX_SYMLINK_FLAG 2 #ifdef _WIN32 #if defined(_WIN32) && !defined(UNDER_CE) #include #endif #else #include #include #endif #include "../Common/MyString.h" #include "../Common/MyBuffer.h" #include "../Windows/TimeUtils.h" #include "Defs.h" HRESULT GetLastError_noZero_HRESULT(); #define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER #define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER #define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER namespace NWindows { namespace NFile { #if defined(_WIN32) && !defined(UNDER_CE) bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL); #endif struct CReparseShortInfo { unsigned Offset; unsigned Size; bool Parse(const Byte *p, size_t size); }; struct CReparseAttr { UInt32 Tag; UInt32 Flags; UString SubsName; UString PrintName; AString WslName; bool HeaderError; bool TagIsUnknown; bool MinorError; DWORD ErrorCode; CReparseAttr(): Tag(0), Flags(0) {} // Parse() // returns (true) and (ErrorCode = 0), if (it'a correct known link) // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag bool Parse(const Byte *p, size_t size); bool IsMountPoint() const { return Tag == Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction bool IsSymLink_Win() const { return Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK; } bool IsSymLink_WSL() const { return Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK; } bool IsRelative_Win() const { return Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE; } bool IsRelative_WSL() const { if (WslName.IsEmpty()) return true; char c = WslName[0]; return !IS_PATH_SEPAR(c); } // bool IsVolume() const; bool IsOkNamePair() const; UString GetPath() const; }; #ifdef _WIN32 #define CFiInfo BY_HANDLE_FILE_INFORMATION #define ST_MTIME(st) (st).ftLastWriteTime #else #define CFiInfo stat #endif #ifdef _WIN32 namespace NIO { bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); bool DeleteReparseData(CFSTR path); class CFileBase MY_UNCOPYABLE { protected: HANDLE _handle; bool Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); public: bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const { return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, outBuffer, outSize, bytesReturned, overlapped)); } bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); } bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const { DWORD bytesReturned; return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); } public: bool PreserveATime; #if 0 bool IsStdStream; bool IsStdPipeStream; #endif #ifdef Z7_DEVICE_FILE bool IsDeviceFile; bool SizeDefined; UInt64 Size; // it can be larger than real available size #endif CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) #if 0 , IsStdStream(false), , IsStdPipeStream(false) #endif {} ~CFileBase() { Close(); } HANDLE GetHandle() const { return _handle; } // void Detach() { _handle = INVALID_HANDLE_VALUE; } bool Close() throw(); bool GetPosition(UInt64 &position) const throw(); bool GetLength(UInt64 &length) const throw(); bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); bool Seek(UInt64 position, UInt64 &newPosition) const throw(); bool SeekToBegin() const throw(); bool SeekToEnd(UInt64 &newPosition) const throw(); bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) { // probably it can work for complex paths: unsupported by another things NIO::CFileBase file; if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) return false; return file.GetFileInformation(info); } }; #ifndef UNDER_CE #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) // #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) // IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP #define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) struct my_DISK_GEOMETRY_EX { DISK_GEOMETRY Geometry; LARGE_INTEGER DiskSize; BYTE Data[1]; }; #endif class CInFile: public CFileBase { #ifdef Z7_DEVICE_FILE #ifndef UNDER_CE bool GetGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } bool GetCdRomGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } bool GetPartitionInfo(PARTITION_INFORMATION *res) { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } #endif void CorrectDeviceSize(); void CalcDeviceSize(CFSTR name); #endif public: bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(CFSTR fileName, bool shareForWrite); bool Open(CFSTR fileName); #if 0 bool AttachStdIn() { IsDeviceFile = false; const HANDLE h = GetStdHandle(STD_INPUT_HANDLE); if (h == INVALID_HANDLE_VALUE || !h) return false; IsStdStream = true; IsStdPipeStream = true; _handle = h; return true; } #endif #ifndef UNDER_CE bool Open_for_ReadAttributes(CFSTR fileName) { return Create(fileName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS); // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory. } bool Open_for_FileRenameInformation(CFSTR fileName) { return Create(fileName, DELETE | SYNCHRONIZE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory. } bool OpenReparse(CFSTR fileName) { // 17.02 fix: to support Windows XP compatibility junctions: // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ return Create(fileName, 0, // Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); } #endif bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); }; class COutFile: public CFileBase { bool Open_Disposition(CFSTR fileName, DWORD creationDisposition); public: bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open_EXISTING(CFSTR fileName) { return Open_Disposition(fileName, OPEN_EXISTING); } bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways) { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : OPEN_ALWAYS); } bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways) { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : CREATE_NEW); } bool Create_ALWAYS(CFSTR fileName) { return Open_Disposition(fileName, CREATE_ALWAYS); } bool Create_NEW(CFSTR fileName) { return Open_Disposition(fileName, CREATE_NEW); } bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes); bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); bool SetMTime(const CFiTime *mTime) throw(); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); bool WriteFull(const void *data, size_t size) throw(); bool SetEndOfFile() throw(); bool SetLength(UInt64 length) throw(); bool SetLength_KeepPosition(UInt64 length) throw(); }; } #else // _WIN32 namespace NIO { bool GetReparseData(CFSTR path, CByteBuffer &reparseData); // bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); // parameters are in reverse order of symlink() function !!! bool SetSymLink(CFSTR from, CFSTR to); bool SetSymLink_UString(CFSTR from, const UString &to); class CFileBase { protected: int _handle; /* bool IsDeviceFile; bool SizeDefined; UInt64 Size; // it can be larger than real available size */ bool OpenBinary(const char *name, int flags, mode_t mode = 0666); public: bool PreserveATime; #if 0 bool IsStdStream; #endif CFileBase(): _handle(-1), PreserveATime(false) #if 0 , IsStdStream(false) #endif {} ~CFileBase() { Close(); } // void Detach() { _handle = -1; } bool Close(); bool GetLength(UInt64 &length) const; off_t seek(off_t distanceToMove, int moveMethod) const; off_t seekToBegin() const throw(); off_t seekToCur() const throw(); // bool SeekToBegin() throw(); int my_fstat(struct stat *st) const { return fstat(_handle, st); } /* int my_ioctl_BLKGETSIZE64(unsigned long long *val); int GetDeviceSize_InBytes(UInt64 &size); void CalcDeviceSize(CFSTR s); */ }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); #if 0 bool AttachStdIn() { _handle = GetStdHandle(STD_INPUT_HANDLE); if (_handle == INVALID_HANDLE_VALUE || !_handle) return false; IsStdStream = true; } #endif ssize_t read_part(void *data, size_t size) throw(); // ssize_t read_full(void *data, size_t size, size_t &processed); bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); }; class COutFile: public CFileBase { bool CTime_defined; bool ATime_defined; bool MTime_defined; CFiTime CTime; CFiTime ATime; CFiTime MTime; AString Path; ssize_t write_part(const void *data, size_t size) throw(); bool OpenBinary_forWrite_oflag(const char *name, int oflag); public: mode_t mode_for_Create; COutFile(): CTime_defined(false), ATime_defined(false), MTime_defined(false), mode_for_Create(0666) {} bool Close(); bool Open_EXISTING(CFSTR fileName); bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways); bool Create_ALWAYS(CFSTR fileName); bool Create_NEW(CFSTR fileName); // bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways); // bool Open_Disposition(const char *name, DWORD creationDisposition); ssize_t write_full(const void *data, size_t size, size_t &processed) throw(); bool WriteFull(const void *data, size_t size) throw() { size_t processed; ssize_t res = write_full(data, size, processed); if (res == -1) return false; return processed == size; } bool SetLength(UInt64 length) throw(); bool SetLength_KeepPosition(UInt64 length) throw() { return SetLength(length); } bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); bool SetMTime(const CFiTime *mTime) throw(); }; } #endif // _WIN32 }} #endif tmp41wklro_/CPP/Windows/FileLink.cpp0000444000175000001440000003463714475541740020446 0ustar nabijaczleweliusers// Windows/FileLink.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #ifndef _WIN32 #include #endif #ifdef Z7_DEVICE_FILE #include "../../C/Alloc.h" #endif #include "../Common/UTFConvert.h" #include "../Common/StringConvert.h" #include "FileDir.h" #include "FileFind.h" #include "FileIO.h" #include "FileName.h" #ifdef Z7_OLD_WIN_SDK #ifndef ERROR_INVALID_REPARSE_DATA #define ERROR_INVALID_REPARSE_DATA 4392L #endif #ifndef ERROR_REPARSE_TAG_INVALID #define ERROR_REPARSE_TAG_INVALID 4393L #endif #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { using namespace NName; /* Reparse Points (Junctions and Symbolic Links): struct { UInt32 Tag; UInt16 Size; // not including starting 8 bytes UInt16 Reserved; // = 0 UInt16 SubstituteOffset; // offset in bytes from start of namesChars UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL UInt16 PrintOffset; // offset in bytes from start of namesChars UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL [UInt32] Flags; // for Symbolic Links only. UInt16 namesChars[] } MOUNT_POINT (Junction point): 1) there is NUL wchar after path 2) Default Order in table: Substitute Path Print Path 3) pathnames can not contain dot directory names SYMLINK: 1) there is no NUL wchar after path 2) Default Order in table: Print Path Substitute Path */ /* Win10 WSL2: admin rights + sudo: it creates normal windows symbolic link. in another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point. */ /* static const UInt32 kReparseFlags_Alias = (1 << 29); static const UInt32 kReparseFlags_HighLatency = (1 << 30); static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); #define Z7_WIN_IO_REPARSE_TAG_HSM (0xC0000004L) #define Z7_WIN_IO_REPARSE_TAG_HSM2 (0x80000006L) #define Z7_WIN_IO_REPARSE_TAG_SIS (0x80000007L) #define Z7_WIN_IO_REPARSE_TAG_WIM (0x80000008L) #define Z7_WIN_IO_REPARSE_TAG_CSV (0x80000009L) #define Z7_WIN_IO_REPARSE_TAG_DFS (0x8000000AL) #define Z7_WIN_IO_REPARSE_TAG_DFSR (0x80000012L) */ #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) static const wchar_t * const k_LinkPrefix = L"\\??\\"; static const unsigned k_LinkPrefix_Size = 4; static bool IsLinkPrefix(const wchar_t *s) { return IsString1PrefixedByString2(s, k_LinkPrefix); } /* static const wchar_t * const k_VolumePrefix = L"Volume{"; static const bool IsVolumeName(const wchar_t *s) { return IsString1PrefixedByString2(s, k_VolumePrefix); } */ #if defined(_WIN32) && !defined(UNDER_CE) #define Set16(p, v) SetUi16(p, v) #define Set32(p, v) SetUi32(p, v) static void WriteString(Byte *dest, const wchar_t *path) { for (;;) { wchar_t c = *path++; if (c == 0) return; Set16(dest, (UInt16)c) dest += 2; } } bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) { bool isAbs = IsAbsolutePath(path); if (!isAbs && !isSymLink) return false; if (isWSL) { // unsupported characters probably use Replacement Character UTF-16 0xFFFD AString utf; ConvertUnicodeToUTF8(path, utf); const size_t size = 4 + utf.Len(); if (size != (UInt16)size) return false; dest.Alloc(8 + size); Byte *p = dest; Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) Set16(p + 4, (UInt16)(size)) Set16(p + 6, 0) Set32(p + 8, Z7_WIN_LX_SYMLINK_FLAG) memcpy(p + 12, utf.Ptr(), utf.Len()); return true; } // usual symbolic LINK (NOT WSL) bool needPrintName = true; if (IsSuperPath(path)) { path += kSuperPathPrefixSize; if (!IsDrivePath(path)) needPrintName = false; } const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; size_t len2 = (size_t)MyStringLen(path) * 2; const size_t len1 = len2 + add_Prefix_Len * 2; if (!needPrintName) len2 = 0; size_t totalNamesSize = (len1 + len2); /* some WIM imagex software uses old scheme for symbolic links. so we can old scheme for byte to byte compatibility */ bool newOrderScheme = isSymLink; // newOrderScheme = false; if (!newOrderScheme) totalNamesSize += 2 * 2; const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; if (size != (UInt16)size) return false; dest.Alloc(size); memset(dest, 0, size); const UInt32 tag = isSymLink ? Z7_WIN_IO_REPARSE_TAG_SYMLINK : Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; Byte *p = dest; Set32(p, tag) Set16(p + 4, (UInt16)(size - 8)) Set16(p + 6, 0) p += 8; unsigned subOffs = 0; unsigned printOffs = 0; if (newOrderScheme) subOffs = (unsigned)len2; else printOffs = (unsigned)len1 + 2; Set16(p + 0, (UInt16)subOffs) Set16(p + 2, (UInt16)len1) Set16(p + 4, (UInt16)printOffs) Set16(p + 6, (UInt16)len2) p += 8; if (isSymLink) { UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE; Set32(p, flags) p += 4; } if (add_Prefix_Len != 0) WriteString(p + subOffs, k_LinkPrefix); WriteString(p + subOffs + add_Prefix_Len * 2, path); if (needPrintName) WriteString(p + printOffs, path); return true; } #endif // defined(_WIN32) && !defined(UNDER_CE) static void GetString(const Byte *p, unsigned len, UString &res) { wchar_t *s = res.GetBuf(len); unsigned i; for (i = 0; i < len; i++) { wchar_t c = Get16(p + i * 2); if (c == 0) break; s[i] = c; } s[i] = 0; res.ReleaseBuf_SetLen(i); } bool CReparseAttr::Parse(const Byte *p, size_t size) { ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; HeaderError = true; TagIsUnknown = true; MinorError = false; if (size < 8) return false; Tag = Get32(p); if (Get16(p + 6) != 0) // padding return false; unsigned len = Get16(p + 4); p += 8; size -= 8; if (len != size) // if (len > size) return false; /* if ((type & kReparseFlags_Alias) == 0 || (type & kReparseFlags_Microsoft) == 0 || (type & 0xFFFF) != 3) */ HeaderError = false; if ( Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT && Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK && Tag != Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) { // for unsupported reparse points ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID return false; } TagIsUnknown = false; if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) { if (len < 4) return false; Flags = Get32(p); // maybe it's not Flags if (Flags != Z7_WIN_LX_SYMLINK_FLAG) return false; len -= 4; p += 4; char *s = WslName.GetBuf(len); unsigned i; for (i = 0; i < len; i++) { char c = (char)p[i]; s[i] = c; if (c == 0) break; } WslName.ReleaseBuf_SetEnd(i); MinorError = (i != len); ErrorCode = 0; return true; } if (len < 8) return false; unsigned subOffs = Get16(p); unsigned subLen = Get16(p + 2); unsigned printOffs = Get16(p + 4); unsigned printLen = Get16(p + 6); len -= 8; p += 8; Flags = 0; if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK) { if (len < 4) return false; Flags = Get32(p); len -= 4; p += 4; } if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) return false; if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) return false; GetString(p + subOffs, subLen >> 1, SubsName); GetString(p + printOffs, printLen >> 1, PrintName); ErrorCode = 0; return true; } bool CReparseShortInfo::Parse(const Byte *p, size_t size) { const Byte *start = p; Offset= 0; Size = 0; if (size < 8) return false; UInt32 Tag = Get32(p); UInt32 len = Get16(p + 4); if (len + 8 > size) return false; /* if ((type & kReparseFlags_Alias) == 0 || (type & kReparseFlags_Microsoft) == 0 || (type & 0xFFFF) != 3) */ if (Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT && Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK) // return true; return false; if (Get16(p + 6) != 0) // padding return false; p += 8; size -= 8; if (len != size) // do we need that check? return false; if (len < 8) return false; unsigned subOffs = Get16(p); unsigned subLen = Get16(p + 2); unsigned printOffs = Get16(p + 4); unsigned printLen = Get16(p + 6); len -= 8; p += 8; // UInt32 Flags = 0; if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK) { if (len < 4) return false; // Flags = Get32(p); len -= 4; p += 4; } if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) return false; if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) return false; Offset = (unsigned)(p - start) + subOffs; Size = subLen; return true; } bool CReparseAttr::IsOkNamePair() const { if (IsLinkPrefix(SubsName)) { if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) return PrintName.IsEmpty(); if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) return true; } return wcscmp(SubsName, PrintName) == 0; } /* bool CReparseAttr::IsVolume() const { if (!IsLinkPrefix(SubsName)) return false; return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); } */ UString CReparseAttr::GetPath() const { if (IsSymLink_WSL()) { UString u; // if (CheckUTF8(attr.WslName) if (!ConvertUTF8ToUnicode(WslName, u)) MultiByteToUnicodeString2(u, WslName); return u; } UString s (SubsName); if (IsLinkPrefix(s)) { s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) s.DeleteFrontal(k_LinkPrefix_Size); } return s; } #ifdef Z7_DEVICE_FILE namespace NSystem { bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif // Z7_DEVICE_FILE #if defined(_WIN32) && !defined(UNDER_CE) namespace NIO { bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) { reparseData.Free(); CInFile file; if (!file.OpenReparse(path)) return false; if (fileInfo) file.GetFileInformation(fileInfo); const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; CByteArr buf(kBufSize); DWORD returnedSize; if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) return false; reparseData.CopyFrom(buf, returnedSize); return true; } static bool CreatePrefixDirOfFile(CFSTR path) { FString path2 (path); int pos = path2.ReverseFind_PathSepar(); if (pos < 0) return true; #ifdef _WIN32 if (pos == 2 && path2[1] == L':') return true; // we don't create Disk folder; #endif path2.DeleteFrom((unsigned)pos); return NDir::CreateComplexDir(path2); } static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size) { COutFile file; if (!file.Open(path, FILE_SHARE_WRITE, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) return false; DWORD returnedSize; return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize); } // If there is Reparse data already, it still writes new Reparse data bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) { NFile::NFind::CFileInfo fi; if (fi.Find(path)) { if (fi.IsDir() != isDir) { ::SetLastError(ERROR_DIRECTORY); return false; } } else { if (isDir) { if (!NDir::CreateComplexDir(path)) return false; } else { CreatePrefixDirOfFile(path); COutFile file; if (!file.Create_NEW(path)) return false; } } return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size); } bool DeleteReparseData(CFSTR path) { CByteBuffer reparseData; if (!GetReparseData(path, reparseData, NULL)) return false; /* MSDN: The tag specified in the ReparseTag member of this structure must match the tag of the reparse point to be deleted, and the ReparseDataLength member must be zero */ #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8 if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE) { SetLastError(ERROR_INVALID_REPARSE_DATA); return false; } BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; memset(buf, 0, sizeof(buf)); memcpy(buf, reparseData, 4); // tag return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf)); } } #endif // defined(_WIN32) && !defined(UNDER_CE) #ifndef _WIN32 namespace NIO { bool GetReparseData(CFSTR path, CByteBuffer &reparseData) { reparseData.Free(); #define MAX_PATHNAME_LEN 1024 char buf[MAX_PATHNAME_LEN + 2]; const size_t request = sizeof(buf) - 1; // printf("\nreadlink() path = %s \n", path); const ssize_t size = readlink(path, buf, request); // there is no tail zero if (size < 0) return false; if ((size_t)size >= request) { SetLastError(EINVAL); // check it: ENAMETOOLONG return false; } // printf("\nreadlink() res = %s size = %d \n", buf, (int)size); reparseData.CopyFrom((const Byte *)buf, (size_t)size); return true; } /* // If there is Reparse data already, it still writes new Reparse data bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) { // AString s; // s.SetFrom_CalcLen(data, size); // return (symlink(s, path) == 0); UNUSED_VAR(path) UNUSED_VAR(isDir) UNUSED_VAR(data) UNUSED_VAR(size) SetLastError(ENOSYS); return false; } */ bool SetSymLink(CFSTR from, CFSTR to) { // printf("\nsymlink() %s -> %s\n", from, to); int ir; // ir = unlink(path); // if (ir == 0) ir = symlink(to, from); return (ir == 0); } bool SetSymLink_UString(CFSTR from, const UString &to) { AString utf; ConvertUnicodeToUTF8(to, utf); return SetSymLink(from, utf); } } #endif // !_WIN32 }} tmp41wklro_/CPP/Windows/FileMapping.cpp0000444000175000001440000000023112450772527021123 0ustar nabijaczleweliusers// Windows/FileMapping.cpp #include "StdAfx.h" #include "FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} tmp41wklro_/CPP/Windows/FileMapping.h0000444000175000001440000000311314357314620020564 0ustar nabijaczleweliusers// Windows/FileMapping.h #ifndef ZIP7_INC_WINDOWS_FILE_MAPPING_H #define ZIP7_INC_WINDOWS_FILE_MAPPING_H #include "../Common/MyTypes.h" #include "Handle.h" namespace NWindows { class CFileMapping: public CHandle { public: WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name) { _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name); return ::GetLastError(); } WRes Open(DWORD #ifndef UNDER_CE desiredAccess #endif , LPCTSTR name) { #ifdef UNDER_CE WRes res = Create(PAGE_READONLY, 0, name); if (res == ERROR_ALREADY_EXISTS) return 0; Close(); if (res == 0) res = ERROR_FILE_NOT_FOUND; return res; #else _handle = ::OpenFileMapping(desiredAccess, FALSE, name); if (_handle != NULL) return 0; return ::GetLastError(); #endif } LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap); } #ifndef UNDER_CE LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress); } #endif }; class CFileUnmapper { const void *_data; public: CFileUnmapper(const void *data) : _data(data) {} ~CFileUnmapper() { ::UnmapViewOfFile(_data); } }; } #endif tmp41wklro_/CPP/Windows/FileName.cpp0000444000175000001440000005312714600534300020404 0ustar nabijaczleweliusers// Windows/FileName.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include "../Common/StringConvert.h" #endif #include "FileDir.h" #include "FileName.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NName { #define IS_SEPAR(c) IS_PATH_SEPAR(c) int FindSepar(const wchar_t *s) throw() { for (const wchar_t *p = s;; p++) { const wchar_t c = *p; if (c == 0) return -1; if (IS_SEPAR(c)) return (int)(p - s); } } #ifndef USE_UNICODE_FSTRING int FindSepar(const FChar *s) throw() { for (const FChar *p = s;; p++) { const FChar c = *p; if (c == 0) return -1; if (IS_SEPAR(c)) return (int)(p - s); } } #endif #ifndef USE_UNICODE_FSTRING void NormalizeDirPathPrefix(FString &dirPath) { if (dirPath.IsEmpty()) return; if (!IsPathSepar(dirPath.Back())) dirPath.Add_PathSepar(); } #endif void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (!IsPathSepar(dirPath.Back())) dirPath.Add_PathSepar(); } #ifdef _WIN32 #ifndef USE_UNICODE_FSTRING #ifdef Z7_LONG_PATH static void NormalizeDirSeparators(UString &s) { const unsigned len = s.Len(); for (unsigned i = 0; i < len; i++) if (s[i] == '/') s.ReplaceOneCharAtPos(i, WCHAR_PATH_SEPARATOR); } #endif #endif void NormalizeDirSeparators(FString &s) { const unsigned len = s.Len(); for (unsigned i = 0; i < len; i++) if (s[i] == '/') s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR); } #endif #define IS_LETTER_CHAR(c) ((((unsigned)(int)(c) | 0x20) - (unsigned)'a' <= (unsigned)('z' - 'a'))) bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } bool IsAltPathPrefix(CFSTR s) throw() { unsigned len = MyStringLen(s); if (len == 0) return false; if (s[len - 1] != ':') return false; #if defined(_WIN32) && !defined(UNDER_CE) if (IsDevicePath(s)) return false; if (IsSuperPath(s)) { s += kSuperPathPrefixSize; len -= kSuperPathPrefixSize; } if (len == 2 && IsDrivePath2(s)) return false; #endif return true; } #if defined(_WIN32) && !defined(UNDER_CE) const char * const kSuperPathPrefix = "\\\\?\\"; #ifdef Z7_LONG_PATH static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; #endif #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) #define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3])) #define IS_UNC_WITH_SLASH(s) ( \ ((s)[0] == 'U' || (s)[0] == 'u') \ && ((s)[1] == 'N' || (s)[1] == 'n') \ && ((s)[2] == 'C' || (s)[2] == 'c') \ && IS_SEPAR((s)[3])) bool IsDevicePath(CFSTR s) throw() { #ifdef UNDER_CE s = s; return false; /* // actually we don't know the way to open device file in WinCE. unsigned len = MyStringLen(s); if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK")) return false; if (s[4] != ':') return false; // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); */ #else if (!IS_DEVICE_PATH(s)) return false; unsigned len = MyStringLen(s); if (len == 6 && s[5] == ':') return true; if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) return false; for (unsigned i = 17; i < len; i++) if (s[i] < '0' || s[i] > '9') return false; return true; #endif } bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } bool IsNetworkPath(CFSTR s) throw() { if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) return false; if (IsSuperUncPath(s)) return true; FChar c = s[2]; return (c != '.' && c != '?'); } unsigned GetNetworkServerPrefixSize(CFSTR s) throw() { if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) return 0; unsigned prefixSize = 2; if (IsSuperUncPath(s)) prefixSize = kSuperUncPathPrefixSize; else { FChar c = s[2]; if (c == '.' || c == '?') return 0; } const int pos = FindSepar(s + prefixSize); if (pos < 0) return 0; return prefixSize + (unsigned)(pos + 1); } bool IsNetworkShareRootPath(CFSTR s) throw() { const unsigned prefixSize = GetNetworkServerPrefixSize(s); if (prefixSize == 0) return false; s += prefixSize; const int pos = FindSepar(s); if (pos < 0) return true; return s[(unsigned)pos + 1] == 0; } static const unsigned kDrivePrefixSize = 3; /* c:\ */ bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } // bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } bool IsAltStreamPrefixWithColon(const UString &s) throw() { if (s.IsEmpty()) return false; if (s.Back() != ':') return false; unsigned pos = 0; if (IsSuperPath(s)) pos = kSuperPathPrefixSize; if (s.Len() - pos == 2 && IsDrivePath2(s.Ptr(pos))) return false; return true; } bool If_IsSuperPath_RemoveSuperPrefix(UString &s) { if (!IsSuperPath(s)) return false; unsigned start = 0; unsigned count = kSuperPathPrefixSize; const wchar_t *s2 = s.Ptr(kSuperPathPrefixSize); if (IS_UNC_WITH_SLASH(s2)) { start = 2; count = kSuperUncPathPrefixSize - 2; } s.Delete(start, count); return true; } #ifndef USE_UNICODE_FSTRING bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } // bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } #endif // USE_UNICODE_FSTRING bool IsDrivePath_SuperAllowed(CFSTR s) throw() { if (IsSuperPath(s)) s += kSuperPathPrefixSize; return IsDrivePath(s); } bool IsDriveRootPath_SuperAllowed(CFSTR s) throw() { if (IsSuperPath(s)) s += kSuperPathPrefixSize; return IsDrivePath(s) && s[kDrivePrefixSize] == 0; } bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]) || IsDrivePath2(s); } int FindAltStreamColon(CFSTR path) throw() { unsigned i = 0; if (IsDrivePath2(path)) i = 2; int colonPos = -1; for (;; i++) { FChar c = path[i]; if (c == 0) return colonPos; if (c == ':') { if (colonPos < 0) colonPos = (int)i; continue; } if (IS_SEPAR(c)) colonPos = -1; } } #ifndef USE_UNICODE_FSTRING static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) { // Network path: we look "server\path\" as root prefix const int pos = FindSepar(s); if (pos < 0) return 0; const int pos2 = FindSepar(s + (unsigned)pos + 1); if (pos2 < 0) return 0; return (unsigned)pos + (unsigned)pos2 + 2; } static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) { if (IsDrivePath(s)) return kDrivePrefixSize; if (!IS_SEPAR(s[0])) return 0; if (s[1] == 0 || !IS_SEPAR(s[1])) return 1; const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); return (size == 0) ? 0 : 2 + size; } static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) { if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) { const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; } // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" const int pos = FindSepar(s + kSuperPathPrefixSize); if (pos < 0) return 0; return kSuperPathPrefixSize + (unsigned)pos + 1; } unsigned GetRootPrefixSize(CFSTR s) throw() { if (IS_DEVICE_PATH(s)) return kDevicePathPrefixSize; if (IsSuperPath(s)) return GetRootPrefixSize_Of_SuperPath(s); return GetRootPrefixSize_Of_SimplePath(s); } #endif // USE_UNICODE_FSTRING static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() { // Network path: we look "server\path\" as root prefix int pos = FindSepar(s); if (pos < 0) return 0; int pos2 = FindSepar(s + (unsigned)pos + 1); if (pos2 < 0) return 0; return (unsigned)(pos + pos2 + 2); } static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() { if (IsDrivePath(s)) return kDrivePrefixSize; if (!IS_SEPAR(s[0])) return 0; if (s[1] == 0 || !IS_SEPAR(s[1])) return 1; unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); return (size == 0) ? 0 : 2 + size; } static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() { if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) { unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; } // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" int pos = FindSepar(s + kSuperPathPrefixSize); if (pos < 0) return 0; return kSuperPathPrefixSize + (unsigned)(pos + 1); } unsigned GetRootPrefixSize(const wchar_t *s) throw() { if (IS_DEVICE_PATH(s)) return kDevicePathPrefixSize; if (IsSuperPath(s)) return GetRootPrefixSize_Of_SuperPath(s); return GetRootPrefixSize_Of_SimplePath(s); } #else // _WIN32 bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); } #ifndef USE_UNICODE_FSTRING unsigned GetRootPrefixSize(CFSTR s) throw(); unsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } #endif unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } #endif // _WIN32 #ifndef UNDER_CE #ifdef USE_UNICODE_FSTRING #define GetCurDir NDir::GetCurrentDir #else static bool GetCurDir(UString &path) { path.Empty(); FString s; if (!NDir::GetCurrentDir(s)) return false; path = fs2us(s); return true; } #endif static bool ResolveDotsFolders(UString &s) { #ifdef _WIN32 // s.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif for (unsigned i = 0;;) { const wchar_t c = s[i]; if (c == 0) return true; if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) { const wchar_t c1 = s[i + 1]; if (c1 == '.') { const wchar_t c2 = s[i + 2]; if (IS_SEPAR(c2) || c2 == 0) { if (i == 0) return false; int k = (int)i - 2; i += 2; for (;; k--) { if (k < 0) return false; if (!IS_SEPAR(s[(unsigned)k])) break; } do k--; while (k >= 0 && !IS_SEPAR(s[(unsigned)k])); unsigned num; if (k >= 0) { num = i - (unsigned)k; i = (unsigned)k; } else { num = (c2 == 0 ? i : (i + 1)); i = 0; } s.Delete(i, num); continue; } } else if (IS_SEPAR(c1) || c1 == 0) { unsigned num = 2; if (i != 0) i--; else if (c1 == 0) num = 1; s.Delete(i, num); continue; } } i++; } } #endif // UNDER_CE #define LONG_PATH_DOTS_FOLDERS_PARSING /* Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ To solve that problem we check such path: - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain */ #ifdef LONG_PATH_DOTS_FOLDERS_PARSING #ifndef UNDER_CE static bool AreThereDotsFolders(CFSTR s) { for (unsigned i = 0;; i++) { FChar c = s[i]; if (c == 0) return false; if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) { FChar c1 = s[i + 1]; if (c1 == 0 || IS_SEPAR(c1) || (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2])))) return true; } } } #endif #endif // LONG_PATH_DOTS_FOLDERS_PARSING #ifdef Z7_LONG_PATH /* Most of Windows versions have problems, if some file or dir name contains '.' or ' ' at the end of name (Bad Path). To solve that problem, we always use Super Path ("\\?\" prefix and full path) in such cases. Note that "." and ".." are not bad names. There are 3 cases: 1) If the path is already Super Path, we use that path 2) If the path is not Super Path : 2.1) Bad Path; we use only Super Path. 2.2) Good Path; we use Main Path. If it fails, we use Super Path. NeedToUseOriginalPath returns: kSuperPathType_UseOnlyMain : Super already kSuperPathType_UseOnlySuper : not Super, Bad Path kSuperPathType_UseMainAndSuper : not Super, Good Path */ int GetUseSuperPathType(CFSTR s) throw() { if (IsSuperOrDevicePath(s)) { #ifdef LONG_PATH_DOTS_FOLDERS_PARSING if ((s)[2] != '.') if (AreThereDotsFolders(s + kSuperPathPrefixSize)) return kSuperPathType_UseOnlySuper; #endif return kSuperPathType_UseOnlyMain; } for (unsigned i = 0;; i++) { FChar c = s[i]; if (c == 0) return kSuperPathType_UseMainAndSuper; if (c == '.' || c == ' ') { FChar c2 = s[i + 1]; if (c2 == 0 || IS_SEPAR(c2)) { // if it's "." or "..", it's not bad name. if (c == '.') { if (i == 0 || IS_SEPAR(s[i - 1])) continue; if (s[i - 1] == '.') { if (i - 1 == 0 || IS_SEPAR(s[i - 2])) continue; } } return kSuperPathType_UseOnlySuper; } } } } /* returns false in two cases: - if GetCurDir was used, and GetCurDir returned error. - if we can't resolve ".." name. if path is ".", "..", res is empty. if it's Super Path already, res is empty. for \**** , and if GetCurDir is not drive (c:\), res is empty for absolute paths, returns true, res is Super path. */ static bool GetSuperPathBase(CFSTR s, UString &res) { res.Empty(); FChar c = s[0]; if (c == 0) return true; if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) return true; if (IsSuperOrDevicePath(s)) { #ifdef LONG_PATH_DOTS_FOLDERS_PARSING if ((s)[2] == '.') return true; // we will return true here, so we will try to use these problem paths. if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) return true; UString temp = fs2us(s); const unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); if (fixedSize == 0) return true; UString rem = temp.Ptr(fixedSize); if (!ResolveDotsFolders(rem)) return true; temp.DeleteFrom(fixedSize); res += temp; res += rem; #endif return true; } if (IS_SEPAR(c)) { if (IS_SEPAR(s[1])) { UString temp = fs2us(s + 2); const unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); // we ignore that error to allow short network paths server\share? /* if (fixedSize == 0) return false; */ UString rem = temp.Ptr(fixedSize); if (!ResolveDotsFolders(rem)) return false; res += kSuperUncPrefix; temp.DeleteFrom(fixedSize); res += temp; res += rem; return true; } } else { if (IsDrivePath2(s)) { UString temp = fs2us(s); unsigned prefixSize = 2; if (IsDrivePath(s)) prefixSize = kDrivePrefixSize; UString rem = temp.Ptr(prefixSize); if (!ResolveDotsFolders(rem)) return true; res += kSuperPathPrefix; temp.DeleteFrom(prefixSize); res += temp; res += rem; return true; } } UString curDir; if (!GetCurDir(curDir)) return false; NormalizeDirPathPrefix(curDir); unsigned fixedSizeStart = 0; unsigned fixedSize = 0; const char *superMarker = NULL; if (IsSuperPath(curDir)) { fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); if (fixedSize == 0) return false; } else { if (IsDrivePath(curDir)) { superMarker = kSuperPathPrefix; fixedSize = kDrivePrefixSize; } else { if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) return false; fixedSizeStart = 2; fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); if (fixedSize == 0) return false; superMarker = kSuperUncPrefix; } } UString temp; if (IS_SEPAR(c)) { temp = fs2us(s + 1); } else { temp += &curDir[fixedSizeStart + fixedSize]; temp += fs2us(s); } if (!ResolveDotsFolders(temp)) return false; if (superMarker) res += superMarker; res += curDir.Mid(fixedSizeStart, fixedSize); res += temp; return true; } /* In that case if GetSuperPathBase doesn't return new path, we don't need to use same path that was used as main path GetSuperPathBase superPath.IsEmpty() onlyIfNew false * * GetCurDir Error true false * use Super path true true true don't use any path, we already used mainPath true true false use main path as Super Path, we don't try mainMath That case is possible now if GetCurDir returns unknown type of path (not drive and not network) We can change that code if we want to try mainPath, if GetSuperPathBase returns error, and we didn't try mainPath still. If we want to work that way, we don't need to use GetSuperPathBase return code. */ bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) { if (GetSuperPathBase(path, superPath)) { if (superPath.IsEmpty()) { // actually the only possible when onlyIfNew == true and superPath is empty // is case when if (onlyIfNew) return false; superPath = fs2us(path); } NormalizeDirSeparators(superPath); return true; } return false; } bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) { if (!GetSuperPathBase(s1, d1) || !GetSuperPathBase(s2, d2)) return false; NormalizeDirSeparators(d1); NormalizeDirSeparators(d2); if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) return false; if (d1.IsEmpty()) d1 = fs2us(s1); if (d2.IsEmpty()) d2 = fs2us(s2); return true; } /* // returns true, if we need additional use with New Super path. bool GetSuperPath(CFSTR path, UString &superPath) { if (GetSuperPathBase(path, superPath)) return !superPath.IsEmpty(); return false; } */ #endif // Z7_LONG_PATH bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) { res = s; #ifdef UNDER_CE if (!IS_SEPAR(s[0])) { if (!dirPrefix) return false; res = dirPrefix; res += s; } #else const unsigned prefixSize = GetRootPrefixSize(s); if (prefixSize != 0) #ifdef _WIN32 if (prefixSize != 1) #endif { if (!AreThereDotsFolders(s + prefixSize)) return true; UString rem = fs2us(s + prefixSize); if (!ResolveDotsFolders(rem)) return true; // maybe false; res.DeleteFrom(prefixSize); res += us2fs(rem); return true; } UString curDir; if (dirPrefix && prefixSize == 0) curDir = fs2us(dirPrefix); // we use (dirPrefix), only if (s) path is relative else { if (!GetCurDir(curDir)) return false; } NormalizeDirPathPrefix(curDir); unsigned fixedSize = GetRootPrefixSize(curDir); UString temp; #ifdef _WIN32 if (prefixSize != 0) { /* (s) is absolute path, but only (prefixSize == 1) is possible here. So for full resolving we need root of current folder and relative part of (s). */ s += prefixSize; // (s) is relative part now if (fixedSize == 0) { // (curDir) is not absolute. // That case is unexpected, but we support it too. curDir.Empty(); curDir.Add_PathSepar(); fixedSize = 1; // (curDir) now is just Separ character. // So final (res) path later also will have Separ prefix. } } else #endif // _WIN32 { // (s) is relative path temp = curDir.Ptr(fixedSize); // (temp) is relative_part_of(curDir) } temp += fs2us(s); if (!ResolveDotsFolders(temp)) return false; curDir.DeleteFrom(fixedSize); // (curDir) now contains only absolute prefix part res = us2fs(curDir); res += us2fs(temp); #endif // UNDER_CE return true; } bool GetFullPath(CFSTR path, FString &fullPath) { return GetFullPath(NULL, path, fullPath); } }}} tmp41wklro_/CPP/Windows/FileName.h0000444000175000001440000001042114421541640020045 0ustar nabijaczleweliusers// Windows/FileName.h #ifndef ZIP7_INC_WINDOWS_FILE_NAME_H #define ZIP7_INC_WINDOWS_FILE_NAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { int FindSepar(const wchar_t *s) throw(); #ifndef USE_UNICODE_FSTRING int FindSepar(const FChar *s) throw(); #endif void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty void NormalizeDirPathPrefix(UString &dirPath); #ifdef _WIN32 void NormalizeDirSeparators(FString &s); #endif bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\" bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ #if defined(_WIN32) && !defined(UNDER_CE) extern const char * const kSuperPathPrefix; /* \\?\ */ const unsigned kDevicePathPrefixSize = 4; const unsigned kSuperPathPrefixSize = 4; const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */ bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */ /* GetNetworkServerPrefixSize() returns size of server prefix: \\?\UNC\SERVER\ \\SERVER\ in another cases it returns 0 */ unsigned GetNetworkServerPrefixSize(CFSTR s) throw(); bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */ bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\" bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\" bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:" // bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:" bool IsSuperPath(const wchar_t *s) throw(); bool IsSuperOrDevicePath(const wchar_t *s) throw(); bool IsAltStreamPrefixWithColon(const UString &s) throw(); // returns true, if super prefix was removed bool If_IsSuperPath_RemoveSuperPrefix(UString &s); #ifndef USE_UNICODE_FSTRING bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:" // bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:" bool IsDrivePath(CFSTR s) throw(); bool IsSuperPath(CFSTR s) throw(); bool IsSuperOrDevicePath(CFSTR s) throw(); /* GetRootPrefixSize() returns size of ROOT PREFIX for cases: \ \\.\ C:\ \\?\C:\ \\?\UNC\SERVER\Shared\ \\SERVER\Shared\ in another cases it returns 0 */ unsigned GetRootPrefixSize(CFSTR s) throw(); #endif int FindAltStreamColon(CFSTR path) throw(); #endif // _WIN32 bool IsAbsolutePath(const wchar_t *s) throw(); unsigned GetRootPrefixSize(const wchar_t *s) throw(); #ifdef Z7_LONG_PATH const int kSuperPathType_UseOnlyMain = 0; const int kSuperPathType_UseOnlySuper = 1; const int kSuperPathType_UseMainAndSuper = 2; int GetUseSuperPathType(CFSTR s) throw(); bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew); bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); #define USE_MAIN_PATH (_useSuperPathType != kSuperPathType_UseOnlySuper) #define USE_MAIN_PATH_2 (_useSuperPathType1 != kSuperPathType_UseOnlySuper && _useSuperPathType2 != kSuperPathType_UseOnlySuper) #define USE_SUPER_PATH (_useSuperPathType != kSuperPathType_UseOnlyMain) #define USE_SUPER_PATH_2 (_useSuperPathType1 != kSuperPathType_UseOnlyMain || _useSuperPathType2 != kSuperPathType_UseOnlyMain) #define IF_USE_MAIN_PATH int _useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) #define IF_USE_MAIN_PATH_2(x1, x2) \ int _useSuperPathType1 = GetUseSuperPathType(x1); \ int _useSuperPathType2 = GetUseSuperPathType(x2); \ if (USE_MAIN_PATH_2) #else #define IF_USE_MAIN_PATH #define IF_USE_MAIN_PATH_2(x1, x2) #endif // Z7_LONG_PATH /* if (dirPrefix != NULL && (path) is relative) { (dirPrefix) will be used result (fullPath) will contain prefix part of (dirPrefix). } Current_Dir path can be used in 2 cases: 1) if (path) is relative && dirPrefix == NULL 2) for _WIN32: if (path) is absolute starting wuth "\" */ bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); bool GetFullPath(CFSTR path, FString &fullPath); }}} #endif tmp41wklro_/CPP/Windows/FileSystem.cpp0000444000175000001440000001166514645523420021023 0ustar nabijaczleweliusers// Windows/FileSystem.cpp #include "StdAfx.h" #ifndef UNDER_CE #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #include "FileSystem.h" #include "Defs.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NSystem { #ifdef _WIN32 bool MyGetVolumeInformation( CFSTR rootPath, UString &volumeName, LPDWORD volumeSerialNumber, LPDWORD maximumComponentLength, LPDWORD fileSystemFlags, UString &fileSystemName) { BOOL res; #ifndef _UNICODE if (!g_IsNT) { TCHAR v[MAX_PATH + 2]; v[0] = 0; TCHAR f[MAX_PATH + 2]; f[0] = 0; res = GetVolumeInformation(fs2fas(rootPath), v, MAX_PATH, volumeSerialNumber, maximumComponentLength, fileSystemFlags, f, MAX_PATH); volumeName = MultiByteToUnicodeString(v); fileSystemName = MultiByteToUnicodeString(f); } else #endif { WCHAR v[MAX_PATH + 2]; v[0] = 0; WCHAR f[MAX_PATH + 2]; f[0] = 0; res = GetVolumeInformationW(fs2us(rootPath), v, MAX_PATH, volumeSerialNumber, maximumComponentLength, fileSystemFlags, f, MAX_PATH); volumeName = v; fileSystemName = f; } return BOOLToBool(res); } UINT MyGetDriveType(CFSTR pathName) { #ifndef _UNICODE if (!g_IsNT) { return GetDriveType(fs2fas(pathName)); } else #endif { return GetDriveTypeW(fs2us(pathName)); } } #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0400 // GetDiskFreeSpaceEx requires Windows95-OSR2, NT4 #define Z7_USE_DYN_GetDiskFreeSpaceEx #endif #ifdef Z7_USE_DYN_GetDiskFreeSpaceEx typedef BOOL (WINAPI * Func_GetDiskFreeSpaceExA)( LPCSTR lpDirectoryName, // directory name PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk ); typedef BOOL (WINAPI * Func_GetDiskFreeSpaceExW)( LPCWSTR lpDirectoryName, // directory name PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk ); #endif bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) { DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters; bool sizeIsDetected = false; #ifndef _UNICODE if (!g_IsNT) { #ifdef Z7_USE_DYN_GetDiskFreeSpaceEx const Func_GetDiskFreeSpaceExA f = Z7_GET_PROC_ADDRESS( Func_GetDiskFreeSpaceExA, GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); if (f) #endif { ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; sizeIsDetected = BOOLToBool( #ifdef Z7_USE_DYN_GetDiskFreeSpaceEx f #else GetDiskFreeSpaceExA #endif (fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); totalSize = totalSize2.QuadPart; freeSize = freeSize2.QuadPart; } if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) return false; } else #endif { #ifdef Z7_USE_DYN_GetDiskFreeSpaceEx const Func_GetDiskFreeSpaceExW f = Z7_GET_PROC_ADDRESS( Func_GetDiskFreeSpaceExW, GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW"); if (f) #endif { ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; sizeIsDetected = BOOLToBool( #ifdef Z7_USE_DYN_GetDiskFreeSpaceEx f #else GetDiskFreeSpaceExW #endif (fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); totalSize = totalSize2.QuadPart; freeSize = freeSize2.QuadPart; } if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) return false; } clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster; if (!sizeIsDetected) { totalSize = clusterSize * (UInt64)numClusters; freeSize = clusterSize * (UInt64)numFreeClusters; } return true; } #endif /* bool Is_File_LimitedBy_4GB(CFSTR _path, bool &isFsDetected) { isFsDetected = false; FString path (_path); path.DeleteFrom(NName::GetRootPrefixSize(path)); // GetVolumeInformation supports super paths. // NName::If_IsSuperPath_RemoveSuperPrefix(path); if (!path.IsEmpty()) { DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags; UString volName, fileSystemName; if (MyGetVolumeInformation(path, volName, &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags, fileSystemName)) { isFsDetected = true; if (fileSystemName.IsPrefixedBy_Ascii_NoCase("fat")) return true; } } return false; } */ }}} #endif tmp41wklro_/CPP/Windows/FileSystem.h0000444000175000001440000000117414357314620020462 0ustar nabijaczleweliusers// Windows/FileSystem.h #ifndef ZIP7_INC_WINDOWS_FILE_SYSTEM_H #define ZIP7_INC_WINDOWS_FILE_SYSTEM_H #include "../Common/MyString.h" #include "../Common/MyTypes.h" namespace NWindows { namespace NFile { namespace NSystem { #ifdef _WIN32 bool MyGetVolumeInformation( CFSTR rootPath , UString &volumeName, LPDWORD volumeSerialNumber, LPDWORD maximumComponentLength, LPDWORD fileSystemFlags, UString &fileSystemName); UINT MyGetDriveType(CFSTR pathName); bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); #endif }}} #endif tmp41wklro_/CPP/Windows/Handle.h0000444000175000001440000000132614405125240017560 0ustar nabijaczleweliusers// Windows/Handle.h #ifndef ZIP7_INC_WINDOWS_HANDLE_H #define ZIP7_INC_WINDOWS_HANDLE_H #include "../Common/MyWindows.h" namespace NWindows { class CHandle MY_UNCOPYABLE { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool IsCreated() const { return (_handle != NULL); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { const HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif tmp41wklro_/CPP/Windows/MemoryGlobal.cpp0000444000175000001440000000124412450771657021331 0ustar nabijaczleweliusers// Windows/MemoryGlobal.cpp #include "StdAfx.h" #include "MemoryGlobal.h" namespace NWindows { namespace NMemory { bool CGlobal::Alloc(UINT flags, SIZE_T size) throw() { HGLOBAL newBlock = ::GlobalAlloc(flags, size); if (newBlock == NULL) return false; _global = newBlock; return true; } bool CGlobal::Free() throw() { if (_global == NULL) return true; _global = ::GlobalFree(_global); return (_global == NULL); } bool CGlobal::ReAlloc(SIZE_T size) throw() { HGLOBAL newBlock = ::GlobalReAlloc(_global, size, GMEM_MOVEABLE); if (newBlock == NULL) return false; _global = newBlock; return true; } }} tmp41wklro_/CPP/Windows/MemoryGlobal.h0000444000175000001440000000202514405125240020753 0ustar nabijaczleweliusers// Windows/MemoryGlobal.h #ifndef ZIP7_INC_WINDOWS_MEMORY_GLOBAL_H #define ZIP7_INC_WINDOWS_MEMORY_GLOBAL_H #include "../Common/MyWindows.h" namespace NWindows { namespace NMemory { class CGlobal { HGLOBAL _global; public: CGlobal(): _global(NULL) {} ~CGlobal() { Free(); } operator HGLOBAL() const { return _global; } void Attach(HGLOBAL hGlobal) { Free(); _global = hGlobal; } HGLOBAL Detach() { const HGLOBAL h = _global; _global = NULL; return h; } bool Alloc(UINT flags, SIZE_T size) throw(); bool Free() throw(); LPVOID Lock() const { return GlobalLock(_global); } void Unlock() const { GlobalUnlock(_global); } bool ReAlloc(SIZE_T size) throw(); }; class CGlobalLock { HGLOBAL _global; LPVOID _ptr; public: LPVOID GetPointer() const { return _ptr; } CGlobalLock(HGLOBAL hGlobal): _global(hGlobal) { _ptr = GlobalLock(hGlobal); } ~CGlobalLock() { if (_ptr) GlobalUnlock(_global); } }; }} #endif tmp41wklro_/CPP/Windows/MemoryLock.cpp0000444000175000001440000000630614614671060021014 0ustar nabijaczleweliusers// Windows/MemoryLock.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #include "MemoryLock.h" namespace NWindows { namespace NSecurity { #ifndef UNDER_CE #ifdef _UNICODE #define MY_FUNC_SELECT(f) :: f #else #define MY_FUNC_SELECT(f) my_ ## f extern "C" { typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); } #define GET_PROC_ADDR(fff, name) \ const Func_ ## fff my_ ## fff = Z7_GET_PROC_ADDRESS( \ Func_ ## fff, hModule, name); #endif bool EnablePrivilege(LPCTSTR privilegeName, bool enable) { bool res = false; #ifndef _UNICODE const HMODULE hModule = ::LoadLibrary(TEXT("advapi32.dll")); if (!hModule) return false; Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION GET_PROC_ADDR( OpenProcessToken, "OpenProcessToken") GET_PROC_ADDR( LookupPrivilegeValue, "LookupPrivilegeValueA") GET_PROC_ADDR( AdjustTokenPrivileges, "AdjustTokenPrivileges") if (my_OpenProcessToken && my_AdjustTokenPrivileges && my_LookupPrivilegeValue) #endif { HANDLE token; if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) { TOKEN_PRIVILEGES tp; if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); } } #ifndef _UNICODE ::FreeLibrary(hModule); #endif return res; } Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); /* We suppose that Window 10 works incorrectly with "Large Pages" at: - Windows 10 1703 (15063) : incorrect allocating after VirtualFree() - Windows 10 1709 (16299) : incorrect allocating after VirtualFree() - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger, if CPU doesn't support 1 GB pages. Windows 10 1903 (18362) probably works correctly. */ unsigned Get_LargePages_RiskLevel() { OSVERSIONINFOEXW vi; const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); if (!ntdll) return 0; const Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS( Func_RtlGetVersion, ntdll, "RtlGetVersion"); if (!func) return 0; func(&vi); if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0; if (vi.dwMajorVersion + vi.dwMinorVersion != 10) return 0; if (vi.dwBuildNumber <= 16299) return 1; #ifdef MY_CPU_X86_OR_AMD64 if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB()) return 1; #endif return 0; } #endif }} tmp41wklro_/CPP/Windows/MemoryLock.h0000444000175000001440000000170414357314620020456 0ustar nabijaczleweliusers// Windows/MemoryLock.h #ifndef ZIP7_INC_WINDOWS_MEMORY_LOCK_H #define ZIP7_INC_WINDOWS_MEMORY_LOCK_H #include "../Common/MyWindows.h" namespace NWindows { namespace NSecurity { #ifndef UNDER_CE bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); inline bool EnablePrivilege_LockMemory(bool enable = true) { return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable); } inline void EnablePrivilege_SymLink() { /* Probably we do not to set any Privilege for junction points. But we need them for Symbolic links */ NSecurity::EnablePrivilege(SE_RESTORE_NAME); /* Probably we need only SE_RESTORE_NAME, but there is also SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */ NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME // Do we need to set SE_BACKUP_NAME ? } unsigned Get_LargePages_RiskLevel(); #endif }} #endif tmp41wklro_/CPP/Windows/NtCheck.h0000444000175000001440000000231714402146440017707 0ustar nabijaczleweliusers// Windows/NtCheck.h #ifndef ZIP7_INC_WINDOWS_NT_CHECK_H #define ZIP7_INC_WINDOWS_NT_CHECK_H #ifdef _WIN32 #include "../Common/MyWindows.h" #if !defined(_WIN64) && !defined(UNDER_CE) #if defined(_MSC_VER) && _MSC_VER >= 1900 #pragma warning(push) // GetVersionExW was declared deprecated #pragma warning(disable : 4996) #endif static inline bool IsItWindowsNT() { OSVERSIONINFO vi; vi.dwOSVersionInfoSize = sizeof(vi); return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT); } #if defined(_MSC_VER) && _MSC_VER >= 1900 #pragma warning(pop) #endif #endif #ifndef _UNICODE extern bool g_IsNT; #if defined(_WIN64) || defined(UNDER_CE) bool g_IsNT = true; #define SET_IS_NT #else bool g_IsNT = false; #define SET_IS_NT g_IsNT = IsItWindowsNT(); #endif #define NT_CHECK_ACTION // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION } #else #if !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION } #else #define NT_CHECK_ACTION #endif #define SET_IS_NT #endif #define NT_CHECK NT_CHECK_ACTION SET_IS_NT #else #define NT_CHECK #endif #endif tmp41wklro_/CPP/Windows/PropVariant.cpp0000444000175000001440000002105614567042400021174 0ustar nabijaczleweliusers// Windows/PropVariant.cpp #include "StdAfx.h" #include "../Common/Defs.h" #include "PropVariant.h" namespace NWindows { namespace NCOM { BSTR AllocBstrFromAscii(const char *s) throw() { if (!s) return NULL; UINT len = (UINT)strlen(s); BSTR p = ::SysAllocStringLen(NULL, len); if (p) { for (UINT i = 0; i <= len; i++) p[i] = (Byte)s[i]; } return p; } HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() { p->bstrVal = ::SysAllocStringLen(NULL, numChars); if (!p->bstrVal) { p->vt = VT_ERROR; p->scode = E_OUTOFMEMORY; return E_OUTOFMEMORY; } p->vt = VT_BSTR; return S_OK; } HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() { p->bstrVal = AllocBstrFromAscii(s); if (p->bstrVal) { p->vt = VT_BSTR; return S_OK; } p->vt = VT_ERROR; p->scode = E_OUTOFMEMORY; return E_OUTOFMEMORY; } CPropVariant::CPropVariant(const PROPVARIANT &varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant &varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } static const char * const kMemException = "out of memory"; CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (!bstrVal && lpszSrc) { throw kMemException; // vt = VT_ERROR; // scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(const UString &s) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocStringLen(s, s.Len()); if (!bstrVal) throw kMemException; return *this; } CPropVariant& CPropVariant::operator=(const UString2 &s) { /* if (s.IsEmpty()) *this = L""; else */ { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len()); if (!bstrVal) throw kMemException; /* SysAllocStringLen probably appends a null-terminating character for NULL string. But it doesn't specified in MSDN. But we suppose that it works if (!s.GetRawPtr()) { *bstrVal = 0; } */ /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL) pointers to this function causes an unexpected termination of the application. Is it safe? Maybe we must chamnge the code for that case ? */ } return *this; } CPropVariant& CPropVariant::operator=(const char *s) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = AllocBstrFromAscii(s); if (!bstrVal) { throw kMemException; // vt = VT_ERROR; // scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) throw() { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } BSTR CPropVariant::AllocBstr(unsigned numChars) { if (vt != VT_EMPTY) InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocStringLen(NULL, numChars); if (!bstrVal) { throw kMemException; // vt = VT_ERROR; // scode = E_OUTOFMEMORY; } return bstrVal; } #define SET_PROP_id_dest(id, dest) \ if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0; void CPropVariant::Set_Int32(Int32 value) throw() { SET_PROP_id_dest(VT_I4, lVal) } void CPropVariant::Set_Int64(Int64 value) throw() { SET_PROP_id_dest(VT_I8, hVal.QuadPart) } #define SET_PROP_FUNC(type, id, dest) \ CPropVariant& CPropVariant::operator=(type value) throw() \ { SET_PROP_id_dest(id, dest) return *this; } SET_PROP_FUNC(Byte, VT_UI1, bVal) // SET_PROP_FUNC(Int16, VT_I2, iVal) // SET_PROP_FUNC(Int32, VT_I4, lVal) SET_PROP_FUNC(UInt32, VT_UI4, ulVal) SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) // SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) #define CASE_SIMPLE_VT_VALUES \ case VT_EMPTY: \ case VT_BOOL: \ case VT_FILETIME: \ case VT_UI8: \ case VT_UI4: \ case VT_UI2: \ case VT_UI1: \ case VT_I8: \ case VT_I4: \ case VT_I2: \ case VT_I1: \ case VT_UINT: \ case VT_INT: \ case VT_NULL: \ case VT_ERROR: \ case VT_R4: \ case VT_R8: \ case VT_CY: \ case VT_DATE: \ /* ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME) So we handle VT_FILETIME and another simple types directly we call system functions for VT_BSTR and for unknown typed */ CPropVariant::~CPropVariant() throw() { switch ((unsigned)vt) { CASE_SIMPLE_VT_VALUES // vt = VT_EMPTY; // it's optional return; default: break; } ::VariantClear((tagVARIANT *)this); } HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() { switch ((unsigned)prop->vt) { CASE_SIMPLE_VT_VALUES prop->vt = VT_EMPTY; break; default: { const HRESULT res = ::VariantClear((VARIANTARG *)prop); if (res != S_OK || prop->vt != VT_EMPTY) return res; break; } } prop->wReserved1 = 0; prop->wReserved2 = 0; prop->wReserved3 = 0; prop->uhVal.QuadPart = 0; return S_OK; } HRESULT CPropVariant::Clear() throw() { if (vt == VT_EMPTY) { wReserved1 = 0; return S_OK; } return PropVariant_Clear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() { Clear(); switch ((unsigned)pSrc->vt) { CASE_SIMPLE_VT_VALUES memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; default: break; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() { const HRESULT hr = Clear(); if (FAILED(hr)) return hr; // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); *(PROPVARIANT *)this = *pSrc; pSrc->vt = VT_EMPTY; pSrc->wReserved1 = 0; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() { if (pDest->vt != VT_EMPTY) { const HRESULT hr = PropVariant_Clear(pDest); if (FAILED(hr)) return hr; } // memcpy(pDest, this, sizeof(PROPVARIANT)); *pDest = *(PROPVARIANT *)this; vt = VT_EMPTY; wReserved1 = 0; return S_OK; } HRESULT CPropVariant::InternalClear() throw() { if (vt == VT_EMPTY) { wReserved1 = 0; return S_OK; } const HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) { const HRESULT hr = Copy(pSrc); if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) throw kMemException; vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) throw() { if (vt != a.vt) return MyCompare(vt, a.vt); switch ((unsigned)vt) { case VT_EMPTY: return 0; // case VT_I1: return MyCompare(cVal, a.cVal); case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); case VT_UI4: return MyCompare(ulVal, a.ulVal); // case VT_UINT: return MyCompare(uintVal, a.uintVal); case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: { const int res = CompareFileTime(&filetime, &a.filetime); if (res != 0) return res; const unsigned v1 = Get_Ns100(); const unsigned v2 = a.Get_Ns100(); return MyCompare(v1, v2); } case VT_BSTR: return 0; // Not implemented default: return 0; } } }} tmp41wklro_/CPP/Windows/PropVariant.h0000444000175000001440000001146114365243200020635 0ustar nabijaczleweliusers// Windows/PropVariant.h #ifndef ZIP7_INC_WINDOWS_PROP_VARIANT_H #define ZIP7_INC_WINDOWS_PROP_VARIANT_H #include "../Common/MyTypes.h" #include "../Common/MyWindows.h" #include "../Common/MyString.h" namespace NWindows { namespace NCOM { BSTR AllocBstrFromAscii(const char *s) throw(); HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() { p->vt = VT_UI4; p->ulVal = v; } inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() { p->vt = VT_UI8; p->uhVal.QuadPart = v; } inline void PropVarEm_Set_FileTime64_Prec(PROPVARIANT *p, UInt64 v, unsigned prec) throw() { p->vt = VT_FILETIME; p->filetime.dwLowDateTime = (DWORD)v; p->filetime.dwHighDateTime = (DWORD)(v >> 32); p->wReserved1 = (WORD)prec; p->wReserved2 = 0; p->wReserved3 = 0; } inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() { p->vt = VT_BOOL; p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); } class CPropVariant : public tagPROPVARIANT { // ---------- forbidden functions ---------- CPropVariant(const char *s); // CPropVariant(const UString &s); #ifdef DEBUG_FSTRING_INHERITS_ASTRING CPropVariant(const FString &s); CPropVariant& operator=(const FString &s); #endif public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; // wReserved2 = 0; // wReserved3 = 0; // uhVal.QuadPart = 0; bstrVal = NULL; } void Set_FtPrec(unsigned prec) { wReserved1 = (WORD)prec; wReserved2 = 0; wReserved3 = 0; } void SetAsTimeFrom_FT_Prec(const FILETIME &ft, unsigned prec) { operator=(ft); Set_FtPrec(prec); } void SetAsTimeFrom_Ft64_Prec(UInt64 v, unsigned prec) { FILETIME ft; ft.dwLowDateTime = (DWORD)(UInt32)v; ft.dwHighDateTime = (DWORD)(UInt32)(v >> 32); operator=(ft); Set_FtPrec(prec); } void SetAsTimeFrom_FT_Prec_Ns100(const FILETIME &ft, unsigned prec, unsigned ns100) { operator=(ft); wReserved1 = (WORD)prec; wReserved2 = (WORD)ns100; wReserved3 = 0; } unsigned Get_Ns100() const { const unsigned prec = wReserved1; const unsigned ns100 = wReserved2; if (prec == 0 && prec <= k_PropVar_TimePrec_1ns && ns100 < 100 && wReserved3 == 0) return ns100; return 0; } ~CPropVariant() throw(); CPropVariant(const PROPVARIANT &varSrc); CPropVariant(const CPropVariant &varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } private: CPropVariant(UInt16 value); // { vt = VT_UI2; wReserved1 = 0; uiVal = value; } CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Int64 value); // { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } public: CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant& operator=(const CPropVariant &varSrc); CPropVariant& operator=(const PROPVARIANT &varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(const UString &s); CPropVariant& operator=(const UString2 &s); CPropVariant& operator=(const char *s); CPropVariant& operator=(const AString &s) { return (*this)=(const char *)s; } CPropVariant& operator=(bool bSrc) throw(); CPropVariant& operator=(Byte value) throw(); private: CPropVariant& operator=(Int16 value) throw(); CPropVariant& operator=(UInt16 value) throw(); CPropVariant& operator=(Int32 value) throw(); CPropVariant& operator=(Int64 value) throw(); public: CPropVariant& operator=(UInt32 value) throw(); CPropVariant& operator=(UInt64 value) throw(); CPropVariant& operator=(const FILETIME &value) throw(); void Set_Int32(Int32 value) throw(); void Set_Int64(Int64 value) throw(); BSTR AllocBstr(unsigned numChars); HRESULT Clear() throw(); HRESULT Copy(const PROPVARIANT *pSrc) throw(); HRESULT Attach(PROPVARIANT *pSrc) throw(); HRESULT Detach(PROPVARIANT *pDest) throw(); HRESULT InternalClear() throw(); void InternalCopy(const PROPVARIANT *pSrc); int Compare(const CPropVariant &a) throw(); }; }} #endif tmp41wklro_/CPP/Windows/PropVariantConv.cpp0000444000175000001440000001652714574265420022040 0ustar nabijaczleweliusers// PropVariantConv.cpp #include "StdAfx.h" #include "../Common/IntToString.h" #include "Defs.h" #include "PropVariantConv.h" #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } static const unsigned k_TimeStringBufferSize = 64; bool g_Timestamp_Show_UTC; #if 0 bool g_Timestamp_Show_DisableZ; bool g_Timestamp_Show_TDelimeter; bool g_Timestamp_Show_ZoneOffset; #endif Z7_NO_INLINE bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level, unsigned flags) throw() { *s = 0; FILETIME ft; #if 0 Int64 bias64 = 0; #endif const bool show_utc = (flags & kTimestampPrintFlags_Force_UTC) ? true : (flags & kTimestampPrintFlags_Force_LOCAL) ? false : g_Timestamp_Show_UTC; if (show_utc) ft = utc; else { if (!FileTimeToLocalFileTime(&utc, &ft)) return false; #if 0 if (g_Timestamp_Show_ZoneOffset) { const UInt64 utc64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime; const UInt64 loc64 = (((UInt64) ft.dwHighDateTime) << 32) + ft.dwLowDateTime; bias64 = (Int64)utc64 - (Int64)loc64; } #endif } SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) { // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set. return false; } { unsigned val = st.wYear; if (val >= 10000) { *s++ = (char)('0' + val / 10000); val %= 10000; } s[3] = (char)('0' + val % 10); val /= 10; s[2] = (char)('0' + val % 10); val /= 10; s[1] = (char)('0' + val % 10); s[0] = (char)('0' + val / 10); s += 4; } UINT_TO_STR_2('-', st.wMonth) UINT_TO_STR_2('-', st.wDay) if (level > kTimestampPrintLevel_DAY) { const char setChar = #if 0 g_Timestamp_Show_TDelimeter ? 'T' : // ISO 8601 #endif ' '; UINT_TO_STR_2(setChar, st.wHour) UINT_TO_STR_2(':', st.wMinute) if (level >= kTimestampPrintLevel_SEC) { UINT_TO_STR_2(':', st.wSecond) if (level > kTimestampPrintLevel_SEC) { *s++ = '.'; /* { unsigned val = st.wMilliseconds; s[2] = (char)('0' + val % 10); val /= 10; s[1] = (char)('0' + val % 10); s[0] = (char)('0' + val / 10); s += 3; } *s++ = ' '; */ { unsigned numDigits = 7; UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000); for (unsigned i = numDigits; i != 0;) { i--; s[i] = (char)('0' + val % 10); val /= 10; } if (numDigits > (unsigned)level) numDigits = (unsigned)level; s += numDigits; } if (level >= kTimestampPrintLevel_NTFS + 1) { *s++ = (char)('0' + (ns100 / 10)); if (level >= kTimestampPrintLevel_NTFS + 2) *s++ = (char)('0' + (ns100 % 10)); } } } } if (show_utc) { if ((flags & kTimestampPrintFlags_DisableZ) == 0 #if 0 && !g_Timestamp_Show_DisableZ #endif ) *s++ = 'Z'; } #if 0 else if (g_Timestamp_Show_ZoneOffset) { #if 1 { char c; if (bias64 < 0) { bias64 = -bias64; c = '+'; } else c = '-'; UInt32 bias = (UInt32)((UInt64)bias64 / (10000000 * 60)); #else TIME_ZONE_INFORMATION zi; const DWORD dw = GetTimeZoneInformation(&zi); if (dw <= TIME_ZONE_ID_DAYLIGHT) // == 2 { // UTC = LOCAL + Bias Int32 bias = zi.Bias; char c; if (bias < 0) { bias = -bias; c = '+'; } else c = '-'; #endif const UInt32 hours = (UInt32)bias / 60; const UInt32 mins = (UInt32)bias % 60; UINT_TO_STR_2(c, hours) UINT_TO_STR_2(':', mins) } } #endif *s = 0; return true; } bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() { return ConvertUtcFileTimeToString2(utc, 0, s, level); } bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw() { char s[k_TimeStringBufferSize]; const bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level); for (unsigned i = 0;; i++) { const Byte c = (Byte)s[i]; dest[i] = c; if (c == 0) break; } return res; } bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() { char s[k_TimeStringBufferSize]; const bool res = ConvertUtcFileTimeToString(ft, s, level); for (unsigned i = 0;; i++) { const Byte c = (Byte)s[i]; dest[i] = c; if (c == 0) break; } return res; } void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() { *dest = 0; switch (prop.vt) { case VT_EMPTY: return; case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; case VT_FILETIME: { // const unsigned prec = prop.wReserved1; int level = 0; /* if (prec == 0) level = 7; else if (prec > 16 && prec <= 16 + 9) level = prec - 16; */ ConvertUtcFileTimeToString(prop.filetime, dest, level); return; } // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); } } void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw() { *dest = 0; switch (prop.vt) { case VT_EMPTY: return; case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; case VT_FILETIME: { // const unsigned prec = prop.wReserved1; int level = 0; /* if (prec == 0) level = 7; else if (prec > 16 && prec <= 16 + 9) level = prec - 16; */ ConvertUtcFileTimeToString(prop.filetime, dest, level); return; } // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return; default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); } } tmp41wklro_/CPP/Windows/PropVariantConv.h0000444000175000001440000000342114574265420021472 0ustar nabijaczleweliusers// Windows/PropVariantConv.h #ifndef ZIP7_INC_PROP_VARIANT_CONV_H #define ZIP7_INC_PROP_VARIANT_CONV_H #include "../Common/MyTypes.h" // provide at least 32 bytes for buffer including zero-end extern bool g_Timestamp_Show_UTC; #define kTimestampPrintLevel_DAY -3 // #define kTimestampPrintLevel_HOUR -2 #define kTimestampPrintLevel_MIN -1 #define kTimestampPrintLevel_SEC 0 #define kTimestampPrintLevel_NTFS 7 #define kTimestampPrintLevel_NS 9 #define kTimestampPrintFlags_Force_UTC (1 << 0) #define kTimestampPrintFlags_Force_LOCAL (1 << 1) #define kTimestampPrintFlags_DisableZ (1 << 4) bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC, unsigned flags = 0) throw(); bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); // provide at least 32 bytes for buffer including zero-end // don't send VT_BSTR to these functions void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) { switch (prop.vt) { case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; case VT_UI4: value = prop.ulVal; return true; case VT_UI2: value = prop.uiVal; return true; case VT_UI1: value = prop.bVal; return true; case VT_EMPTY: return false; default: throw 151199; } } #endif tmp41wklro_/CPP/Windows/Registry.cpp0000444000175000001440000002406014476353540020546 0ustar nabijaczleweliusers// Windows/Registry.cpp #include "StdAfx.h" #include // #include #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #include "Registry.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NRegistry { #define MYASSERT(expr) // _ASSERTE(expr) #define MY_ASSUME(expr) /* static void Error() { #ifdef _CONSOLE printf("\nregistry error\n"); #else MessageBoxW(0, L"registry error", L"", 0); // exit(1); #endif } #define MY_ASSUME(expr) { if (!(expr)) Error(); } */ LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, LPTSTR keyClass, DWORD options, REGSAM accessMask, LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw() { MY_ASSUME(parentKey != NULL); DWORD dispositionReal; HKEY key = NULL; LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, options, accessMask, securityAttributes, &key, &dispositionReal); if (disposition != NULL) *disposition = dispositionReal; if (res == ERROR_SUCCESS) { res = Close(); _object = key; } return res; } LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw() { MY_ASSUME(parentKey != NULL); HKEY key = NULL; LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); if (res == ERROR_SUCCESS) { res = Close(); MYASSERT(res == ERROR_SUCCESS); _object = key; } return res; } LONG CKey::Close() throw() { LONG res = ERROR_SUCCESS; if (_object != NULL) { res = RegCloseKey(_object); _object = NULL; } return res; } // win95, win98: deletes sunkey and all its subkeys // winNT to be deleted must not have subkeys LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() { MY_ASSUME(_object != NULL); return RegDeleteKey(_object, subKeyName); } LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() { CKey key; LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); if (res != ERROR_SUCCESS) return res; FILETIME fileTime; const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL DWORD size = kBufSize; TCHAR buffer[kBufSize]; while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) { res = key.RecurseDeleteKey(buffer); if (res != ERROR_SUCCESS) return res; size = kBufSize; } key.Close(); return DeleteSubKey(subKeyName); } ///////////////////////// // Value Functions static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } LONG CKey::DeleteValue(LPCTSTR name) throw() { MY_ASSUME(_object != NULL); return ::RegDeleteValue(_object, name); } #ifndef _UNICODE LONG CKey::DeleteValue(LPCWSTR name) { MY_ASSUME(_object != NULL); if (g_IsNT) return ::RegDeleteValueW(_object, name); return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); } #endif LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw() { MY_ASSUME(_object != NULL); return RegSetValueEx(_object, name, 0, REG_DWORD, (const BYTE *)&value, sizeof(UInt32)); } LONG CKey::SetValue(LPCTSTR name, bool value) throw() { return SetValue(name, BoolToUINT32(value)); } LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() { MYASSERT(value != NULL); MY_ASSUME(_object != NULL); return RegSetValueEx(_object, name, 0, REG_SZ, (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)); } /* LONG CKey::SetValue(LPCTSTR name, const CSysString &value) { MYASSERT(value != NULL); MY_ASSUME(_object != NULL); return RegSetValueEx(_object, name, NULL, REG_SZ, (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); } */ #ifndef _UNICODE LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) { MYASSERT(value != NULL); MY_ASSUME(_object != NULL); if (g_IsNT) return RegSetValueExW(_object, name, 0, REG_SZ, (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), value == 0 ? 0 : (LPCSTR)GetSystemString(value)); } #endif LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw() { MYASSERT(value != NULL); MY_ASSUME(_object != NULL); return RegSetValueEx(_object, name, 0, REG_BINARY, (const BYTE *)value, size); } LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) { MYASSERT(value != NULL); CKey key; LONG res = key.Create(parentKey, keyName); if (res == ERROR_SUCCESS) res = key.SetValue(valueName, value); return res; } LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw() { MYASSERT(value != NULL); CKey key; LONG res = key.Create(_object, keyName); if (res == ERROR_SUCCESS) res = key.SetValue(valueName, value); return res; } LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() { DWORD type = 0; DWORD count = sizeof(DWORD); LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)&value, &count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); return res; } LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() { UInt32 uintValue = BoolToUINT32(value); LONG res = QueryValue(name, uintValue); value = UINT32ToBool(uintValue); return res; } LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() { UInt32 newVal; LONG res = QueryValue(name, newVal); if (res == ERROR_SUCCESS) value = newVal; return res; } LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() { bool newVal = false; LONG res = QueryValue(name, newVal); if (res == ERROR_SUCCESS) value = newVal; return res; } LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() { DWORD type = 0; LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); return res; } LONG CKey::QueryValue(LPCTSTR name, CSysString &value) { value.Empty(); DWORD type = 0; DWORD curSize = 0; LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, &curSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; UInt32 curSize2 = curSize; res = QueryValue(name, value.GetBuf(curSize), curSize2); if (curSize > curSize2) curSize = curSize2; value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); return res; } #ifndef _UNICODE LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) { DWORD type = 0; LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); return res; } LONG CKey::QueryValue(LPCWSTR name, UString &value) { value.Empty(); DWORD type = 0; DWORD curSize = 0; LONG res; if (g_IsNT) { res = RegQueryValueExW(_object, name, NULL, &type, NULL, &curSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; UInt32 curSize2 = curSize; res = QueryValue(name, value.GetBuf(curSize), curSize2); if (curSize > curSize2) curSize = curSize2; value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); } else { AString vTemp; res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); value = GetUnicodeString(vTemp); } return res; } #endif LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() { DWORD type = 0; LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); return res; } LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) { DWORD type = 0; dataSize = 0; LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize); if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) return res; value.Alloc(dataSize); return QueryValue(name, (BYTE *)value, dataSize); } LONG CKey::EnumKeys(CSysStringVector &keyNames) { keyNames.Clear(); CSysString keyName; for (DWORD index = 0; ; index++) { const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL FILETIME lastWriteTime; UInt32 nameSize = kBufSize; LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); keyName.ReleaseBuf_CalcLen(kBufSize); if (result == ERROR_NO_MORE_ITEMS) break; if (result != ERROR_SUCCESS) return result; keyNames.Add(keyName); } return ERROR_SUCCESS; } LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) { size_t numChars = 0; unsigned i; for (i = 0; i < strings.Size(); i++) numChars += strings[i].Len() + 1; CObjArray buffer(numChars); size_t pos = 0; for (i = 0; i < strings.Size(); i++) { const UString &s = strings[i]; size_t size = s.Len() + 1; wmemcpy(buffer + pos, s, size); pos += size; } return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); } LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) { strings.Clear(); CByteBuffer buffer; UInt32 dataSize = 0; const LONG res = QueryValue(valueName, buffer, dataSize); if (res != ERROR_SUCCESS) return res; if (dataSize > buffer.Size()) return E_FAIL; if (dataSize % sizeof(wchar_t) != 0) return E_FAIL; const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; const size_t numChars = dataSize / sizeof(wchar_t); size_t prev = 0; UString s; for (size_t i = 0; i < numChars; i++) { if (data[i] == 0) { s = data + prev; strings.Add(s); prev = i + 1; } } return res; } }} tmp41wklro_/CPP/Windows/Registry.h0000444000175000001440000000502514357314620020205 0ustar nabijaczleweliusers// Windows/Registry.h #ifndef ZIP7_INC_WINDOWS_REGISTRY_H #define ZIP7_INC_WINDOWS_REGISTRY_H #include "../Common/MyBuffer.h" #include "../Common/MyString.h" namespace NWindows { namespace NRegistry { LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); class CKey { HKEY _object; public: CKey(): _object(NULL) {} ~CKey() { Close(); } operator HKEY() const { return _object; } void Attach(HKEY key) { _object = key; } HKEY Detach() { HKEY key = _object; _object = NULL; return key; } LONG Create(HKEY parentKey, LPCTSTR keyName, LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, REGSAM accessMask = KEY_ALL_ACCESS, LPSECURITY_ATTRIBUTES securityAttributes = NULL, LPDWORD disposition = NULL) throw(); LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw(); LONG Close() throw(); LONG DeleteSubKey(LPCTSTR subKeyName) throw(); LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); LONG DeleteValue(LPCTSTR name) throw(); #ifndef _UNICODE LONG DeleteValue(LPCWSTR name); #endif LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); LONG SetValue(LPCTSTR valueName, bool value) throw(); LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); // LONG SetValue(LPCTSTR valueName, const CSysString &value); #ifndef _UNICODE LONG SetValue(LPCWSTR name, LPCWSTR value); // LONG SetValue(LPCWSTR name, const UString &value); #endif LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); LONG QueryValue(LPCTSTR name, bool &value) throw(); LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); LONG QueryValue(LPCTSTR name, CSysString &value); LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); #ifndef _UNICODE LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); LONG QueryValue(LPCWSTR name, UString &value); #endif LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); LONG EnumKeys(CSysStringVector &keyNames); }; }} #endif tmp41wklro_/CPP/Windows/ResourceString.cpp0000444000175000001440000000411714003613306021676 0ustar nabijaczleweliusers// Windows/ResourceString.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #include "ResourceString.h" extern HINSTANCE g_hInstance; #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { #ifndef _UNICODE static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID) { CSysString s; int size = 128; int len; do { size <<= 1; len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); } while (size - len <= 1); s.ReleaseBuf_CalcLen((unsigned)len); return s; } #endif static const int kStartSize = 256; static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s) { int size = kStartSize; int len; do { size <<= 1; len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); } while (size - len <= 1); s.ReleaseBuf_CalcLen((unsigned)len); } // NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it. UString MyLoadString(UINT resourceID) { #ifndef _UNICODE if (!g_IsNT) return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID)); else #endif { { wchar_t s[kStartSize]; s[0] = 0; int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize); if (kStartSize - len > 1) return s; } UString dest; MyLoadString2(g_hInstance, resourceID, dest); return dest; } } void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest) { dest.Empty(); #ifndef _UNICODE if (!g_IsNT) MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID)); else #endif { { wchar_t s[kStartSize]; s[0] = 0; int len = ::LoadStringW(hInstance, resourceID, s, kStartSize); if (kStartSize - len > 1) { dest = s; return; } } MyLoadString2(hInstance, resourceID, dest); } } void MyLoadString(UINT resourceID, UString &dest) { MyLoadString(g_hInstance, resourceID, dest); } } tmp41wklro_/CPP/Windows/ResourceString.h0000444000175000001440000000061214405267600021347 0ustar nabijaczleweliusers// Windows/ResourceString.h #ifndef ZIP7_INC_WINDOWS_RESOURCE_STRING_H #define ZIP7_INC_WINDOWS_RESOURCE_STRING_H #include "../Common/MyString.h" #include "../Common/MyWindows.h" namespace NWindows { UString MyLoadString(UINT resourceID); void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest); void MyLoadString(UINT resourceID, UString &dest); } #endif tmp41wklro_/CPP/Windows/SecurityUtils.cpp0000444000175000001440000001203214405276620021555 0ustar nabijaczleweliusers// Windows/SecurityUtils.cpp #include "StdAfx.h" #include "SecurityUtils.h" namespace NWindows { namespace NSecurity { /* bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) { DWORD accountNameSize = 0, domainNameSize = 0; if (!::LookupAccountSid(systemName, sid, accountName.GetBuf(0), &accountNameSize, domainName.GetBuf(0), &domainNameSize, sidNameUse)) { if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) return false; } DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize; bool result = BOOLToBool(::LookupAccountSid(systemName, sid, accountName.GetBuf(accountNameSize), &accountNameSize2, domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse)); accountName.ReleaseBuf_CalcLen(accountNameSize); domainName.ReleaseBuf_CalcLen(domainNameSize); return result; } */ static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) { const size_t len = (size_t)wcslen(src); dest->Length = (USHORT)(len * sizeof(WCHAR)); dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); dest->Buffer = src; } /* static void MyLookupSids(CPolicy &policy, PSID ps) { LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; LSA_TRANSLATED_NAME *names = NULL; NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); int res = LsaNtStatusToWinError(nts); LsaFreeMemory(referencedDomains); LsaFreeMemory(names); } */ extern "C" { #ifndef _UNICODE typedef BOOL (WINAPI * Func_LookupAccountNameW)( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse ); #endif } static PSID GetSid(LPWSTR accountName) { #ifndef _UNICODE const HMODULE hModule = GetModuleHandle(TEXT("advapi32.dll")); if (!hModule) return NULL; const Func_LookupAccountNameW lookupAccountNameW = Z7_GET_PROC_ADDRESS( Func_LookupAccountNameW, hModule, "LookupAccountNameW"); if (!lookupAccountNameW) return NULL; #endif DWORD sidLen = 0, domainLen = 0; SID_NAME_USE sidNameUse; if (! #ifdef _UNICODE ::LookupAccountNameW #else lookupAccountNameW #endif (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) { if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { const PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); const BOOL res = #ifdef _UNICODE ::LookupAccountNameW #else lookupAccountNameW #endif (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); ::HeapFree(GetProcessHeap(), 0, domainName); if (res) return pSid; } } return NULL; } #define Z7_WIN_SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" bool AddLockMemoryPrivilege() { CPolicy policy; LSA_OBJECT_ATTRIBUTES attr; attr.Length = sizeof(attr); attr.RootDirectory = NULL; attr.ObjectName = NULL; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; if (policy.Open(NULL, &attr, // GENERIC_WRITE) POLICY_ALL_ACCESS) // STANDARD_RIGHTS_REQUIRED, // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) != 0) return false; LSA_UNICODE_STRING userRights; wchar_t s[128] = Z7_WIN_SE_LOCK_MEMORY_NAME; SetLsaString(s, &userRights); WCHAR userName[256 + 2]; DWORD size = 256; if (!GetUserNameW(userName, &size)) return false; const PSID psid = GetSid(userName); if (psid == NULL) return false; bool res = false; /* PLSA_UNICODE_STRING userRightsArray; ULONG countOfRights; NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); if (status != 0) return false; bool finded = false; for (ULONG i = 0; i < countOfRights; i++) { LSA_UNICODE_STRING &ur = userRightsArray[i]; if (ur.Length != s.Length() * sizeof(WCHAR)) continue; if (wcsncmp(ur.Buffer, s, s.Length()) != 0) continue; finded = true; res = true; break; } if (!finded) */ { /* LSA_ENUMERATION_INFORMATION *enums; ULONG countReturned; NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); if (status == 0) { for (ULONG i = 0; i < countReturned; i++) MyLookupSids(policy, enums[i].Sid); if (enums) ::LsaFreeMemory(enums); res = true; } */ const NTSTATUS status = policy.AddAccountRights(psid, &userRights); if (status == 0) res = true; // ULONG res = LsaNtStatusToWinError(status); } HeapFree(GetProcessHeap(), 0, psid); return res; } }} tmp41wklro_/CPP/Windows/SecurityUtils.h0000444000175000001440000001070314614671060021224 0ustar nabijaczleweliusers// Windows/SecurityUtils.h #ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H #define ZIP7_INC_WINDOWS_SECURITY_UTILS_H #include #include "Defs.h" #ifndef _UNICODE extern "C" { typedef NTSTATUS (NTAPI *Func_LsaOpenPolicy)(PLSA_UNICODE_STRING SystemName, PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); typedef NTSTATUS (NTAPI *Func_LsaClose)(LSA_HANDLE ObjectHandle); typedef NTSTATUS (NTAPI *Func_LsaAddAccountRights)(LSA_HANDLE PolicyHandle, PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); #define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) } Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION #define POLICY_FUNC_CALL(fff, str) \ if (hModule == NULL) return MY_STATUS_NOT_IMPLEMENTED; \ const Func_ ## fff v = Z7_GET_PROC_ADDRESS(Func_ ## fff, hModule, str); \ if (!v) return MY_STATUS_NOT_IMPLEMENTED; \ const NTSTATUS res = v #else #define POLICY_FUNC_CALL(fff, str) \ const NTSTATUS res = ::fff #endif namespace NWindows { namespace NSecurity { class CAccessToken { HANDLE _handle; public: CAccessToken(): _handle(NULL) {} ~CAccessToken() { Close(); } bool Close() { if (_handle == NULL) return true; bool res = BOOLToBool(::CloseHandle(_handle)); if (res) _handle = NULL; return res; } bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) { Close(); return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); } /* bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) { Close(); return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); } */ bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), newState, bufferLength, previousState, returnLength)); } bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) { return AdjustPrivileges(false, newState); } }; struct CPolicy { protected: LSA_HANDLE _handle; #ifndef _UNICODE HMODULE hModule; #endif public: operator LSA_HANDLE() const { return _handle; } CPolicy(): _handle(NULL) { #ifndef _UNICODE hModule = GetModuleHandle(TEXT("advapi32.dll")); #endif } ~CPolicy() { Close(); } NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, ACCESS_MASK desiredAccess) { Close(); POLICY_FUNC_CALL (LsaOpenPolicy, "LsaOpenPolicy") (systemName, objectAttributes, desiredAccess, &_handle); return res; } NTSTATUS Close() { if (_handle == NULL) return 0; POLICY_FUNC_CALL (LsaClose, "LsaClose") (_handle); _handle = NULL; return res; } NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } NTSTATUS LookupSids(ULONG count, PSID* sids, PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) { POLICY_FUNC_CALL (LsaAddAccountRights, "LsaAddAccountRights") (_handle, accountSid, userRights, countOfRights); return res; } NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) { return AddAccountRights(accountSid, userRights, 1); } NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } }; bool AddLockMemoryPrivilege(); }} #endif tmp41wklro_/CPP/Windows/Shell.cpp0000444000175000001440000005761014554374340020012 0ustar nabijaczleweliusers// Windows/Shell.cpp #include "StdAfx.h" #include "../Common/MyCom.h" #include "../Common/StringConvert.h" #include "COM.h" #include "FileName.h" #include "MemoryGlobal.h" #include "Shell.h" #ifndef _UNICODE extern bool g_IsNT; #endif // MSVC6 and old SDK don't support this function: // #define LWSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE // LWSTDAPI StrRetToStrW(STRRET *pstr, LPCITEMIDLIST pidl, LPWSTR *ppsz); // #define SHOW_DEBUG_SHELL #ifdef SHOW_DEBUG_SHELL #include "../Common/IntToString.h" static void Print_Number(UInt32 number, const char *s) { AString s2; s2.Add_UInt32(number); s2.Add_Space(); s2 += s; OutputDebugStringA(s2); } #define ODS(sz) { OutputDebugStringA(sz); } #define ODS_U(s) { OutputDebugStringW(s); } #define ODS_(op) { op; } #else #define ODS(sz) #define ODS_U(s) #define ODS_(op) #endif namespace NWindows { namespace NShell { #ifndef UNDER_CE // SHGetMalloc is unsupported in Windows Mobile? void CItemIDList::Free() { if (!m_Object) return; /* DOCs: SHGetMalloc was introduced in Windows 95 and Microsoft Windows NT 4.0, but as of Windows 2000 it is no longer necessary. In its place, programs can call the equivalent (and easier to use) CoTaskMemAlloc and CoTaskMemFree. Description from oldnewthings: shell functions could work without COM (if OLE32.DLL is not loaded), but now if OLE32.DLL is loaded, then shell functions and com functions do same things. 22.02: so we use OLE32.DLL function to free memory: */ /* CMyComPtr shellMalloc; if (::SHGetMalloc(&shellMalloc) != NOERROR) throw 41099; shellMalloc->Free(m_Object); */ CoTaskMemFree(m_Object); m_Object = NULL; } /* CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) { *this = itemIDList; } CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) { *this = itemIDList; } CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) { Free(); if (object != 0) { UINT32 size = GetSize(object); m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); if (m_Object != NULL) MoveMemory(m_Object, object, size); } return *this; } CItemIDList& CItemIDList::operator=(const CItemIDList &object) { Free(); if (object.m_Object != NULL) { UINT32 size = GetSize(object.m_Object); m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); if (m_Object != NULL) MoveMemory(m_Object, object.m_Object, size); } return *this; } */ static HRESULT ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names) { names.Clear(); const wchar_t *lim = p + size; UString s; /* if (size == 0 || p[size - 1] != 0) return E_INVALIDARG; if (size == 1) return S_OK; if (p[size - 2] != 0) return E_INVALIDARG; */ for (;;) { const wchar_t *start = p; for (;;) { if (p == lim) return E_INVALIDARG; // S_FALSE if (*p++ == 0) break; } const size_t num = (size_t)(p - start); if (num == 1) { if (p != lim) return E_INVALIDARG; // S_FALSE return S_OK; } s.SetFrom(start, (unsigned)(num - 1)); ODS_U(s) names.Add(s); // names.ReserveOnePosition(); // names.AddInReserved_Ptr_of_new(new UString((unsigned)num - 1, start)); } } static HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names) { names.Clear(); AString name; for (; size != 0; size--) { const char c = *p++; if (c == 0) { if (name.IsEmpty()) return S_OK; names.Add(GetUnicodeString(name)); name.Empty(); } else name.Add_Char(c); } return E_INVALIDARG; } #define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } static HRESULT DataObject_GetData_HGLOBAL(IDataObject *dataObject, CLIPFORMAT cf, NCOM::CStgMedium &medium) { FORMATETC etc = INIT_FORMATETC_HGLOBAL(cf); RINOK(dataObject->GetData(&etc, &medium)) if (medium.tymed != TYMED_HGLOBAL) return E_INVALIDARG; return S_OK; } static HRESULT DataObject_GetData_HDROP_Names(IDataObject *dataObject, UStringVector &names) { names.Clear(); NCOM::CStgMedium medium; /* Win10 : if (dataObject) is from IContextMenu::Initialize() and if (len_of_path >= MAX_PATH (260) for some file in data object) { GetData() returns HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) "The data area passed to a system call is too small", Is there a way to fix this code for long paths? } */ RINOK(DataObject_GetData_HGLOBAL(dataObject, CF_HDROP, medium)) const size_t blockSize = GlobalSize(medium.hGlobal); if (blockSize < sizeof(DROPFILES)) return E_INVALIDARG; NMemory::CGlobalLock dropLock(medium.hGlobal); const DROPFILES *dropFiles = (const DROPFILES *)dropLock.GetPointer(); if (!dropFiles) return E_INVALIDARG; if (blockSize < dropFiles->pFiles || dropFiles->pFiles < sizeof(DROPFILES) // || dropFiles->pFiles != sizeof(DROPFILES) ) return E_INVALIDARG; const size_t size = blockSize - dropFiles->pFiles; const void *namesData = (const Byte *)(const void *)dropFiles + dropFiles->pFiles; HRESULT hres; if (dropFiles->fWide) { if (size % sizeof(wchar_t) != 0) return E_INVALIDARG; hres = ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names); } else hres = ReadAnsiStrings((const char *)namesData, size, names); ODS_(Print_Number(names.Size(), "DataObject_GetData_HDROP_Names")) return hres; } // CF_IDLIST: #define MYWIN_CFSTR_SHELLIDLIST TEXT("Shell IDList Array") typedef struct { UINT cidl; UINT aoffset[1]; } MYWIN_CIDA; /* cidl : number of PIDLs that are being transferred, not including the parent folder. aoffset : An array of offsets, relative to the beginning of this structure. aoffset[0] - fully qualified PIDL of a parent folder. If this PIDL is empty, the parent folder is the desktop. aoffset[1] ... aoffset[cidl] : offset to one of the PIDLs to be transferred. All of these PIDLs are relative to the PIDL of the parent folder. */ static HRESULT DataObject_GetData_IDLIST(IDataObject *dataObject, UStringVector &names) { names.Clear(); NCOM::CStgMedium medium; RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT) RegisterClipboardFormat(MYWIN_CFSTR_SHELLIDLIST), medium)) const size_t blockSize = GlobalSize(medium.hGlobal); if (blockSize < sizeof(MYWIN_CIDA) || blockSize >= (UInt32)((UInt32)0 - 1)) return E_INVALIDARG; NMemory::CGlobalLock dropLock(medium.hGlobal); const MYWIN_CIDA *cida = (const MYWIN_CIDA *)dropLock.GetPointer(); if (!cida) return E_INVALIDARG; if (cida->cidl == 0) { // is it posssible to have no selected items? // it's unexpected case. return E_INVALIDARG; } if (cida->cidl >= (blockSize - (UInt32)sizeof(MYWIN_CIDA)) / sizeof(UINT)) return E_INVALIDARG; const UInt32 start = cida->cidl * (UInt32)sizeof(UINT) + (UInt32)sizeof(MYWIN_CIDA); STRRET strret; CMyComPtr parentFolder; { const UINT offset = cida->aoffset[0]; if (offset < start || offset >= blockSize // || offset != start ) return E_INVALIDARG; CMyComPtr desktopFolder; RINOK(::SHGetDesktopFolder(&desktopFolder)) if (!desktopFolder) return E_FAIL; LPCITEMIDLIST const lpcItem = (LPCITEMIDLIST)(const void *)((const Byte *)cida + offset); #ifdef SHOW_DEBUG_SHELL { const HRESULT res = desktopFolder->GetDisplayNameOf( lpcItem, SHGDN_FORPARSING, &strret); if (res == S_OK && strret.uType == STRRET_WSTR) { ODS_U(strret.pOleStr) /* if lpcItem is empty, the path will be "C:\Users\user_name\Desktop" if lpcItem is "My Computer" folder, the path will be "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" */ CoTaskMemFree(strret.pOleStr); } } #endif RINOK(desktopFolder->BindToObject(lpcItem, NULL, IID_IShellFolder, (void **)&parentFolder)) if (!parentFolder) return E_FAIL; } names.ClearAndReserve(cida->cidl); UString path; // for (int y = 0; y < 1; y++) // for debug for (unsigned i = 1; i <= cida->cidl; i++) { const UINT offset = cida->aoffset[i]; if (offset < start || offset >= blockSize) return E_INVALIDARG; const void *p = (const Byte *)(const void *)cida + offset; /* ITEMIDLIST of file can contain more than one SHITEMID item. In win10 only SHGDN_FORPARSING returns path that contains all path parts related to parts of ITEMIDLIST. So we can use only SHGDN_FORPARSING here. Don't use (SHGDN_INFOLDER) Don't use (SHGDN_INFOLDER | SHGDN_FORPARSING) */ RINOK(parentFolder->GetDisplayNameOf((LPCITEMIDLIST)p, SHGDN_FORPARSING, &strret)) /* // MSVC6 and old SDK do not support StrRetToStrW(). LPWSTR lpstr; RINOK (StrRetToStrW(&strret, NULL, &lpstr)) ODS_U(lpstr) path = lpstr; CoTaskMemFree(lpstr); */ if (strret.uType != STRRET_WSTR) return E_INVALIDARG; ODS_U(strret.pOleStr) path = strret.pOleStr; // the path could have super path prefix "\\\\?\\" // we can remove super path prefix here, if we don't need that prefix #ifdef Z7_LONG_PATH // we remove super prefix, if we can work without that prefix NFile::NName::If_IsSuperPath_RemoveSuperPrefix(path); #endif names.AddInReserved(path); CoTaskMemFree(strret.pOleStr); } ODS_(Print_Number(cida->cidl, "CFSTR_SHELLIDLIST END")) return S_OK; } HRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &paths) { ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names START") HRESULT hres = NShell::DataObject_GetData_HDROP_Names(dataObject, paths); // if (hres == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) if (hres != S_OK) { ODS("-- DataObject_GetData_IDLIST START") // for (int y = 0; y < 10000; y++) // for debug hres = NShell::DataObject_GetData_IDLIST(dataObject, paths); } ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names END") return hres; } // #if (NTDDI_VERSION >= NTDDI_VISTA) typedef struct { UINT cItems; // number of items in rgdwFileAttributes array DWORD dwSumFileAttributes; // all of the attributes ORed together DWORD dwProductFileAttributes; // all of the attributes ANDed together DWORD rgdwFileAttributes[1]; // array } MYWIN_FILE_ATTRIBUTES_ARRAY; #define MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY TEXT("File Attributes Array") HRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs) { attribs.Clear(); NCOM::CStgMedium medium; RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT) RegisterClipboardFormat(MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY), medium)) const size_t blockSize = GlobalSize(medium.hGlobal); if (blockSize < sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY)) return E_INVALIDARG; NMemory::CGlobalLock dropLock(medium.hGlobal); const MYWIN_FILE_ATTRIBUTES_ARRAY *faa = (const MYWIN_FILE_ATTRIBUTES_ARRAY *)dropLock.GetPointer(); if (!faa) return E_INVALIDARG; const unsigned numFiles = faa->cItems; if (numFiles == 0) { // is it posssible to have empty array here? return E_INVALIDARG; } if ((blockSize - (sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY) - sizeof(DWORD))) / sizeof(DWORD) != numFiles) return E_INVALIDARG; // attribs.Sum = faa->dwSumFileAttributes; // attribs.Product = faa->dwProductFileAttributes; // attribs.Vals.SetFromArray(faa->rgdwFileAttributes, numFiles); // attribs.IsDirVector.ClearAndSetSize(numFiles); if ((faa->dwSumFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { /* in win10: if selected items are volumes (c:\, d:\ ..) in My Compter, all items have FILE_ATTRIBUTE_DIRECTORY attribute ntfs volume also have FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM udf volume: FILE_ATTRIBUTE_READONLY dvd-rom device: (-1) : all bits are set */ const DWORD *attr = faa->rgdwFileAttributes; // DWORD product = (UInt32)0 - 1, sum = 0; for (unsigned i = 0; i < numFiles; i++) { if (attr[i] & FILE_ATTRIBUTE_DIRECTORY) { // attribs.ThereAreDirs = true; attribs.FirstDirIndex = (int)i; break; } // attribs.IsDirVector[i] = (attr[i] & FILE_ATTRIBUTE_DIRECTORY) != 0; // product &= v; // sum |= v; } // ODS_(Print_Number(product, "Product calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) // ODS_(Print_Number(sum, "Sum calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) } // ODS_(Print_Number(attribs.Product, "Product FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) // ODS_(Print_Number(attribs.Sum, "Sum FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) ODS_(Print_Number(numFiles, "FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) return S_OK; } ///////////////////////////// // CDrop /* win10: DragQueryFile() implementation code is not effective because there is no pointer inside DROP internal file list, so DragQueryFile(fileIndex) runs all names in range [0, fileIndex]. DragQueryFile(,, buf, bufSize) if (buf == NULL) by spec { returns value is the required size in characters, of the buffer, not including the terminating null character tests show that if (bufSize == 0), then it also returns required size. } if (bufSize != NULL) { returns: the count of the characters copied, not including null character. win10: null character is also copied at position buf[ret_count]; } */ /* void CDrop::Attach(HDROP object) { Free(); m_Object = object; m_Assigned = true; } void CDrop::Free() { if (m_MustBeFinished && m_Assigned) Finish(); m_Assigned = false; } UINT CDrop::QueryCountOfFiles() { return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); } void CDrop::QueryFileName(UINT fileIndex, UString &fileName) { #ifndef _UNICODE if (!g_IsNT) { AString fileNameA; const UINT len = QueryFile(fileIndex, (LPTSTR)NULL, 0); const UINT numCopied = QueryFile(fileIndex, fileNameA.GetBuf(len + 2), len + 2); fileNameA.ReleaseBuf_CalcLen(len); if (numCopied != len) throw 20221223; fileName = GetUnicodeString(fileNameA); } else #endif { // kReserve must be >= 3 for additional buffer size // safety and for optimal performance const unsigned kReserve = 3; { unsigned len = 0; wchar_t *buf = fileName.GetBuf_GetMaxAvail(len); if (len >= kReserve) { const UINT numCopied = QueryFile(fileIndex, buf, len); if (numCopied < len - 1) { // (numCopied < len - 1) case means that it have copied full string. fileName.ReleaseBuf_CalcLen(numCopied); return; } } } const UINT len = QueryFile(fileIndex, (LPWSTR)NULL, 0); const UINT numCopied = QueryFile(fileIndex, fileName.GetBuf(len + kReserve), len + kReserve); fileName.ReleaseBuf_CalcLen(len); if (numCopied != len) throw 20221223; } } void CDrop::QueryFileNames(UStringVector &fileNames) { UINT numFiles = QueryCountOfFiles(); Print_Number(numFiles, "\n====== CDrop::QueryFileNames START ===== \n"); fileNames.ClearAndReserve(numFiles); UString s; for (UINT i = 0; i < numFiles; i++) { QueryFileName(i, s); if (!s.IsEmpty()) fileNames.AddInReserved(s); } Print_Number(numFiles, "\n====== CDrop::QueryFileNames END ===== \n"); } */ // #if (NTDDI_VERSION >= NTDDI_VISTA) // SHGetPathFromIDListEx returns a win32 file system path for the item in the name space. typedef int Z7_WIN_GPFIDL_FLAGS; extern "C" { #ifndef _UNICODE typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); // nt4 #endif #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0600 // Vista #define Z7_USE_DYN_SHGetPathFromIDListEx #endif #ifdef Z7_USE_DYN_SHGetPathFromIDListEx Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION typedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); // vista #endif } #ifndef _UNICODE bool GetPathFromIDList(LPCITEMIDLIST itemIDList, AString &path) { path.Empty(); const unsigned len = MAX_PATH + 16; const bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); path.ReleaseBuf_CalcLen(len); return result; } #endif bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) { path.Empty(); unsigned len = MAX_PATH + 16; #ifdef _UNICODE bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); #else const Func_SHGetPathFromIDListW shGetPathFromIDListW = Z7_GET_PROC_ADDRESS( Func_SHGetPathFromIDListW, ::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); if (!shGetPathFromIDListW) return false; bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); #endif if (!result) { ODS("==== GetPathFromIDList() SHGetPathFromIDList() returned false") /* for long path we need SHGetPathFromIDListEx(). win10: SHGetPathFromIDListEx() for long path returns path with with super path prefix "\\\\?\\". */ #ifdef Z7_USE_DYN_SHGetPathFromIDListEx const Func_SHGetPathFromIDListEx func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS( Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListEx"); if (func_SHGetPathFromIDListEx) #endif { ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)") do { len *= 4; result = BOOLToBool( #ifdef Z7_USE_DYN_SHGetPathFromIDListEx func_SHGetPathFromIDListEx #else SHGetPathFromIDListEx #endif (itemIDList, path.GetBuf(len), len, 0)); if (result) break; } while (len <= (1 << 16)); } } path.ReleaseBuf_CalcLen(len); return result; } #endif #ifdef UNDER_CE bool BrowseForFolder(LPBROWSEINFO, CSysString) { return false; } bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) { return false; } bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, LPCTSTR /* initialFolder */, CSysString & /* resultPath */) { /* // SHBrowseForFolder doesn't work before CE 6.0 ? if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) MessageBoxW(0, L"no", L"", 0); else MessageBoxW(0, L"yes", L"", 0); */ /* UString s = "all files"; s += " (*.*)"; return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); */ return false; } #else /* win10: SHBrowseForFolder() doesn't support long paths, even if long path suppport is enabled in registry and in manifest. and SHBrowseForFolder() doesn't support super path prefix "\\\\?\\". */ bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) { resultPath.Empty(); NWindows::NCOM::CComInitializer comInitializer; LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); if (!itemIDList) return false; CItemIDList itemIDListHolder; itemIDListHolder.Attach(itemIDList); return GetPathFromIDList(itemIDList, resultPath); } static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) { #ifndef UNDER_CE switch (uMsg) { case BFFM_INITIALIZED: { SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); break; } /* case BFFM_SELCHANGED: { TCHAR dir[MAX_PATH]; if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); else SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); break; } */ default: break; } #endif return 0; } static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, LPCTSTR initialFolder, CSysString &resultPath) { CSysString displayName; BROWSEINFO browseInfo; browseInfo.hwndOwner = owner; browseInfo.pidlRoot = NULL; // there are Unicode/Astring problems in some WinCE SDK ? /* #ifdef UNDER_CE browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); browseInfo.lpszTitle = (LPCSTR)title; #else */ browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); browseInfo.lpszTitle = title; // #endif browseInfo.ulFlags = ulFlags; browseInfo.lpfn = initialFolder ? BrowseCallbackProc : NULL; browseInfo.lParam = (LPARAM)initialFolder; return BrowseForFolder(&browseInfo, resultPath); } #ifdef Z7_OLD_WIN_SDK // ShlObj.h: #ifndef BIF_NEWDIALOGSTYLE #define BIF_NEWDIALOGSTYLE 0x0040 #endif #endif bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath) { return BrowseForFolder(owner, title, #ifndef UNDER_CE BIF_NEWDIALOGSTYLE | #endif BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) } #ifndef _UNICODE extern "C" { typedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi); } static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) { NWindows::NCOM::CComInitializer comInitializer; const Func_SHBrowseForFolderW f_SHBrowseForFolderW = Z7_GET_PROC_ADDRESS( Func_SHBrowseForFolderW, ::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); if (!f_SHBrowseForFolderW) return false; LPITEMIDLIST itemIDList = f_SHBrowseForFolderW(browseInfo); if (!itemIDList) return false; CItemIDList itemIDListHolder; itemIDListHolder.Attach(itemIDList); return GetPathFromIDList(itemIDList, resultPath); } static int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) { switch (uMsg) { case BFFM_INITIALIZED: { SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); break; } /* case BFFM_SELCHANGED: { wchar_t dir[MAX_PATH * 2]; if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); else SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); break; } */ default: break; } return 0; } static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, LPCWSTR initialFolder, UString &resultPath) { UString displayName; BROWSEINFOW browseInfo; browseInfo.hwndOwner = owner; browseInfo.pidlRoot = NULL; browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); browseInfo.lpszTitle = title; browseInfo.ulFlags = ulFlags; browseInfo.lpfn = initialFolder ? BrowseCallbackProc2 : NULL; browseInfo.lParam = (LPARAM)initialFolder; return BrowseForFolder(&browseInfo, resultPath); } bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) { if (g_IsNT) return BrowseForFolder(owner, title, BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. , initialFolder, resultPath); // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) CSysString s; bool res = BrowseForFolder(owner, GetSystemString(title), BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. , GetSystemString(initialFolder), s); resultPath = GetUnicodeString(s); return res; } #endif #endif }} tmp41wklro_/CPP/Windows/Shell.h0000444000175000001440000000631314555152040017441 0ustar nabijaczleweliusers// Windows/Shell.h #ifndef ZIP7_WINDOWS_SHELL_H #define ZIP7_WINDOWS_SHELL_H #include "../Common/MyWindows.h" #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NShell { ///////////////////////// // CItemIDList #ifndef UNDER_CE class CItemIDList { LPITEMIDLIST m_Object; Z7_CLASS_NO_COPY(CItemIDList) public: CItemIDList(): m_Object(NULL) {} // CItemIDList(LPCITEMIDLIST itemIDList); // CItemIDList(const CItemIDList& itemIDList); ~CItemIDList() { Free(); } void Free(); void Attach(LPITEMIDLIST object) { Free(); m_Object = object; } LPITEMIDLIST Detach() { LPITEMIDLIST object = m_Object; m_Object = NULL; return object; } operator LPITEMIDLIST() { return m_Object;} operator LPCITEMIDLIST() const { return m_Object;} LPITEMIDLIST* operator&() { return &m_Object; } LPITEMIDLIST operator->() { return m_Object; } // CItemIDList& operator=(LPCITEMIDLIST object); // CItemIDList& operator=(const CItemIDList &object); }; ///////////////////////////// // CDrop /* class CDrop { HDROP m_Object; bool m_MustBeFinished; bool m_Assigned; void Free(); public: CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {} ~CDrop() { Free(); } void Attach(HDROP object); operator HDROP() { return m_Object;} bool QueryPoint(LPPOINT point) { return BOOLToBool(::DragQueryPoint(m_Object, point)); } void Finish() { ::DragFinish(m_Object); } UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT bufSize) { return ::DragQueryFile(m_Object, fileIndex, fileName, bufSize); } #ifndef _UNICODE UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT bufSize) { return ::DragQueryFileW(m_Object, fileIndex, fileName, bufSize); } #endif UINT QueryCountOfFiles(); void QueryFileName(UINT fileIndex, UString &fileName); void QueryFileNames(UStringVector &fileNames); }; */ #endif struct CFileAttribs { int FirstDirIndex; // DWORD Sum; // DWORD Product; // CRecordVector Vals; // CRecordVector IsDirVector; CFileAttribs() { Clear(); } void Clear() { FirstDirIndex = -1; // Sum = 0; // Product = 0; // IsDirVector.Clear(); } }; /* read pathnames from HDROP or SHELLIDLIST. The parser can return E_INVALIDARG, if there is some unexpected data in dataObject */ HRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &names); HRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs); bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path); bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath); bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath); #ifndef _UNICODE bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path); bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath); bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath); #endif }} #endif tmp41wklro_/CPP/Windows/StdAfx.h0000444000175000001440000000035314533321440017557 0ustar nabijaczleweliusers// StdAfx.h #ifndef ZIP7_INC_STDAFX_H #define ZIP7_INC_STDAFX_H #if defined(_MSC_VER) && _MSC_VER >= 1800 #pragma warning(disable : 4464) // relative include path contains '..' #endif #include "../Common/Common.h" #endif tmp41wklro_/CPP/Windows/Synchronization.cpp0000444000175000001440000000346014405305640022126 0ustar nabijaczleweliusers// Windows/Synchronization.cpp #include "StdAfx.h" #ifndef _WIN32 #include "Synchronization.h" namespace NWindows { namespace NSynchronization { /* #define INFINITE 0xFFFFFFFF #define MAXIMUM_WAIT_OBJECTS 64 #define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L) #define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) #define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 ) // WINAPI DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout); */ /* clang: we need to place some virtual functions in cpp file to rid off the warning: 'CBaseHandle_WFMO' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit */ CBaseHandle_WFMO::~CBaseHandle_WFMO() { } bool CBaseEvent_WFMO::IsSignaledAndUpdate() { if (this->_state == false) return false; if (this->_manual_reset == false) this->_state = false; return true; } bool CSemaphore_WFMO::IsSignaledAndUpdate() { if (this->_count == 0) return false; this->_count--; return true; } DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) { if (count < 1) { // abort(); SetLastError(EINVAL); return WAIT_FAILED; } CSynchro *synchro = handles[0]->_sync; synchro->Enter(); // #ifdef DEBUG_SYNCHRO for (DWORD i = 1; i < count; i++) { if (synchro != handles[i]->_sync) { // abort(); synchro->Leave(); SetLastError(EINVAL); return WAIT_FAILED; } } // #endif for (;;) { for (DWORD i = 0; i < count; i++) { if (handles[i]->IsSignaledAndUpdate()) { synchro->Leave(); return WAIT_OBJECT_0 + i; } } synchro->WaitCond(); } } }} #endif tmp41wklro_/CPP/Windows/Synchronization.h0000444000175000001440000002202014571036020021561 0ustar nabijaczleweliusers// Windows/Synchronization.h #ifndef ZIP7_INC_WINDOWS_SYNCHRONIZATION_H #define ZIP7_INC_WINDOWS_SYNCHRONIZATION_H #include "../../C/Threads.h" #include "../Common/MyTypes.h" #include "Defs.h" #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent MY_UNCOPYABLE { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 operator HANDLE() { return _object; } WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) { _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (name == NULL && _object != NULL) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object != NULL) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated_Reset() { if (IsCreated()) return Reset(); return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated_Reset() { if (IsCreated()) return Reset(); return AutoResetEvent_CreateNotSignaled(&_object); } }; /* #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) { _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name); if (name == NULL && _handle != 0) return 0; return ::GetLastError(); } #ifndef UNDER_CE WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } #endif WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock MY_UNCOPYABLE { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif // _WIN32 */ class CSemaphore MY_UNCOPYABLE { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } #ifdef _WIN32 operator HANDLE() { return _object; } #endif // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; } WRes Create(UInt32 initCount, UInt32 maxCount) { return Semaphore_Create(&_object, initCount, maxCount); } WRes OptCreateInit(UInt32 initCount, UInt32 maxCount) { return Semaphore_OptCreateInit(&_object, initCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection MY_UNCOPYABLE { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock MY_UNCOPYABLE { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; #ifdef _WIN32 typedef HANDLE CHandle_WFMO; typedef CSemaphore CSemaphore_WFMO; typedef CAutoResetEvent CAutoResetEvent_WFMO; typedef CManualResetEvent CManualResetEvent_WFMO; inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) { return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); } #define SYNC_OBJ_DECL(obj) #define SYNC_WFMO(x) #define SYNC_PARAM(x) #define SYNC_PARAM_DECL(x) #else // _WIN32 // POSIX sync objects for WaitForMultipleObjects #define SYNC_WFMO(x) x #define SYNC_PARAM(x) x, #define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x #define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x; class CSynchro MY_UNCOPYABLE { pthread_mutex_t _mutex; pthread_cond_t _cond; bool _isValid; public: CSynchro() { _isValid = false; } ~CSynchro() { if (_isValid) { ::pthread_mutex_destroy(&_mutex); ::pthread_cond_destroy(&_cond); } _isValid = false; } WRes Create() { RINOK(::pthread_mutex_init(&_mutex, NULL)) const WRes ret = ::pthread_cond_init(&_cond, NULL); _isValid = 1; return ret; } WRes Enter() { #if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \ && defined(__FreeBSD__) #pragma GCC diagnostic ignored "-Wthread-safety-negative" #pragma GCC diagnostic ignored "-Wthread-safety-analysis" #endif return ::pthread_mutex_lock(&_mutex); } WRes Leave() { return ::pthread_mutex_unlock(&_mutex); } WRes WaitCond() { return ::pthread_cond_wait(&_cond, &_mutex); } WRes LeaveAndSignal() { const WRes res1 = ::pthread_cond_broadcast(&_cond); const WRes res2 = ::pthread_mutex_unlock(&_mutex); return (res2 ? res2 : res1); } }; struct CBaseHandle_WFMO; typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO; // these constants are from Windows #define WAIT_OBJECT_0 0 #define WAIT_FAILED ((DWORD)0xFFFFFFFF) DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles); struct CBaseHandle_WFMO MY_UNCOPYABLE { CSynchro *_sync; CBaseHandle_WFMO(): _sync(NULL) {} virtual ~CBaseHandle_WFMO(); operator CHandle_WFMO() { return this; } virtual bool IsSignaledAndUpdate() = 0; }; class CBaseEvent_WFMO : public CBaseHandle_WFMO { bool _manual_reset; bool _state; public: // bool IsCreated() { return (this->_sync != NULL); } // CBaseEvent_WFMO() { ; } // ~CBaseEvent_WFMO() Z7_override { Close(); } WRes Close() { this->_sync = NULL; return 0; } WRes Create( CSynchro *sync, bool manualReset, bool initiallyOwn) { this->_sync = sync; this->_manual_reset = manualReset; this->_state = initiallyOwn; return 0; } WRes Set() { RINOK(this->_sync->Enter()) this->_state = true; return this->_sync->LeaveAndSignal(); } WRes Reset() { RINOK(this->_sync->Enter()) this->_state = false; return this->_sync->Leave(); } virtual bool IsSignaledAndUpdate() Z7_override; }; class CManualResetEvent_WFMO Z7_final: public CBaseEvent_WFMO { public: WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } }; class CAutoResetEvent_WFMO Z7_final: public CBaseEvent_WFMO { public: WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } WRes CreateIfNotCreated_Reset(CSynchro *sync) { return Create(sync); } }; class CSemaphore_WFMO Z7_final: public CBaseHandle_WFMO { UInt32 _count; UInt32 _maxCount; public: CSemaphore_WFMO() : _count(0), _maxCount(0) {} WRes Close() { this->_sync = NULL; return 0; } WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) { if (initCount > maxCount || maxCount < 1) return EINVAL; this->_sync = sync; this->_count = initCount; this->_maxCount = maxCount; return 0; } WRes Release(UInt32 releaseCount = 1) { if (releaseCount < 1) return EINVAL; RINOK(this->_sync->Enter()) UInt32 newCount = this->_count + releaseCount; if (newCount > this->_maxCount) { RINOK(this->_sync->Leave()) return ERROR_TOO_MANY_POSTS; // EINVAL } this->_count = newCount; return this->_sync->LeaveAndSignal(); } virtual bool IsSignaledAndUpdate() Z7_override; }; #endif // _WIN32 }} #endif tmp41wklro_/CPP/Windows/System.cpp0000444000175000001440000001722514603664460020225 0ustar nabijaczleweliusers// Windows/System.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #if defined(__APPLE__) || defined(__DragonFly__) || \ defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #else #include #endif #endif #include "../Common/Defs.h" // #include "../Common/MyWindows.h" // #include "../../C/CpuArch.h" #include "System.h" namespace NWindows { namespace NSystem { #ifdef _WIN32 UInt32 CountAffinity(DWORD_PTR mask) { UInt32 num = 0; for (unsigned i = 0; i < sizeof(mask) * 8; i++) { num += (UInt32)(mask & 1); mask >>= 1; } return num; } BOOL CProcessAffinity::Get() { #ifndef UNDER_CE return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); #else return FALSE; #endif } UInt32 GetNumberOfProcessors() { // We need to know how many threads we can use. // By default the process is assigned to one group. // So we get the number of logical processors (threads) // assigned to current process in the current group. // Group size can be smaller than total number logical processors, for exammple, 2x36 CProcessAffinity pa; if (pa.Get() && pa.processAffinityMask != 0) return pa.GetNumProcessThreads(); SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); // the number of logical processors in the current group return (UInt32)systemInfo.dwNumberOfProcessors; } #else BOOL CProcessAffinity::Get() { numSysThreads = GetNumberOfProcessors(); /* numSysThreads = 8; for (unsigned i = 0; i < numSysThreads; i++) CpuSet_Set(&cpu_set, i); return TRUE; */ #ifdef Z7_AFFINITY_SUPPORTED // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0) return FALSE; return TRUE; #else // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1; return TRUE; // errno = ENOSYS; // return FALSE; #endif } UInt32 GetNumberOfProcessors() { #ifndef Z7_ST long n = sysconf(_SC_NPROCESSORS_CONF); // The number of processors configured if (n < 1) n = 1; return (UInt32)n; #else return 1; #endif } #endif #ifdef _WIN32 #ifndef UNDER_CE #if !defined(_WIN64) && \ (defined(__MINGW32_VERSION) || defined(Z7_OLD_WIN_SDK)) typedef struct { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer); #endif // !UNDER_CE bool GetRamSize(UInt64 &size) { size = (UInt64)(sizeof(size_t)) << 29; #ifndef UNDER_CE MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #endif #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return false; size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); return true; #else #ifndef UNDER_CE const Func_GlobalMemoryStatusEx fn = Z7_GET_PROC_ADDRESS( Func_GlobalMemoryStatusEx, ::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx"); if (fn && fn(&stat)) { size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); return true; } #endif { MEMORYSTATUS stat2; stat2.dwLength = sizeof(stat2); ::GlobalMemoryStatus(&stat2); size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys); return true; } #endif } #else // POSIX // #include bool GetRamSize(UInt64 &size) { size = (UInt64)(sizeof(size_t)) << 29; #if defined(__APPLE__) || defined(__DragonFly__) || \ defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) uint64_t val = 0; int mib[2]; mib[0] = CTL_HW; #ifdef HW_MEMSIZE mib[1] = HW_MEMSIZE; // printf("\n sysctl HW_MEMSIZE"); #elif defined(HW_PHYSMEM64) mib[1] = HW_PHYSMEM64; // printf("\n sysctl HW_PHYSMEM64"); #else mib[1] = HW_PHYSMEM; // printf("\n sysctl HW_PHYSMEM"); #endif size_t size_sys = sizeof(val); int res = sysctl(mib, 2, &val, &size_sys, NULL, 0); // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val, (int)size_sys, errno); // we use strict check (size_sys == sizeof(val)) for returned value // because big-endian encoding is possible: if (res == 0 && size_sys == sizeof(val) && val) size = val; else { uint32_t val32 = 0; size_sys = sizeof(val32); res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); if (res == 0 && size_sys == sizeof(val32) && val32) size = val32; } #elif defined(_AIX) #if defined(_SC_AIX_REALMEM) // AIX size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; #endif #elif 0 || defined(__sun) #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) // FreeBSD, Linux, OpenBSD, and Solaris. { const long phys_pages = sysconf(_SC_PHYS_PAGES); const long page_size = sysconf(_SC_PAGESIZE); // #pragma message("GetRamSize : sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)") // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); if (phys_pages != -1 && page_size != -1) size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; } #endif #elif defined(__gnu_hurd__) // fixme #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__) // GNU/kFreeBSD Debian // fixme #else struct sysinfo info; if (::sysinfo(&info) != 0) return false; size = (UInt64)info.mem_unit * info.totalram; /* printf("\n mem_unit = %lld", (UInt64)info.mem_unit); printf("\n totalram = %lld", (UInt64)info.totalram); printf("\n freeram = %lld", (UInt64)info.freeram); */ #endif const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); if (size > kLimit) size = kLimit; return true; } #endif unsigned long Get_File_OPEN_MAX() { #ifdef _WIN32 return (1 << 24) - (1 << 16); // ~16M handles #else // some linux versions have default open file limit for user process of 1024 files. long n = sysconf(_SC_OPEN_MAX); // n = -1; // for debug // n = 9; // for debug if (n < 1) { // n = OPEN_MAX; // ??? // n = FOPEN_MAX; // = 16 : #ifdef _POSIX_OPEN_MAX n = _POSIX_OPEN_MAX; // = 20 : #else n = 30; // our limit #endif } return (unsigned long)n; #endif } unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks() { unsigned long numFiles_OPEN_MAX = NSystem::Get_File_OPEN_MAX(); const unsigned delta = 10; // the reserve for another internal needs of process if (numFiles_OPEN_MAX > delta) numFiles_OPEN_MAX -= delta; else numFiles_OPEN_MAX = 1; numFiles_OPEN_MAX /= 3; // we suppose that we have up to 3 tasks in total for multiple file processing numFiles_OPEN_MAX = MyMax(numFiles_OPEN_MAX, (unsigned long)3); unsigned n = (unsigned)(int)-1; if (n > numFiles_OPEN_MAX) n = (unsigned)numFiles_OPEN_MAX; return n; } }} tmp41wklro_/CPP/Windows/System.h0000444000175000001440000000535314563351220017661 0ustar nabijaczleweliusers// Windows/System.h #ifndef ZIP7_INC_WINDOWS_SYSTEM_H #define ZIP7_INC_WINDOWS_SYSTEM_H #ifndef _WIN32 // #include #include "../../C/Threads.h" #endif #include "../Common/MyTypes.h" #include "../Common/MyWindows.h" namespace NWindows { namespace NSystem { #ifdef _WIN32 UInt32 CountAffinity(DWORD_PTR mask); struct CProcessAffinity { // UInt32 numProcessThreads; // UInt32 numSysThreads; DWORD_PTR processAffinityMask; DWORD_PTR systemAffinityMask; void InitST() { // numProcessThreads = 1; // numSysThreads = 1; processAffinityMask = 1; systemAffinityMask = 1; } void CpuZero() { processAffinityMask = 0; } void CpuSet(unsigned cpuIndex) { processAffinityMask |= ((DWORD_PTR)1 << cpuIndex); } UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } BOOL Get(); BOOL SetProcAffinity() const { return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask); } }; #else // WIN32 struct CProcessAffinity { UInt32 numSysThreads; UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; } BOOL Get(); #ifdef Z7_AFFINITY_SUPPORTED CCpuSet cpu_set; void InitST() { numSysThreads = 1; CpuSet_Zero(&cpu_set); CpuSet_Set(&cpu_set, 0); } UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); } void CpuZero() { CpuSet_Zero(&cpu_set); } void CpuSet(unsigned cpuIndex) { CpuSet_Set(&cpu_set, cpuIndex); } int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); } // void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); } BOOL SetProcAffinity() const { return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0; } #else // Z7_AFFINITY_SUPPORTED void InitST() { numSysThreads = 1; } UInt32 GetNumProcessThreads() const { return numSysThreads; /* UInt32 num = 0; for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++) num += (UInt32)((cpu_set >> i) & 1); return num; */ } void CpuZero() { } void CpuSet(unsigned /* cpuIndex */) { /* UNUSED_VAR(cpuIndex) */ } int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; } BOOL SetProcAffinity() const { errno = ENOSYS; return FALSE; } #endif // Z7_AFFINITY_SUPPORTED }; #endif // _WIN32 UInt32 GetNumberOfProcessors(); bool GetRamSize(UInt64 &size); // returns false, if unknown ram size unsigned long Get_File_OPEN_MAX(); unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks(); }} #endif tmp41wklro_/CPP/Windows/SystemInfo.cpp0000444000175000001440000006206414656114660021042 0ustar nabijaczleweliusers// Windows/SystemInfo.cpp #include "StdAfx.h" #include "../../C/CpuArch.h" #include "../Common/IntToString.h" #include "../Common/StringConvert.h" #ifdef _WIN32 #include "Registry.h" #else #include #include #ifdef __APPLE__ #include #elif !defined(_AIX) #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) #define Z7_GETAUXV_AVAILABLE #else // #pragma message("=== is not NEW GLIBC === ") #if defined __has_include #if __has_include () // #pragma message("=== sys/auxv.h is avail=== ") #define Z7_GETAUXV_AVAILABLE #endif #endif #endif #ifdef Z7_GETAUXV_AVAILABLE // #if defined __has_include // #if __has_include () #include #define USE_HWCAP // #endif // #endif // #undef AT_HWCAP // to debug // #undef AT_HWCAP2 // to debug /* the following patch for some debian systems. Is it OK to define AT_HWCAP and AT_HWCAP2 here with these constant numbers? */ /* #if defined(__FreeBSD_kernel__) && defined(__GLIBC__) #ifndef AT_HWCAP #define AT_HWCAP 16 #endif #ifndef AT_HWCAP2 #define AT_HWCAP2 26 #endif #endif */ #ifdef USE_HWCAP #if defined(__FreeBSD__) // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???) static unsigned long MY_getauxval(int aux) { unsigned long val; if (elf_aux_info(aux, &val, sizeof(val))) return 0; return val; } #else // ! __FreeBSD__ #ifdef MY_CPU_ARM_OR_ARM64 #if defined __has_include #if __has_include () #include #endif #endif #endif #if defined(AT_HWCAP) || defined(AT_HWCAP2) #define MY_getauxval getauxval #endif #endif // ! __FreeBSD__ #endif // USE_HWCAP #endif // Z7_GETAUXV_AVAILABLE #endif // !defined(_AIX) #ifdef __linux__ #include "../Windows/FileIO.h" #endif #endif // WIN32 #include "SystemInfo.h" #include "System.h" using namespace NWindows; #ifdef __linux__ static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; /* UInt64 size; if (!file.GetLength(size)) { // GetLength() doesn't work "/proc/cpuinfo" return false; } if (size >= ((UInt32)1 << 29)) return false; */ size_t size = 0; size_t addSize = (size_t)1 << 12; for (;;) { // printf("\nsize = %d\n", (unsigned)size); buf.ChangeSize_KeepData(size + addSize, size); size_t processed; if (!file.ReadFull(buf.NonConstData() + size, addSize, processed)) return false; if (processed == 0) { buf.ChangeSize_KeepData(size, size); return true; } size += processed; addSize *= 2; } } #endif #if defined(_WIN32) || defined(AT_HWCAP) || defined(AT_HWCAP2) static void PrintHex(AString &s, UInt64 v) { char temp[32]; ConvertUInt64ToHex(v, temp); s += temp; } #endif #ifdef MY_CPU_X86_OR_AMD64 Z7_NO_INLINE static void PrintCpuChars(AString &s, UInt32 v) { for (unsigned j = 0; j < 4; j++) { const Byte b = (Byte)(v & 0xFF); v >>= 8; if (b == 0) break; if (b >= 0x20 && b <= 0x7f) s.Add_Char((char)b); else { s.Add_Char('['); char temp[16]; ConvertUInt32ToHex(b, temp); s += temp; s.Add_Char(']'); } } } static void x86cpuid_to_String(AString &s) { s.Empty(); UInt32 a[4]; // cpuid was called already. So we don't check for cpuid availability here z7_x86_cpuid(a, 0x80000000); if (a[0] >= 0x80000004) // if (maxFunc2 >= hi+4) the full name is available { for (unsigned i = 0; i < 3; i++) { z7_x86_cpuid(a, (UInt32)(0x80000002 + i)); for (unsigned j = 0; j < 4; j++) PrintCpuChars(s, a[j]); } } s.Trim(); if (s.IsEmpty()) { z7_x86_cpuid(a, 0); for (unsigned i = 1; i < 4; i++) { const unsigned j = (i ^ (i >> 1)); PrintCpuChars(s, a[j]); } s.Trim(); } } /* static void x86cpuid_all_to_String(AString &s) { Cx86cpuid p; if (!x86cpuid_CheckAndRead(&p)) return; s += "x86cpuid maxFunc = "; s.Add_UInt32(p.maxFunc); for (unsigned j = 0; j <= p.maxFunc; j++) { s.Add_LF(); // s.Add_UInt32(j); // align { char temp[32]; ConvertUInt32ToString(j, temp); unsigned len = (unsigned)strlen(temp); while (len < 8) { len++; s.Add_Space(); } s += temp; } s += ":"; UInt32 d[4] = { 0 }; MyCPUID(j, &d[0], &d[1], &d[2], &d[3]); for (unsigned i = 0; i < 4; i++) { char temp[32]; ConvertUInt32ToHex8Digits(d[i], temp); s.Add_Space(); s += temp; } } } */ #endif #ifdef _WIN32 static const char * const k_PROCESSOR_ARCHITECTURE[] = { "x86" // "INTEL" , "MIPS" , "ALPHA" , "PPC" , "SHX" , "ARM" , "IA64" , "ALPHA64" , "MSIL" , "x64" // "AMD64" , "IA32_ON_WIN64" , "NEUTRAL" , "ARM64" , "ARM32_ON_WIN64" }; #define Z7_WIN_PROCESSOR_ARCHITECTURE_INTEL 0 #define Z7_WIN_PROCESSOR_ARCHITECTURE_AMD64 9 #define Z7_WIN_PROCESSOR_INTEL_PENTIUM 586 #define Z7_WIN_PROCESSOR_AMD_X8664 8664 /* static const CUInt32PCharPair k_PROCESSOR[] = { { 2200, "IA64" }, { 8664, "x64" } }; #define PROCESSOR_INTEL_386 386 #define PROCESSOR_INTEL_486 486 #define PROCESSOR_INTEL_PENTIUM 586 #define PROCESSOR_INTEL_860 860 #define PROCESSOR_INTEL_IA64 2200 #define PROCESSOR_AMD_X8664 8664 #define PROCESSOR_MIPS_R2000 2000 #define PROCESSOR_MIPS_R3000 3000 #define PROCESSOR_MIPS_R4000 4000 #define PROCESSOR_ALPHA_21064 21064 #define PROCESSOR_PPC_601 601 #define PROCESSOR_PPC_603 603 #define PROCESSOR_PPC_604 604 #define PROCESSOR_PPC_620 620 #define PROCESSOR_HITACHI_SH3 10003 #define PROCESSOR_HITACHI_SH3E 10004 #define PROCESSOR_HITACHI_SH4 10005 #define PROCESSOR_MOTOROLA_821 821 #define PROCESSOR_SHx_SH3 103 #define PROCESSOR_SHx_SH4 104 #define PROCESSOR_STRONGARM 2577 // 0xA11 #define PROCESSOR_ARM720 1824 // 0x720 #define PROCESSOR_ARM820 2080 // 0x820 #define PROCESSOR_ARM920 2336 // 0x920 #define PROCESSOR_ARM_7TDMI 70001 #define PROCESSOR_OPTIL 18767 // 0x494f */ /* static const char * const k_PF[] = { "FP_ERRATA" , "FP_EMU" , "CMPXCHG" , "MMX" , "PPC_MOVEMEM_64BIT" , "ALPHA_BYTE" , "SSE" , "3DNOW" , "RDTSC" , "PAE" , "SSE2" , "SSE_DAZ" , "NX" , "SSE3" , "CMPXCHG16B" , "CMP8XCHG16" , "CHANNELS" , "XSAVE" , "ARM_VFP_32" , "ARM_NEON" , "L2AT" , "VIRT_FIRMWARE" , "RDWRFSGSBASE" , "FASTFAIL" , "ARM_DIVIDE" , "ARM_64BIT_LOADSTORE_ATOMIC" , "ARM_EXTERNAL_CACHE" , "ARM_FMAC" , "RDRAND" , "ARM_V8" , "ARM_V8_CRYPTO" , "ARM_V8_CRC32" , "RDTSCP" , "RDPID" , "ARM_V81_ATOMIC" , "MONITORX" }; */ #endif static void PrintPage(AString &s, UInt64 v) { const char *t = "B"; if ((v & 0x3ff) == 0) { v >>= 10; t = "KB"; } s.Add_UInt64(v); s += t; } #ifdef _WIN32 static AString TypeToString2(const char * const table[], unsigned num, UInt32 value) { char sz[16]; const char *p = NULL; if (value < num) p = table[value]; if (!p) { ConvertUInt32ToString(value, sz); p = sz; } return (AString)p; } // #if defined(Z7_LARGE_PAGES) || defined(_WIN32) // #ifdef _WIN32 void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v) { char c = 0; if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; if ((v & 0x3FF) == 0) { v >>= 10; c = 'M'; if ((v & 0x3FF) == 0) { v >>= 10; c = 'G'; if ((v & 0x3FF) == 0) { v >>= 10; c = 'T'; }}}} else { // s += "0x"; PrintHex(s, v); return; } s.Add_UInt64(v); if (c) s.Add_Char(c); s.Add_Char('B'); } // #endif // #endif static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si) { s += TypeToString2(k_PROCESSOR_ARCHITECTURE, Z7_ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture); if (!( (si.wProcessorArchitecture == Z7_WIN_PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == Z7_WIN_PROCESSOR_INTEL_PENTIUM) || (si.wProcessorArchitecture == Z7_WIN_PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == Z7_WIN_PROCESSOR_AMD_X8664))) { s.Add_Space(); // s += TypePairToString(k_PROCESSOR, Z7_ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType); s.Add_UInt32(si.dwProcessorType); } s.Add_Space(); PrintHex(s, si.wProcessorLevel); s.Add_Dot(); PrintHex(s, si.wProcessorRevision); if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors)) if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8) { s += " act:"; PrintHex(s, si.dwActiveProcessorMask); } s += " threads:"; s.Add_UInt32(si.dwNumberOfProcessors); if (si.dwPageSize != 1 << 12) { s += " page:"; PrintPage(s, si.dwPageSize); } if (si.dwAllocationGranularity != 1 << 16) { s += " gran:"; PrintPage(s, si.dwAllocationGranularity); } s.Add_Space(); const DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress; UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1; const UInt32 kReserveSize = ((UInt32)1 << 16); if (minAdd != kReserveSize) { PrintSize_KMGT_Or_Hex(s, minAdd); s.Add_Minus(); } else { if ((maxSize & (kReserveSize - 1)) == 0) maxSize += kReserveSize; } PrintSize_KMGT_Or_Hex(s, maxSize); } #ifndef _WIN64 EXTERN_C_BEGIN typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); EXTERN_C_END #endif #endif #ifdef __APPLE__ #ifndef MY_CPU_X86_OR_AMD64 static void Add_sysctlbyname_to_String(const char *name, AString &s) { size_t bufSize = 256; char buf[256]; if (z7_sysctlbyname_Get(name, &buf, &bufSize) == 0) s += buf; } #endif #endif void GetSysInfo(AString &s1, AString &s2); void GetSysInfo(AString &s1, AString &s2) { s1.Empty(); s2.Empty(); #ifdef _WIN32 SYSTEM_INFO si; GetSystemInfo(&si); { SysInfo_To_String(s1, si); // s += " : "; } #if !defined(_WIN64) && !defined(UNDER_CE) const Func_GetNativeSystemInfo fn = Z7_GET_PROC_ADDRESS( Func_GetNativeSystemInfo, GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); if (fn) { SYSTEM_INFO si2; fn(&si2); // if (memcmp(&si, &si2, sizeof(si)) != 0) { // s += " - "; SysInfo_To_String(s2, si2); } } #endif #endif } static void AddBracedString(AString &dest, AString &src) { if (!src.IsEmpty()) { dest.Add_Space_if_NotEmpty(); dest.Add_Char('('); dest += src; dest.Add_Char(')'); } } struct CCpuName { AString CpuName; AString Revision; AString Microcode; AString LargePages; void Fill(); void Get_Revision_Microcode_LargePages(AString &s) { s.Empty(); AddBracedString(s, Revision); AddBracedString(s, Microcode); s.Add_OptSpaced(LargePages); } }; void CCpuName::Fill() { CpuName.Empty(); Revision.Empty(); Microcode.Empty(); LargePages.Empty(); AString &s = CpuName; #ifdef MY_CPU_X86_OR_AMD64 { #if !defined(MY_CPU_AMD64) if (z7_x86_cpuid_GetMaxFunc()) #endif { x86cpuid_to_String(s); { UInt32 a[4]; z7_x86_cpuid(a, 1); char temp[16]; ConvertUInt32ToHex(a[0], temp); Revision += temp; } } } #elif defined(__APPLE__) { Add_sysctlbyname_to_String("machdep.cpu.brand_string", s); } #elif defined(MY_CPU_E2K) && defined(Z7_MCST_LCC_VERSION) && (Z7_MCST_LCC_VERSION >= 12323) { s += "mcst "; s += __builtin_cpu_name(); s.Add_Space(); s += __builtin_cpu_arch(); } #endif #ifdef _WIN32 { NRegistry::CKey key; if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS) { // s.Empty(); // for debug { CSysString name; if (s.IsEmpty()) if (key.QueryValue(TEXT("ProcessorNameString"), name) == ERROR_SUCCESS) { s += GetAnsiString(name); } if (key.QueryValue(TEXT("Identifier"), name) == ERROR_SUCCESS) { if (!Revision.IsEmpty()) Revision += " : "; Revision += GetAnsiString(name); } } LONG res[2]; CByteBuffer bufs[2]; { for (unsigned i = 0; i < 2; i++) { UInt32 size = 0; res[i] = key.QueryValue(i == 0 ? TEXT("Previous Update Revision") : TEXT("Update Revision"), bufs[i], size); if (res[i] == ERROR_SUCCESS) if (size != bufs[i].Size()) res[i] = ERROR_SUCCESS + 1; } } if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) { for (unsigned i = 0; i < 2; i++) { if (i == 1) Microcode += "->"; if (res[i] != ERROR_SUCCESS) continue; const CByteBuffer &buf = bufs[i]; if (buf.Size() == 8) { const UInt32 high = GetUi32(buf); if (high != 0) { PrintHex(Microcode, high); Microcode.Add_Dot(); } PrintHex(Microcode, GetUi32(buf + 4)); } } } } } #endif if (s.IsEmpty()) { #ifdef MY_CPU_NAME s += MY_CPU_NAME; #endif } #ifdef __APPLE__ { AString s2; UInt32 v = 0; if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0) { s2.Add_UInt32(v); s2.Add_Char('C'); } if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0) { s2.Add_UInt32(v); s2.Add_Char('T'); } if (!s2.IsEmpty()) { s.Add_Space_if_NotEmpty(); s += s2; } } #endif #ifdef Z7_LARGE_PAGES Add_LargePages_String(LargePages); #endif } void AddCpuFeatures(AString &s); void AddCpuFeatures(AString &s) { #ifdef _WIN32 // const unsigned kNumFeatures_Extra = 32; // we check also for unknown features // const unsigned kNumFeatures = Z7_ARRAY_SIZE(k_PF) + kNumFeatures_Extra; const unsigned kNumFeatures = 64; UInt64 flags = 0; for (unsigned i = 0; i < kNumFeatures; i++) { if (IsProcessorFeaturePresent((DWORD)i)) { flags += (UInt64)1 << i; // s.Add_Space_if_NotEmpty(); // s += TypeToString2(k_PF, Z7_ARRAY_SIZE(k_PF), i); } } s.Add_OptSpaced("f:"); PrintHex(s, flags); #elif defined(__APPLE__) { UInt32 v = 0; if (z7_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0) { s.Add_OptSpaced("PageSize:"); PrintPage(s, v); } } #else const long v = sysconf(_SC_PAGESIZE); if (v != -1) { s.Add_OptSpaced("PageSize:"); PrintPage(s, (unsigned long)v); } #if !defined(_AIX) #ifdef __linux__ CByteBuffer buf; if (ReadFile_to_Buffer("/sys/kernel/mm/transparent_hugepage/enabled", buf)) // if (ReadFile_to_Buffer("/proc/cpuinfo", buf)) { s.Add_OptSpaced("THP:"); AString s2; s2.SetFrom_CalcLen((const char *)(const void *)(const Byte *)buf, (unsigned)buf.Size()); const int pos = s2.Find('['); if (pos >= 0) { const int pos2 = s2.Find(']', (unsigned)pos + 1); if (pos2 >= 0) { s2.DeleteFrom((unsigned)pos2); s2.DeleteFrontal((unsigned)pos + 1); } } s += s2; } // else throw CSystemException(MY_SRes_HRESULT_FROM_WRes(errno)); #endif #ifdef AT_HWCAP s.Add_OptSpaced("hwcap:"); { unsigned long h = MY_getauxval(AT_HWCAP); PrintHex(s, h); #ifdef MY_CPU_ARM64 if (h & HWCAP_CRC32) s += ":CRC32"; if (h & HWCAP_SHA1) s += ":SHA1"; if (h & HWCAP_SHA2) s += ":SHA2"; if (h & HWCAP_AES) s += ":AES"; if (h & HWCAP_ASIMD) s += ":ASIMD"; #elif defined(MY_CPU_ARM) if (h & HWCAP_NEON) s += ":NEON"; #endif } #endif // AT_HWCAP #ifdef AT_HWCAP2 { unsigned long h = MY_getauxval(AT_HWCAP2); #ifndef MY_CPU_ARM if (h != 0) #endif { s += " hwcap2:"; PrintHex(s, h); #ifdef MY_CPU_ARM if (h & HWCAP2_CRC32) s += ":CRC32"; if (h & HWCAP2_SHA1) s += ":SHA1"; if (h & HWCAP2_SHA2) s += ":SHA2"; if (h & HWCAP2_AES) s += ":AES"; #endif } } #endif // AT_HWCAP2 #endif // _AIX #endif // _WIN32 } #ifdef _WIN32 #ifndef UNDER_CE Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION EXTERN_C_BEGIN typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); EXTERN_C_END static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi) { const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); if (!ntdll) return FALSE; const Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS( Func_RtlGetVersion, ntdll, "RtlGetVersion"); if (!func) return FALSE; func(vi); return TRUE; } #endif #endif void GetOsInfoText(AString &sRes) { sRes.Empty(); AString s; #ifdef _WIN32 #ifndef UNDER_CE // OSVERSIONINFO vi; OSVERSIONINFOEXW vi; vi.dwOSVersionInfoSize = sizeof(vi); // if (::GetVersionEx(&vi)) if (My_RtlGetVersion(&vi)) { s += "Windows"; if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) s.Add_UInt32(vi.dwPlatformId); s.Add_Space(); s.Add_UInt32(vi.dwMajorVersion); s.Add_Dot(); s.Add_UInt32(vi.dwMinorVersion); s.Add_Space(); s.Add_UInt32(vi.dwBuildNumber); if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0) { s += " SP:"; s.Add_UInt32(vi.wServicePackMajor); s.Add_Dot(); s.Add_UInt32(vi.wServicePackMinor); } // s += " Suite:"; PrintHex(s, vi.wSuiteMask); // s += " Type:"; s.Add_UInt32(vi.wProductType); // s.Add_Space(); s += GetOemString(vi.szCSDVersion); } /* { s += " OEMCP:"; s.Add_UInt32(GetOEMCP()); s += " ACP:"; s.Add_UInt32(GetACP()); } */ #endif #else // _WIN32 if (!s.IsEmpty()) s.Add_LF(); struct utsname un; if (uname(&un) == 0) { s += un.sysname; // s += " : "; s += un.nodename; // we don't want to show name of computer s += " : "; s += un.release; s += " : "; s += un.version; s += " : "; s += un.machine; #ifdef __APPLE__ // Add_sysctlbyname_to_String("kern.version", s); // it's same as "utsname.version" #endif } #endif // _WIN32 sRes += s; #ifdef MY_CPU_X86_OR_AMD64 { AString s2; GetVirtCpuid(s2); if (!s2.IsEmpty()) { sRes += " : "; sRes += s2; } } #endif } void GetSystemInfoText(AString &sRes) { GetOsInfoText(sRes); sRes.Add_LF(); { AString s, s1, s2; GetSysInfo(s1, s2); if (!s1.IsEmpty() || !s2.IsEmpty()) { s = s1; if (s1 != s2 && !s2.IsEmpty()) { s += " - "; s += s2; } } { AddCpuFeatures(s); if (!s.IsEmpty()) { sRes += s; sRes.Add_LF(); } } } { AString s; GetCpuName_MultiLine(s); if (!s.IsEmpty()) { sRes += s; sRes.Add_LF(); } } /* #ifdef MY_CPU_X86_OR_AMD64 { AString s; x86cpuid_all_to_String(s); if (!s.IsEmpty()) { printCallback->Print(s); printCallback->NewLine(); } } #endif */ } void GetCpuName_MultiLine(AString &s); void GetCpuName_MultiLine(AString &s) { CCpuName cpuName; cpuName.Fill(); s = cpuName.CpuName; AString s2; cpuName.Get_Revision_Microcode_LargePages(s2); if (!s2.IsEmpty()) { s.Add_LF(); s += s2; } } #ifdef MY_CPU_X86_OR_AMD64 void GetVirtCpuid(AString &s) { const UInt32 kHv = 0x40000000; Z7_IF_X86_CPUID_SUPPORTED { UInt32 a[4]; z7_x86_cpuid(a, kHv); if (a[0] < kHv || a[0] >= kHv + (1 << 16)) return; { { for (unsigned j = 1; j < 4; j++) PrintCpuChars(s, a[j]); } } if (a[0] >= kHv + 1) { UInt32 d[4]; z7_x86_cpuid(d, kHv + 1); s += " : "; PrintCpuChars(s, d[0]); if (a[0] >= kHv + 2) { z7_x86_cpuid(d, kHv + 2); s += " : "; s.Add_UInt32(d[1] >> 16); s.Add_Dot(); s.Add_UInt32(d[1] & 0xffff); s.Add_Dot(); s.Add_UInt32(d[0]); s.Add_Dot(); s.Add_UInt32(d[2]); s.Add_Dot(); s.Add_UInt32(d[3] >> 24); s.Add_Dot(); s.Add_UInt32(d[3] & 0xffffff); } /* if (a[0] >= kHv + 5) { z7_x86_cpuid(d, kHv + 5); s += " : "; s.Add_UInt32(d[0]); s += "p"; s.Add_UInt32(d[1]); s += "t"; } */ } } } #endif void GetCompiler(AString &s) { #ifdef __clang__ s += " CLANG "; s.Add_UInt32(__clang_major__); s.Add_Dot(); s.Add_UInt32(__clang_minor__); s.Add_Dot(); s.Add_UInt32(__clang_patchlevel__); #endif #ifdef __xlC__ s += " XLC "; s.Add_UInt32(__xlC__ >> 8); s.Add_Dot(); s.Add_UInt32(__xlC__ & 0xFF); #ifdef __xlC_ver__ s.Add_Dot(); s.Add_UInt32(__xlC_ver__ >> 8); s.Add_Dot(); s.Add_UInt32(__xlC_ver__ & 0xFF); #endif #endif // #define __LCC__ 126 // #define __LCC_MINOR__ 20 // #define __MCST__ 1 #ifdef __MCST__ s += " MCST"; #endif #ifdef __LCC__ s += " LCC "; s.Add_UInt32(__LCC__ / 100); s.Add_Dot(); s.Add_UInt32(__LCC__ % 100 / 10); s.Add_UInt32(__LCC__ % 10); #ifdef __LCC_MINOR__ s.Add_Dot(); s.Add_UInt32(__LCC_MINOR__ / 10); s.Add_UInt32(__LCC_MINOR__ % 10); #endif #endif // #define __EDG_VERSION__ 602 #ifdef __EDG_VERSION__ s += " EDG "; s.Add_UInt32(__EDG_VERSION__ / 100); s.Add_Dot(); s.Add_UInt32(__EDG_VERSION__ % 100 / 10); s.Add_UInt32(__EDG_VERSION__ % 10); #endif #ifdef __VERSION__ s.Add_Space(); s += "ver:"; s += __VERSION__; #endif #ifdef __GNUC__ s += " GCC "; s.Add_UInt32(__GNUC__); s.Add_Dot(); s.Add_UInt32(__GNUC_MINOR__); s.Add_Dot(); s.Add_UInt32(__GNUC_PATCHLEVEL__); #endif #ifdef _MSC_VER s += " MSC "; s.Add_UInt32(_MSC_VER); #ifdef _MSC_FULL_VER s.Add_Dot(); s.Add_UInt32(_MSC_FULL_VER); #endif #endif #if defined(__AVX512F__) #if defined(__AVX512VL__) #define MY_CPU_COMPILE_ISA "AVX512VL" #else #define MY_CPU_COMPILE_ISA "AVX512F" #endif #elif defined(__AVX2__) #define MY_CPU_COMPILE_ISA "AVX2" #elif defined(__AVX__) #define MY_CPU_COMPILE_ISA "AVX" #elif defined(__SSE2__) #define MY_CPU_COMPILE_ISA "SSE2" #elif defined(_M_IX86_FP) && (_M_IX86_FP >= 2) #define MY_CPU_COMPILE_ISA "SSE2" #elif defined(__SSE__) #define MY_CPU_COMPILE_ISA "SSE" #elif defined(_M_IX86_FP) && (_M_IX86_FP >= 1) #define MY_CPU_COMPILE_ISA "SSE" #elif defined(__i686__) #define MY_CPU_COMPILE_ISA "i686" #elif defined(__i586__) #define MY_CPU_COMPILE_ISA "i586" #elif defined(__i486__) #define MY_CPU_COMPILE_ISA "i486" #elif defined(__i386__) #define MY_CPU_COMPILE_ISA "i386" #elif defined(_M_IX86_FP) #define MY_CPU_COMPILE_ISA "IA32" #endif AString s2; #ifdef MY_CPU_COMPILE_ISA s2.Add_OptSpaced(MY_CPU_COMPILE_ISA); #endif #ifndef MY_CPU_ARM64 #ifdef __ARM_FP s2.Add_OptSpaced("FP"); #endif #ifdef __ARM_NEON s2.Add_OptSpaced("NEON"); #endif #ifdef __NEON__ s2.Add_OptSpaced("__NEON__"); #endif #ifdef __ARM_FEATURE_SIMD32 s2.Add_OptSpaced("SIMD32"); #endif #endif #ifdef __ARM_FEATURE_CRYPTO s2.Add_OptSpaced("CRYPTO"); #endif #ifdef __ARM_FEATURE_SHA2 s2.Add_OptSpaced("SHA2"); #endif #ifdef __ARM_FEATURE_AES s2.Add_OptSpaced("AES"); #endif #ifdef __ARM_FEATURE_CRC32 s2.Add_OptSpaced("CRC32"); #endif #ifdef __ARM_FEATURE_UNALIGNED s2.Add_OptSpaced("UNALIGNED"); #endif #ifdef MY_CPU_BE s2.Add_OptSpaced("BE"); #endif #if defined(MY_CPU_LE_UNALIGN) \ && !defined(MY_CPU_X86_OR_AMD64) \ && !defined(MY_CPU_ARM64) s2.Add_OptSpaced("LE-unaligned"); #endif if (!s2.IsEmpty()) { s.Add_OptSpaced(": "); s += s2; } } tmp41wklro_/CPP/Windows/SystemInfo.h0000444000175000001440000000065414357314620020500 0ustar nabijaczleweliusers// Windows/SystemInfo.h #ifndef ZIP7_INC_WINDOWS_SYSTEM_INFO_H #define ZIP7_INC_WINDOWS_SYSTEM_INFO_H #include "../Common/MyString.h" void GetCpuName_MultiLine(AString &s); void GetOsInfoText(AString &sRes); void GetSystemInfoText(AString &s); void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v); void Add_LargePages_String(AString &s); void GetCompiler(AString &s); void GetVirtCpuid(AString &s); #endif tmp41wklro_/CPP/Windows/Thread.h0000444000175000001440000000305414400604220017567 0ustar nabijaczleweliusers// Windows/Thread.h #ifndef ZIP7_INC_WINDOWS_THREAD_H #define ZIP7_INC_WINDOWS_THREAD_H #include "../../C/Threads.h" #include "Defs.h" namespace NWindows { class CThread MY_UNCOPYABLE { ::CThread thread; public: CThread() { Thread_CONSTRUCT(&thread) } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } // WRes Wait() { return Thread_Wait(&thread); } WRes Wait_Close() { return Thread_Wait_Close(&thread); } WRes Create(THREAD_FUNC_TYPE startAddress, LPVOID param) { return Thread_Create(&thread, startAddress, param); } WRes Create_With_Affinity(THREAD_FUNC_TYPE startAddress, LPVOID param, CAffinityMask affinity) { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); } WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet) { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); } #ifdef _WIN32 operator HANDLE() { return thread; } void Attach(HANDLE handle) { thread = handle; } HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread); } DWORD Suspend() { return ::SuspendThread(thread); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } #endif }; } #endif tmp41wklro_/CPP/Windows/TimeUtils.cpp0000444000175000001440000002774014606444620020660 0ustar nabijaczleweliusers// Windows/TimeUtils.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #endif #include "Defs.h" #include "TimeUtils.h" namespace NWindows { namespace NTime { static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const unsigned kFileTimeStartYear = 1601; #if !defined(_WIN32) || defined(UNDER_CE) static const unsigned kDosTimeStartYear = 1980; #endif static const unsigned kUnixTimeStartYear = 1970; static const UInt64 kUnixTimeOffset = (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear)); static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() { #if defined(_WIN32) && !defined(UNDER_CE) return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); #else ft.dwLowDateTime = 0; ft.dwHighDateTime = 0; UInt64 res; if (!GetSecondsSince1601( kDosTimeStartYear + (unsigned)(dosTime >> 25), (unsigned)((dosTime >> 21) & 0xF), (unsigned)((dosTime >> 16) & 0x1F), (unsigned)((dosTime >> 11) & 0x1F), (unsigned)((dosTime >> 5) & 0x3F), (unsigned)((dosTime & 0x1F)) * 2, res)) return false; res *= kNumTimeQuantumsInSecond; ft.dwLowDateTime = (UInt32)res; ft.dwHighDateTime = (UInt32)(res >> 32); return true; #endif } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw() { #if defined(_WIN32) && !defined(UNDER_CE) WORD datePart, timePart; if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) { dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; #else #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 += (kNumTimeQuantumsInSecond * 2 - 1); v64 /= kNumTimeQuantumsInSecond; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = kFileTimeStartYear + (unsigned)(v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; dosTime = kLowDosTime; if (year < kDosTimeStartYear) return false; year -= kDosTimeStartYear; dosTime = kHighDosTime; if (year >= 128) return false; dosTime = ((UInt32)year << 25) | ((UInt32)mon << 21) | ((UInt32)day << 16) | ((UInt32)hour << 11) | ((UInt32)min << 5) | ((UInt32)sec >> 1); #endif return true; } bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw() { FILETIME loc = { 0, 0 }; const UInt64 u1 = FILETIME_To_UInt64(utc); const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec. if (u1 >= kDelta) { if (!FileTimeToLocalFileTime(&utc, &loc)) loc = utc; else { const UInt64 u2 = FILETIME_To_UInt64(loc); const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2); if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time loc = utc; } } return FileTime_To_DosTime(loc, dosTime); } UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw() { return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; } void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw() { const UInt64 v = UnixTime_To_FileTime64(unixTime); ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw() { return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; } bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw() { if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) { fileTime = (UInt64)(Int64)-1; return false; } if (unixTime < -(Int64)kUnixTimeOffset) { fileTime = 0; return false; } fileTime = UnixTime64_To_FileTime64(unixTime); return true; } bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw() { UInt64 v; const bool res = UnixTime64_To_FileTime64(unixTime, v); ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); return res; } Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw() { const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; } Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw() { const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond); return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; } bool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw() { UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; winTime /= kNumTimeQuantumsInSecond; if (winTime < kUnixTimeOffset) { unixTime = 0; return false; } winTime -= kUnixTimeOffset; if (winTime > (UInt32)0xFFFFFFFF) { unixTime = (UInt32)0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw() { resSeconds = 0; if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; const unsigned numYears = year - kFileTimeStartYear; UInt32 numDays = (UInt32)((UInt32)numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += (UInt32)(day - 1); resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } /* docs: TIME_UTC is not defined on many platforms: glibc 2.15, macOS 10.13 FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin 2.9, mingw, MSVC 14, Android 9.0. */ #if defined(TIME_UTC) #define ZIP7_USE_timespec_get // #pragma message("ZIP7_USE_timespec_get") #elif defined(CLOCK_REALTIME) #define ZIP7_USE_clock_gettime // #pragma message("ZIP7_USE_clock_gettime") #endif void GetCurUtc_FiTime(CFiTime &ft) throw() { #ifdef _WIN32 // Both variants provide same low resolution on WinXP: about 15 ms. // But GetSystemTimeAsFileTime is much faster. #ifdef UNDER_CE SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); #else GetSystemTimeAsFileTime(&ft); #endif #else FiTime_Clear(ft); #ifdef ZIP7_USE_timespec_get timespec_get(&ft, TIME_UTC); #elif defined ZIP7_USE_clock_gettime #if defined(_AIX) { timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ft.tv_sec = ts.tv_sec; ft.tv_nsec = ts.tv_nsec; } #else clock_gettime(CLOCK_REALTIME, &ft); #endif #else struct timeval now; if (gettimeofday(&now, NULL) == 0) { ft.tv_sec = now.tv_sec; // timeval::tv_usec can be 64-bit signed in some cases // timespec::tv_nsec can be 32-bit signed in some cases ft.tv_nsec = (Int32) // to eliminate compiler conversion error (now.tv_usec * 1000); } #endif #endif } #ifndef _WIN32 void GetCurUtcFileTime(FILETIME &ft) throw() { UInt64 v = 0; #if defined(ZIP7_USE_timespec_get) || \ defined(ZIP7_USE_clock_gettime) timespec ts; #if defined(ZIP7_USE_timespec_get) if (timespec_get(&ts, TIME_UTC)) #else if (clock_gettime(CLOCK_REALTIME, &ts) == 0) #endif { v = ((UInt64)ts.tv_sec + kUnixTimeOffset) * kNumTimeQuantumsInSecond + (UInt64)ts.tv_nsec / 100; } #else struct timeval now; if (gettimeofday(&now, NULL) == 0) { v = ((UInt64)now.tv_sec + kUnixTimeOffset) * kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; } #endif ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } #endif }} #ifdef _WIN32 /* void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) { if (prec == k_PropVar_TimePrec_0 || prec == k_PropVar_TimePrec_HighPrec || prec >= k_PropVar_TimePrec_100ns) return; UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; UInt32 d; if (prec == k_PropVar_TimePrec_DOS) { // we round up as windows DosDateTimeToFileTime() v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1; d = NWindows::NTime::kNumTimeQuantumsInSecond * 2; } else { if (prec == k_PropVar_TimePrec_Unix) numDigits = 0; else if (numDigits < 0) return; d = 1; for (unsigned k = numDigits; k < 7; k++) d *= 10; } v /= d; v *= d; ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } */ #else /* void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) { if (prec >= k_PropVar_TimePrec_1ns || prec == k_PropVar_TimePrec_HighPrec) return; int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; UInt32 d; if (prec == k_PropVar_TimePrec_Unix || prec == (int)k_PropVar_TimePrec_Base) { ft.tv_nsec = 0; return; } if (prec == k_PropVar_TimePrec_DOS) { // we round up as windows DosDateTimeToFileTime() const unsigned sec1 = (ft.tv_sec & 1); if (ft.tv_nsec == 0 && sec1 == 0) return; ft.tv_nsec = 0; ft.tv_sec += 2 - sec1; return; } { if (prec == k_PropVar_TimePrec_0 || numDigits < 0) numDigits = 7; d = 1; for (unsigned k = numDigits; k < 9; k++) d *= 10; ft.tv_nsec /= d; ft.tv_nsec *= d; } } */ int Compare_FiTime(const CFiTime *a1, const CFiTime *a2) { if (a1->tv_sec < a2->tv_sec) return -1; if (a1->tv_sec > a2->tv_sec) return 1; if (a1->tv_nsec < a2->tv_nsec) return -1; if (a1->tv_nsec > a2->tv_nsec) return 1; return 0; } bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts) { UInt32 quantums; const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); // time_t is long const time_t sec2 = (time_t)sec; if (sec2 == sec) { ts.tv_sec = sec2; ts.tv_nsec = (Int32)(quantums * 100); return true; } return false; } void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100) { const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); ns100 = (unsigned)((UInt64)ts.tv_nsec % 100); ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft) { const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } #endif tmp41wklro_/CPP/Windows/TimeUtils.h0000444000175000001440000001020114357314620020304 0ustar nabijaczleweliusers// Windows/TimeUtils.h #ifndef ZIP7_INC_WINDOWS_TIME_UTILS_H #define ZIP7_INC_WINDOWS_TIME_UTILS_H #include "../Common/MyTypes.h" #include "../Common/MyWindows.h" #include "PropVariant.h" inline UInt64 FILETIME_To_UInt64(const FILETIME &ft) { return (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; } inline void FILETIME_Clear(FILETIME &ft) { ft.dwLowDateTime = 0; ft.dwHighDateTime = 0; } inline bool FILETIME_IsZero(const FILETIME &ft) { return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0); } #ifdef _WIN32 #define CFiTime FILETIME #define Compare_FiTime ::CompareFileTime inline void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft) { ft = ts; } /* inline void FILETIME_To_FiTime(const FILETIME &ft, CFiTime &ts) { ts = ft; } */ inline void FiTime_Clear(CFiTime &ft) { ft.dwLowDateTime = 0; ft.dwHighDateTime = 0; } #else #include #if defined(_AIX) #define CFiTime st_timespec #else #define CFiTime timespec #endif int Compare_FiTime(const CFiTime *a1, const CFiTime *a2); bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts); void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft); void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100); inline void FiTime_Clear(CFiTime &ft) { ft.tv_sec = 0; ft.tv_nsec = 0; } #ifdef __APPLE__ #define ST_MTIME(st) st.st_mtimespec #define ST_ATIME(st) st.st_atimespec #define ST_CTIME(st) st.st_ctimespec #else #define ST_MTIME(st) st.st_mtim #define ST_ATIME(st) st.st_atim #define ST_CTIME(st) st.st_ctim #endif #endif // void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec); namespace NWindows { namespace NTime { bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &fileTime) throw(); bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw(); bool FileTime_To_DosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); // UInt32 Unix Time : for dates 1970-2106 UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw(); void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &fileTime) throw(); // Int64 Unix Time : negative values for dates before 1970 UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw(); // no check bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw(); bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &fileTime) throw(); Int64 FileTime64_To_UnixTime64(UInt64 ft64) throw(); bool FileTime_To_UnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw(); Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw(); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); void GetCurUtc_FiTime(CFiTime &ft) throw(); #ifdef _WIN32 #define GetCurUtcFileTime GetCurUtc_FiTime #else void GetCurUtcFileTime(FILETIME &ft) throw(); #endif }} inline void PropVariant_SetFrom_UnixTime(NWindows::NCOM::CPropVariant &prop, UInt32 unixTime) { FILETIME ft; NWindows::NTime::UnixTime_To_FileTime(unixTime, ft); prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix); } inline void PropVariant_SetFrom_NtfsTime(NWindows::NCOM::CPropVariant &prop, const FILETIME &ft) { prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_100ns); } inline void PropVariant_SetFrom_FiTime(NWindows::NCOM::CPropVariant &prop, const CFiTime &fts) { #ifdef _WIN32 PropVariant_SetFrom_NtfsTime(prop, fts); #else unsigned ns100; FILETIME ft; FiTime_To_FILETIME_ns100(fts, ft, ns100); prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100); #endif } inline bool PropVariant_SetFrom_DosTime(NWindows::NCOM::CPropVariant &prop, UInt32 dosTime) { FILETIME localFileTime, utc; if (!NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime)) return false; if (!LocalFileTimeToFileTime(&localFileTime, &utc)) return false; prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_DOS); return true; } #endif tmp41wklro_/CPP/Windows/Window.cpp0000444000175000001440000001111514354236600020172 0ustar nabijaczleweliusers// Windows/Window.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #include "Window.h" #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { #ifndef _UNICODE ATOM MyRegisterClass(CONST WNDCLASSW *wndClass) { if (g_IsNT) return RegisterClassW(wndClass); WNDCLASSA wndClassA; wndClassA.style = wndClass->style; wndClassA.lpfnWndProc = wndClass->lpfnWndProc; wndClassA.cbClsExtra = wndClass->cbClsExtra; wndClassA.cbWndExtra = wndClass->cbWndExtra; wndClassA.hInstance = wndClass->hInstance; wndClassA.hIcon = wndClass->hIcon; wndClassA.hCursor = wndClass->hCursor; wndClassA.hbrBackground = wndClass->hbrBackground; AString menuName; AString className; if (IS_INTRESOURCE(wndClass->lpszMenuName)) wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName; else { menuName = GetSystemString(wndClass->lpszMenuName); wndClassA.lpszMenuName = menuName; } if (IS_INTRESOURCE(wndClass->lpszClassName)) wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName; else { className = GetSystemString(wndClass->lpszClassName); wndClassA.lpszClassName = className; } return RegisterClassA(&wndClassA); } bool CWindow::Create(LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam) { if (g_IsNT) { _window = ::CreateWindowW(className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); return (_window != NULL); } return Create(GetSystemString(className), GetSystemString(windowName), style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); } bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam) { if (g_IsNT) { _window = ::CreateWindowExW(exStyle, className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); return (_window != NULL); } AString classNameA; LPCSTR classNameP; if (IS_INTRESOURCE(className)) classNameP = (LPCSTR)className; else { classNameA = GetSystemString(className); classNameP = classNameA; } AString windowNameA; LPCSTR windowNameP; if (IS_INTRESOURCE(windowName)) windowNameP = (LPCSTR)windowName; else { windowNameA = GetSystemString(windowName); windowNameP = windowNameA; } return CreateEx(exStyle, classNameP, windowNameP, style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); } #endif #ifndef _UNICODE bool MySetWindowText(HWND wnd, LPCWSTR s) { if (g_IsNT) return BOOLToBool(::SetWindowTextW(wnd, s)); return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s))); } #endif bool CWindow::GetText(CSysString &s) const { s.Empty(); unsigned len = (unsigned)GetTextLength(); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); TCHAR *p = s.GetBuf(len); { const unsigned len2 = (unsigned)GetText(p, (int)(len + 1)); if (len > len2) len = len2; } s.ReleaseBuf_CalcLen(len); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); return true; } #ifndef _UNICODE bool CWindow::GetText(UString &s) const { if (g_IsNT) { s.Empty(); unsigned len = (unsigned)GetWindowTextLengthW(_window); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); wchar_t *p = s.GetBuf(len); { const unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1)); if (len > len2) len = len2; } s.ReleaseBuf_CalcLen(len); if (len == 0) return (::GetLastError() == ERROR_SUCCESS); return true; } CSysString sysString; const bool result = GetText(sysString); MultiByteToUnicodeString2(s, sysString); return result; } #endif /* bool CWindow::ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags) { DWORD style = GetWindowLong(styleOffset); DWORD newStyle = (style & ~remove) | add; if (style == newStyle) return false; // it is not good SetWindowLong(styleOffset, newStyle); if (flags != 0) { ::SetWindowPos(_window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags); } return TRUE; } */ } tmp41wklro_/CPP/Windows/Window.h0000444000175000001440000002732714406316100017643 0ustar nabijaczleweliusers// Windows/Window.h #ifndef ZIP7_INC_WINDOWS_WINDOW_H #define ZIP7_INC_WINDOWS_WINDOW_H #include "../Common/MyWindows.h" #include "../Common/MyString.h" #include "Defs.h" #ifndef UNDER_CE #ifdef WM_CHANGEUISTATE #define Z7_WIN_WM_CHANGEUISTATE WM_CHANGEUISTATE #define Z7_WIN_WM_UPDATEUISTATE WM_UPDATEUISTATE #define Z7_WIN_WM_QUERYUISTATE WM_QUERYUISTATE #else // these are defined for (_WIN32_WINNT >= 0x0500): #define Z7_WIN_WM_CHANGEUISTATE 0x0127 #define Z7_WIN_WM_UPDATEUISTATE 0x0128 #define Z7_WIN_WM_QUERYUISTATE 0x0129 #endif #ifdef UIS_SET #define Z7_WIN_UIS_SET UIS_SET #define Z7_WIN_UIS_CLEAR UIS_CLEAR #define Z7_WIN_UIS_INITIALIZE UIS_INITIALIZE #define Z7_WIN_UISF_HIDEFOCUS UISF_HIDEFOCUS #define Z7_WIN_UISF_HIDEACCEL UISF_HIDEACCEL #else // these are defined for (_WIN32_WINNT >= 0x0500): // LOWORD(wParam) values in WM_*UISTATE #define Z7_WIN_UIS_SET 1 #define Z7_WIN_UIS_CLEAR 2 #define Z7_WIN_UIS_INITIALIZE 3 // HIWORD(wParam) values in WM_*UISTATE #define Z7_WIN_UISF_HIDEFOCUS 0x1 #define Z7_WIN_UISF_HIDEACCEL 0x2 // defined for for (_WIN32_WINNT >= 0x0501): // #define Z7_WIN_UISF_ACTIVE 0x4 #endif #endif // UNDER_CE #ifdef Z7_OLD_WIN_SDK // #define VK_OEM_1 0xBA // ';:' for US #define VK_OEM_PLUS 0xBB // '+' any country // #define VK_OEM_COMMA 0xBC // ',' any country #define VK_OEM_MINUS 0xBD // '-' any country // #define VK_OEM_PERIOD 0xBE // '.' any country // #define VK_OEM_2 0xBF // '/?' for US // #define VK_OEM_3 0xC0 // '`~' for US // #ifndef GWLP_USERDATA #define GWLP_WNDPROC (-4) #define GWLP_USERDATA (-21) // #endif #define DWLP_MSGRESULT 0 // #define DWLP_DLGPROC DWLP_MSGRESULT + sizeof(LRESULT) // #define DWLP_USER DWLP_DLGPROC + sizeof(DLGPROC) #define BTNS_BUTTON TBSTYLE_BUTTON // 0x0000 /* vc6 defines INT_PTR via long: typedef long INT_PTR, *PINT_PTR; typedef unsigned long UINT_PTR, *PUINT_PTR; but newer sdk (sdk2003+) defines INT_PTR via int: typedef _W64 int INT_PTR, *PINT_PTR; typedef _W64 unsigned int UINT_PTR, *PUINT_PTR; */ #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0) #define GetWindowLongPtrA GetWindowLongA #define GetWindowLongPtrW GetWindowLongW #ifdef UNICODE #define GetWindowLongPtr GetWindowLongPtrW #else #define GetWindowLongPtr GetWindowLongPtrA #endif // !UNICODE #define SetWindowLongPtrA SetWindowLongA #define SetWindowLongPtrW SetWindowLongW #ifdef UNICODE #define SetWindowLongPtr SetWindowLongPtrW #else #define SetWindowLongPtr SetWindowLongPtrA #endif // !UNICODE #define ListView_SetCheckState(hwndLV, i, fCheck) \ ListView_SetItemState(hwndLV, i, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), LVIS_STATEIMAGEMASK) #endif // Z7_OLD_WIN_SDK inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); } #define MY_int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i)) namespace NWindows { inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass) { return ::RegisterClass(wndClass); } #ifndef _UNICODE ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); #endif #ifdef _UNICODE inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); } #else bool MySetWindowText(HWND wnd, LPCWSTR s); #endif #ifdef UNDER_CE #define GWLP_USERDATA GWL_USERDATA #define GWLP_WNDPROC GWL_WNDPROC #define BTNS_BUTTON TBSTYLE_BUTTON #define WC_COMBOBOXW L"ComboBox" #define DWLP_MSGRESULT DWL_MSGRESULT #endif class CWindow { Z7_CLASS_NO_COPY(CWindow) private: // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags); protected: HWND _window; public: CWindow(HWND newWindow = NULL): _window(newWindow) {} CWindow& operator=(HWND newWindow) { _window = newWindow; return *this; } operator HWND() const { return _window; } void Attach(HWND newWindow) { _window = newWindow; } HWND Detach() { HWND window = _window; _window = NULL; return window; } bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); } HWND GetParent() const { return ::GetParent(_window); } bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); } #ifndef UNDER_CE bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); } #endif bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); } bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); } bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam) { _window = ::CreateWindowEx(exStyle, className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); return (_window != NULL); } bool Create(LPCTSTR className, LPCTSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam) { _window = ::CreateWindow(className, windowName, style, x, y, width, height, parentWindow, idOrHMenu, instance, createParam); return (_window != NULL); } #ifndef _UNICODE bool Create(LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam); bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, DWORD style, int x, int y, int width, int height, HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam); #endif bool Destroy() { if (_window == NULL) return true; bool result = BOOLToBool(::DestroyWindow(_window)); if (result) _window = NULL; return result; } bool IsWindow() { return BOOLToBool(::IsWindow(_window)); } bool Move(int x, int y, int width, int height, bool repaint = true) { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); } bool ChangeSubWindowSizeX(HWND hwnd, int xSize) { RECT rect; ::GetWindowRect(hwnd, &rect); POINT p1; p1.x = rect.left; p1.y = rect.top; ScreenToClient(&p1); return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE)); } void ScreenToClient(RECT *rect) { POINT p1, p2; p1.x = rect->left; p1.y = rect->top; p2.x = rect->right; p2.y = rect->bottom; ScreenToClient(&p1); ScreenToClient(&p2); rect->left = p1.x; rect->top = p1.y; rect->right = p2.x; rect->bottom = p2.y; } bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); } bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); } bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); } #ifndef UNDER_CE bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); } bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); } #endif bool Update() { return BOOLToBool(::UpdateWindow(_window)); } bool InvalidateRect(LPCRECT rect, bool backgroundErase = true) { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); } void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); } LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); } // LONG_PTR SetStyle(DWORD style) { return SetLongPtr(GWL_STYLE, (LONG_PTR)style); } LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); } // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); } LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); } LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); } LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); } LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); } #ifdef UNDER_CE LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); } LONG_PTR GetLongPtr(int index) const { return GetLong(index); } LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); } LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); } #else LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return ::SetWindowLongPtr(_window, index, #ifndef _WIN64 (LONG) #endif newLongPtr); } #ifndef _UNICODE LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr) { return ::SetWindowLongPtrW(_window, index, #ifndef _WIN64 (LONG) #endif newLongPtr); } #endif LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); } LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); } LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); } #endif /* bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) { return ModifyStyleBase(GWL_STYLE, remove, add, flags); } bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); } */ HWND SetFocus() { return ::SetFocus(_window); } LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return ::SendMessage(_window, message, wParam, lParam); } #ifndef _UNICODE LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return ::SendMessageW(_window, message, wParam, lParam); } #endif bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); } #ifndef _UNICODE bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); } #endif bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); } #ifndef _UNICODE bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); } #endif int GetTextLength() const { return GetWindowTextLength(_window); } int GetText(LPTSTR string, int maxCount) const { return GetWindowText(_window, string, maxCount); } bool GetText(CSysString &s) const; #ifndef _UNICODE /* UINT GetText(LPWSTR string, int maxCount) const { return GetWindowTextW(_window, string, maxCount); } */ bool GetText(UString &s) const; #endif bool Enable(bool enable) { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); } bool IsEnabled() const { return BOOLToBool(::IsWindowEnabled(_window)); } #ifndef UNDER_CE HMENU GetSystemMenu(bool revert) { return ::GetSystemMenu(_window, BoolToBOOL(revert)); } #endif UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = NULL) { return ::SetTimer(_window, idEvent, elapse, timerFunc); } bool KillTimer(UINT_PTR idEvent) {return BOOLToBool(::KillTimer(_window, idEvent)); } HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); } }; #define RECT_SIZE_X(r) ((r).right - (r).left) #define RECT_SIZE_Y(r) ((r).bottom - (r).top) inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; } } #endif tmp41wklro_/CS/0000700000175000001440000000000014706260545014447 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/0000700000175000001440000000000014706260545015340 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Common/0000700000175000001440000000000014706260545016570 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Common/CommandLineParser.cs0000444000175000001440000001540410156337732022474 0ustar nabijaczleweliusers// CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } tmp41wklro_/CS/7zip/Common/CRC.cs0000444000175000001440000000221010156340016017514 0ustar nabijaczleweliusers// Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } tmp41wklro_/CS/7zip/Common/InBuffer.cs0000444000175000001440000000255610156340122020620 0ustar nabijaczleweliusers// InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } tmp41wklro_/CS/7zip/Common/OutBuffer.cs0000444000175000001440000000166010156340120021012 0ustar nabijaczleweliusers// OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } tmp41wklro_/CS/7zip/Compress/0000700000175000001440000000000014706260545017133 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/LZ/0000700000175000001440000000000014706260545017460 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/LZ/IMatchFinder.cs0000444000175000001440000000110010367375131022301 0ustar nabijaczleweliusers// IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } tmp41wklro_/CS/7zip/Compress/LZ/LzBinTree.cs0000444000175000001440000002264510370102221021641 0ustar nabijaczleweliusers// LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } tmp41wklro_/CS/7zip/Compress/LZ/LzInWindow.cs0000444000175000001440000000750710370072257022066 0ustar nabijaczleweliusers// LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } tmp41wklro_/CS/7zip/Compress/LZ/LzOutWindow.cs0000444000175000001440000000424610643175734022273 0ustar nabijaczleweliusers// LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } tmp41wklro_/CS/7zip/Compress/LZMA/0000700000175000001440000000000014706260545017676 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/LZMA/LzmaBase.cs0000444000175000001440000000532410370615663021735 0ustar nabijaczleweliusers// LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } tmp41wklro_/CS/7zip/Compress/LZMA/LzmaDecoder.cs0000444000175000001440000002745310643175741022440 0ustar nabijaczleweliusers// LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } tmp41wklro_/CS/7zip/Compress/LZMA/LzmaEncoder.cs0000444000175000001440000013025011173305665022437 0ustar nabijaczleweliusers// LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } tmp41wklro_/CS/7zip/Compress/LzmaAlone/0000700000175000001440000000000014706260545021015 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs0000444000175000001440000002473311112200367023227 0ustar nabijaczleweliusersusing System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } tmp41wklro_/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln0000444000175000001440000000161610155141350023413 0ustar nabijaczleweliusers Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal tmp41wklro_/CS/7zip/Compress/LzmaAlone/LzmaBench.cs0000444000175000001440000002306210432013666023212 0ustar nabijaczleweliusers// LzmaBench.cs using System; using System.IO; namespace SevenZip { /// /// LZMA Benchmark /// internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } tmp41wklro_/CS/7zip/Compress/LzmaAlone/Properties/0000700000175000001440000000000014706260545023151 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs0000644000175000001440000000172010156133474026100 0ustar nabijaczleweliusers#region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] tmp41wklro_/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs0000644000175000001440000000400410155141322025443 0ustar nabijaczleweliusers//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } tmp41wklro_/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs0000644000175000001440000000203110155141322025267 0ustar nabijaczleweliusers//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } tmp41wklro_/CS/7zip/Compress/RangeCoder/0000700000175000001440000000000014706260545021144 5ustar nabijaczleweliuserstmp41wklro_/CS/7zip/Compress/RangeCoder/RangeCoder.cs0000444000175000001440000001013610345763654023521 0ustar nabijaczleweliusersusing System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } tmp41wklro_/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs0000444000175000001440000000631010203636304024137 0ustar nabijaczleweliusersusing System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } tmp41wklro_/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs0000444000175000001440000000670510156322710024767 0ustar nabijaczleweliusersusing System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } tmp41wklro_/CS/7zip/ICoder.cs0000444000175000001440000000726211210155614017036 0ustar nabijaczleweliusers// ICoder.h using System; namespace SevenZip { /// /// The exception that is thrown when an error in input stream occurs during decoding. /// class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// /// The exception that is thrown when the value of an argument is outside the allowable range. /// class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// /// Callback progress. /// /// /// input size. -1 if unknown. /// /// /// output size. -1 if unknown. /// void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// /// Codes streams. /// /// /// input Stream. /// /// /// output Stream. /// /// /// input Size. -1 if unknown. /// /// /// output Size. -1 if unknown. /// /// /// callback progress reference. /// /// /// if input stream is not valid /// void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// /// Provides the fields that represent properties idenitifiers for compressing. /// public enum CoderPropID { /// /// Specifies default property. /// DefaultProp = 0, /// /// Specifies size of dictionary. /// DictionarySize, /// /// Specifies size of memory for PPM*. /// UsedMemorySize, /// /// Specifies order for PPM methods. /// Order, /// /// Specifies Block Size. /// BlockSize, /// /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// PosStateBits, /// /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// LitContextBits, /// /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// LitPosBits, /// /// Specifies number of fast bytes for LZ*. /// NumFastBytes, /// /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// MatchFinder, /// /// Specifies the number of match finder cyckes. /// MatchFinderCycles, /// /// Specifies number of passes. /// NumPasses, /// /// Specifies number of algorithm. /// Algorithm, /// /// Specifies the number of threads. /// NumThreads, /// /// Specifies mode with end marker. /// EndMarker }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } tmp41wklro_/Java/0000700000175000001440000000000014706260545015023 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/0000700000175000001440000000000014706260545016566 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/Compression/0000700000175000001440000000000014706260545021067 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/Compression/LZ/0000700000175000001440000000000014706260545021414 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/Compression/LZ/BinTree.java0000444000175000001440000002173610370121353023612 0ustar nabijaczleweliusers// LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } tmp41wklro_/Java/SevenZip/Compression/LZ/InWindow.java0000444000175000001440000000721610370072262024021 0ustar nabijaczleweliusers// LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } tmp41wklro_/Java/SevenZip/Compression/LZ/OutWindow.java0000444000175000001440000000300510345001552024206 0ustar nabijaczleweliusers// LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } tmp41wklro_/Java/SevenZip/Compression/LZMA/0000700000175000001440000000000014706260545021632 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/Compression/LZMA/Base.java0000444000175000001440000000521110370623441023345 0ustar nabijaczleweliusers// Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } tmp41wklro_/Java/SevenZip/Compression/LZMA/Decoder.java0000444000175000001440000002342610346235422024051 0ustar nabijaczleweliuserspackage SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } tmp41wklro_/Java/SevenZip/Compression/LZMA/Encoder.java0000444000175000001440000012242511066617644024074 0ustar nabijaczleweliuserspackage SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols< 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } tmp41wklro_/Java/SevenZip/Compression/RangeCoder/0000700000175000001440000000000014706260545023100 5ustar nabijaczleweliuserstmp41wklro_/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java0000444000175000001440000000236710341011402026560 0ustar nabijaczleweliuserspackage SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } tmp41wklro_/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java0000444000175000001440000000412510341034674026604 0ustar nabijaczleweliuserspackage SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } tmp41wklro_/Java/SevenZip/Compression/RangeCoder/Decoder.java0000444000175000001440000000357410345254716025327 0ustar nabijaczleweliuserspackage SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } tmp41wklro_/Java/SevenZip/Compression/RangeCoder/Encoder.java0000444000175000001440000000624610345764736025350 0ustar nabijaczleweliuserspackage SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } tmp41wklro_/Java/SevenZip/CRC.java0000444000175000001440000000160310344254336020043 0ustar nabijaczleweliusers// SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } tmp41wklro_/Java/SevenZip/ICodeProgress.java0000444000175000001440000000016110343552236022141 0ustar nabijaczleweliuserspackage SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } tmp41wklro_/Java/SevenZip/LzmaAlone.java0000444000175000001440000001544411112200147021307 0ustar nabijaczleweliuserspackage SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } tmp41wklro_/Java/SevenZip/LzmaBench.java0000444000175000001440000002322310432014021021260 0ustar nabijaczleweliuserspackage SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } tmp41wklro_/DOC/0000700000175000001440000000000014706260545014547 5ustar nabijaczleweliuserstmp41wklro_/DOC/7zC.txt0000644000175000001440000001262212437617700015766 0ustar nabijaczleweliusers7z ANSI-C Decoder 9.35 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You can create .7z archive with 7z.exe, 7za.exe or 7zr.exe: 7z.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec : e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ Use SzArEx_GetFileNameUtf16 function. Look example code in C\Util\7z\7zMain.c file. Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html tmp41wklro_/DOC/7zFormat.txt0000644000175000001440000001663313275474152017045 0ustar nabijaczleweliusers7z Format description (18.06) ---------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd 0x01 = kHeader 0x02 = kArchiveProperties 0x03 = kAdditionalStreamsInfo 0x04 = kMainStreamsInfo 0x05 = kFilesInfo 0x06 = kPackInfo 0x07 = kUnPackInfo 0x08 = kSubStreamsInfo 0x09 = kSize 0x0A = kCRC 0x0B = kFolder 0x0C = kCodersUnPackSize 0x0D = kNumUnPackStream 0x0E = kEmptyStream 0x0F = kEmptyFile 0x10 = kAnti 0x11 = kName 0x12 = kCTime 0x13 = kATime 0x14 = kMTime 0x15 = kWinAttributes 0x16 = kComment 0x17 = kEncodedHeader 0x18 = kStartPos 0x19 = kDummy 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 4 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 CodecIdSize 4: Is Complex Coder 5: There Are Attributes 6: Reserved 7: There are more alternative methods. (Not used anymore, must be 0). } BYTE CodecId[CodecIdSize] if (Is Complex Coder) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (There Are Attributes) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCTime: (0x12) case kATime: (0x13) case kMTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) REAL_UINT64 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document tmp41wklro_/DOC/installer.txt0000644000175000001440000001240412452026606017312 0ustar nabijaczleweliusers7-Zip for installers 9.38 ------------------------- 7-Zip is a file archiver for Windows NT/2000/2003/2008/XP/Vista/7/8/10. 7-Zip for installers is part of LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. It's allowed to join 7-Zip SFX module with another software. It's allowed to change resources of 7-Zip's SFX modules. HOW to use ----------- 7zr.exe is reduced version of 7za.exe of 7-Zip. 7zr.exe supports only format with these codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, Copy. Example of compressing command for installation packages: 7zr a archive.7z files 7zSD.sfx is SFX module for installers. 7zSD.sfx uses msvcrt.dll. SFX modules for installers allow to create installation program. Such module extracts archive to temp folder and then runs specified program and removes temp files after program finishing. Self-extract archive for installers must be created as joining 3 files: SFX_Module, Installer_Config, 7z_Archive. Installer_Config is optional file. You can use the following command to create installer self-extract archive: copy /b 7zSD.sfx + config.txt + archive.7z archive.exe The smallest installation package size can be achieved, if installation files was uncompressed before including to 7z archive. -y switch for installer module (at runtime) specifies quiet mode for extracting. Installer Config file format ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Config file contains commands for Installer. File begins from string ;!@Install@!UTF-8! and ends with ;!@InstallEnd@!. File must be written in UTF-8 encoding. File contains string pairs: ID_String="Value" ID_String Description Title Title for messages BeginPrompt Begin Prompt message Progress Value can be "yes" or "no". Default value is "yes". RunProgram Command for executing. Default value is "setup.exe". Substring %%T will be replaced with path to temporary folder, where files were extracted Directory Directory prefix for "RunProgram". Default value is ".\\" ExecuteFile Name of file for executing ExecuteParameters Parameters for "ExecuteFile" You can omit any string pair. There are two ways to run program: RunProgram and ExecuteFile. Use RunProgram, if you want to run some program from .7z archive. Use ExecuteFile, if you want to open some document from .7z archive or if you want to execute some command from Windows. If you use RunProgram and if you specify empty directory prefix: Directory="", the system searches for the executable file in the following sequence: 1. The directory from which the application (installer) loaded. 2. The temporary folder, where files were extracted. 3. The Windows system directory. Config file Examples ~~~~~~~~~~~~~~~~~~~~ ;!@Install@!UTF-8! Title="7-Zip 4.00" BeginPrompt="Do you want to install the 7-Zip 4.00?" RunProgram="setup.exe" ;!@InstallEnd@! ;!@Install@!UTF-8! Title="7-Zip 4.00" BeginPrompt="Do you want to install the 7-Zip 4.00?" ExecuteFile="7zip.msi" ;!@InstallEnd@! ;!@Install@!UTF-8! Title="7-Zip 4.01 Update" BeginPrompt="Do you want to install the 7-Zip 4.01 Update?" ExecuteFile="msiexec.exe" ExecuteParameters="/i 7zip.msi REINSTALL=ALL REINSTALLMODE=vomus" ;!@InstallEnd@! Small SFX modules for installers -------------------------------- 7zS2.sfx - small SFX module (GUI version) 7zS2con.sfx - small SFX module (Console version) Small SFX modules support this codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, COPY Small SFX module is similar to common SFX module for installers. The difference (what's new in small version): - Smaller size (30 KB vs 100 KB) - C source code instead of Ñ++ - No installer Configuration file - No extracting progress window - It decompresses solid 7z blocks (it can be whole 7z archive) to RAM. So user that calls SFX installer must have free RAM of size of largest solid 7z block (size of 7z archive at simplest case). How to use ---------- copy /b 7zS2.sfx + archive.7z sfx.exe When you run installer sfx module (sfx.exe) 1) It creates "7zNNNNNNNN" temp folder in system temp folder. 2) It extracts .7z archive to that folder 3) It executes one file from "7zNNNNNNNN" temp folder. 4) It removes "7zNNNNNNNN" temp folder You can send parameters to installer, and installer will transfer them to extracted .exe file. Small SFX uses 3 levels of priorities to select file to execute: 1) Files in root folder have higher priority than files in subfolders. 2) File extension priorities (from high to low priority order): bat, cmd, exe, inf, msi, cab (under Windows CE), html, htm 3) File name priorities (from high to low priority order): setup, install, run, start Windows CE (ARM) version of 7zS2.sfx is included to 7-Zip for Windows Mobile package. Examples -------- 1) To create compressed console 7-Zip: 7zr a c.7z 7z.exe 7z.dll -mx copy /b 7zS2con.sfx + c.7z 7zCompr.exe 7zCompr.exe b -md22 2) To create compressed GUI 7-Zip: 7zr a g.7z 7zg.exe 7z.dll -mx copy /b 7zS2.sfx + g.7z 7zgCompr.exe 7zgCompr.exe b -md22 3) To open some file: 7zr a h.7z readme.txt -mx copy /b 7zS2.sfx + h.7z 7zTxt.exe 7zTxt.exe tmp41wklro_/DOC/lzma-history.txt0000644000175000001440000005402614634517020017764 0ustar nabijaczleweliusersHISTORY of the LZMA SDK ----------------------- 24.07 2024-06-19 ------------------------- - Changes in files: Asm/x86/Sha256Opt.asm Now it uses "READONLY" flag for constant array segment. It fixes an issue where ".rodata" section in 7-Zip for x86/x64 Linux had a "WRITE" attribute. 24.05 2024-05-14 ------------------------- - New switch -myv={MMNN} to set decoder compatibility version for 7z archive creating. {MMNN} is 4-digit number that represents the version of 7-Zip without a dot. If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can be decoded by the specified version {MMNN} of 7-Zip and newer versions. If -myv={MMNN} switch is not specified, -myv=2300 is used, and 7-Zip will only use compression methods that can be decoded by 7-Zip 23.00 and newer versions. - New switch -myfa={FilterID} to allow 7-Zip to use the specified filter method for 7z archive creating. - New switch -myfd={FilterID} to disallow 7-Zip to use the specified filter method for 7z archive creating. 24.03 2024-03-23 ------------------------- - 7-Zip now can use new RISCV filter for compression to 7z and xz archives. RISCV filter can increase compression ratio for data containing executable files compiled for RISC-V architecture. - The speed for LZMA and LZMA2 decompression in ARM64 version for Windows was increased by 20%-60%. It uses arm64 assembler code, and clang-cl is required for arm64 assembler code compiling. - -slmu switch : to show timestamps as UTC instead of LOCAL TIME. - -slsl switch : in console 7-Zip for Windows : to show file paths with linux path separator slash '/' instead of backslash separator '\'. - 7-Zip supports .sha256 files that use backslash path separator '\'. - Some bugs were fixed. 24.01 2024-01-31 ------------------------- - 7-Zip uses file C/Precomp.h that is included to all c and c++ files. CPP/Common/Common.h also includes C/Precomp.h. C/Precomp.h defines the following macros (if _WIN32 is defined): Z7_LARGE_PAGES 1 Z7_LONG_PATH 1 Z7_WIN32_WINNT_MIN 0x0500 (or higher) _WIN32_WINNT 0x0500 (or higher) WINVER _WIN32_WINNT UNICODE 1 _UNICODE 1 if _WIN32_WINNT is defined already, C/Precomp.h doesn't redefine it. - Speed optimizations for hash caclulation: CRC-32, CRC-64. - The bug was fixed: 7-Zip for Linux could fail for multivolume creation in some cases. - 7zr.exe for arm64 is included to LZMA SDK package. - Some bugs were fixed. 23.01 2023-06-20 ------------------------- - 7-Zip now can use new ARM64 filter for compression to 7z and xz archives. ARM64 filter can increase compression ratio for data containing executable files compiled for ARM64 (AArch64) architecture. Also 7-Zip now parses executable files (that have exe and dll filename extensions) before compressing, and it selects appropriate filter for each parsed file: - BCJ or BCJ2 filter for x86 executable files, - ARM64 filter for ARM64 executable files. Previous versions by default used x86 filter BCJ or BCJ2 for all exe/dll files. - Default section size for BCJ2 filter was changed from 64 MiB to 240 MiB. It can increase compression ratio for executable files larger than 64 MiB. - Some optimizations in filters code: BCJ, BCJ2, Swap* and opthers. - If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp files in system's TEMP folder. 7-Zip uses temp file for additional compressed data stream, if size of such compressed stream is larger than predefined limit: 16 MiB in 32-bit version, 4 GiB in 64-bit version. - When new 7-Zip creates multivolume archive, 7-Zip keeps in open state only volumes that still can be changed. Previous versions kept all volumes in open state until the end of the archive creation. - 7-Zip for Linux and macOS now can reduce the number of simultaneously open files, when 7-Zip opens, extracts or creates multivolume archive. It allows to avoid the failures for cases with big number of volumes, bacause there is a limitation for number of open files allowed for a single program in Linux and macOS. - Some bugs were fixed. - Source code changes: - All external macros for compiling C/C++ code of 7-Zip now have Z7_ prefix. - 7-Zip COM interfaces now use new macros that allow to declare and implement COM interface. - The code has been modified to compile with the maximum diagnostic warning level: -Wall in MSVC and -Weverything in CLANG. And some warning types are disabled in 2 files: - C/Compiler.h for C/C++ code warnings. - CPP/Common/Common.h for C++ code warnings. - Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use virtual destructor that was used in previous 7-Zip and p7zip: // virtual ~IUnknown() {} So 7-Zip's dynamically linked shared libraries (codecs) are not compatible between new 7-Zip for Linux/macOS and old 7-Zip (and p7zip). 21.07 2021-12-26 ------------------------- - New switches: -spm and -im!{file_path} to exclude directories from processing for specified paths that don't contain path separator character at the end of path. - The sorting order of files in archives was slightly changed to be more consistent for cases where the name of some directory is the same as the prefix part of the name of another directory or file. 21.06 2021-11-24 ------------------------- - Bug in LZMA encoder in file LzmaEnc.c was fixed: LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, if size value for output buffer is smaller than size required for all compressed data. LzmaEnc_Encode() could work incorrectly, if callback ISeqOutStream::Write() doesn't write all compressed data. NCompress::NLzma::CEncoder::Code() could work incorrectly, if callback ISequentialOutStream::Write() returns error code. - Bug in versions 21.00-21.05 was fixed: 7-Zip didn't set attributes of directories during archive extracting. 21.04 beta 2021-11-02 ------------------------- - 7-Zip now reduces the number of working CPU threads for compression, if RAM size is not enough for compression with big LZMA2 dictionary. - 7-Zip now can create and check "file.sha256" text files that contain the list of file names and SHA-256 checksums in format compatible with sha256sum program. 21.03 beta 2021-07-20 ------------------------- - The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB). - Minor speed optimizations in LZMA/LZMA2 compressing. 21.02 alpha 2021-05-06 ------------------------- - The command line version of 7-Zip for macOS was released. - The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux was increased by 20%-60%. 21.01 alpha 2021-03-09 ------------------------- - The command line version of 7-Zip for Linux was released. - The improvements for speed of ARM64 version using hardware CPU instructions for AES, CRC-32, SHA-1 and SHA-256. - Some bugs were fixed. 20.02 alpha 2020-08-08 ------------------------- - The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. It allows to increase the compression speed for big 7z archives, if there is a big number of CPU cores and threads. - The speed of PPMd compressing/decompressing was increased for 7z archives. - The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system to modify "Last Access Time" property of source files for archiving and hashing operations. - Some bugs were fixed. 20.00 alpha 2020-02-06 ------------------------- - 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, that can work faster than bt4 and hc4 match finders for the data with big redundancy. - The compression ratio was improved for Fast and Fastest compression levels with the following default settings: - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. - Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra compression levels. 19.00 2019-02-21 ------------------------- - Encryption strength for 7z archives was increased: the size of random initialization vector was increased from 64-bit to 128-bit, and the pseudo-random number generator was improved. - The bug in 7zIn.c code was fixed. 18.06 2018-12-30 ------------------------- - The speed for LZMA/LZMA2 compressing was increased by 3-10%, and there are minor changes in compression ratio. - Some bugs were fixed. - The bug in 7-Zip 18.02-18.05 was fixed: There was memory leak in multithreading xz decoder - XzDecMt_Decode(), if xz stream contains only one block. - The changes for MSVS compiler makefiles: - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64) instead of "CPU" macroname with values (AMD64, ARM64). - the makefiles by default now use static version of the run-time library. 18.05 2018-04-30 ------------------------- - The speed for LZMA/LZMA2 compressing was increased by 8% for fastest/fast compression levels and by 3% for normal/maximum compression levels. - Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in Windows 10 because of some BUG with "Large Pages" in Windows 10. Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). - The BUG was fixed in Lzma2Enc.c Lzma2Enc_Encode2() function worked incorretly, if (inStream == NULL) and the number of block threads is more than 1. 18.03 beta 2018-03-04 ------------------------- - Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm for x64 with about 30% higher speed than main version of LZMA decoder written in C. - The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. - 7-Zip now can use multi-threading for 7z/LZMA2 decoding, if there are multiple independent data chunks in LZMA2 stream. - 7-Zip now can use multi-threading for xz decoding, if there are multiple blocks in xz stream. 18.01 2019-01-28 ------------------------- - The BUG in 17.01 - 18.00 beta was fixed: XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished() didn't work correctly for xz archives without checksum (CRC). 18.00 beta 2019-01-10 ------------------------- - The BUG in xz encoder was fixed: There was memory leak of 16 KB for each file compressed with xz compression method, if additional filter was used. 17.01 beta 2017-08-28 ------------------------- - Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression. 7-Zip now uses additional memory buffers for multi-block LZMA2 compression. CPU utilization was slightly improved. - 7-zip now creates multi-block xz archives by default. Block size can be specified with -ms[Size]{m|g} switch. - xz decoder now can unpack random block from multi-block xz archives. - 7-Zip command line: @listfile now doesn't work after -- switch. Use -i@listfile before -- switch instead. - The BUGs were fixed: 7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive. 17.00 beta 2017-04-29 ------------------------- - NewHandler.h / NewHandler.cpp: now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). - C/7zTypes.h : the names of variables in interface structures were changed (vt). - Some bugs were fixed. 7-Zip could crash in some cases. - Some internal changes in code. 16.04 2016-10-04 ------------------------- - The bug was fixed in DllSecur.c. 16.03 2016-09-28 ------------------------- - SFX modules now use some protection against DLL preloading attack. - Some bugs in 7z code were fixed. 16.02 2016-05-21 ------------------------- - The BUG in 16.00 - 16.01 was fixed: Split Handler (SplitHandler.cpp) returned incorrect total size value (kpidSize) for split archives. 16.01 2016-05-19 ------------------------- - Some internal changes to reduce the number of compiler warnings. 16.00 2016-05-10 ------------------------- - Some bugs were fixed. 15.12 2015-11-19 ------------------------- - The BUG in C version of 7z decoder was fixed: 7zDec.c : SzDecodeLzma2() 7z decoder could mistakenly report about decoding error for some 7z archives that use LZMA2 compression method. The probability to get that mistaken decoding error report was about one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). - The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: 7zArcIn.c : SzReadHeader2() 7z decoder worked incorrectly for 7z archives that contain empty solid blocks, that can be placed to 7z archive, if some file is unavailable for reading during archive creation. 15.09 beta 2015-10-16 ------------------------- - The BUG in LZMA / LZMA2 encoding code was fixed. The BUG in LzFind.c::MatchFinder_ReadBlock() function. If input data size is larger than (4 GiB - dictionary_size), the following code worked incorrectly: - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions for compressing from memory to memory. That BUG is not related to LZMA encoder version that works via streams. - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if default value of chunk size (CLzma2EncProps::blockSize) is changed to value larger than (4 GiB - dictionary_size). 9.38 beta 2015-01-03 ------------------------- - The BUG in 9.31-9.37 was fixed: IArchiveGetRawProps interface was disabled for 7z archives. - The BUG in 9.26-9.36 was fixed: Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows. 9.36 beta 2014-12-26 ------------------------- - The BUG in command line version was fixed: 7-Zip created temporary archive in current folder during update archive operation, if -w{Path} switch was not specified. The fixed 7-Zip creates temporary archive in folder that contains updated archive. - The BUG in 9.33-9.35 was fixed: 7-Zip silently ignored file reading errors during 7z or gz archive creation, and the created archive contained only part of file that was read before error. The fixed 7-Zip stops archive creation and it reports about error. 9.35 beta 2014-12-07 ------------------------- - 7zr.exe now support AES encryption. - SFX mudules were added to LZMA SDK - Some bugs were fixed. 9.21 beta 2011-04-11 ------------------------- - New class FString for file names at file systems. - Speed optimization in CRC code for big-endian CPUs. - The BUG in Lzma2Dec.c was fixed: Lzma2Decode function didn't work. 9.18 beta 2010-11-02 ------------------------- - New small SFX module for installers (SfxSetup). 9.12 beta 2010-03-24 ------------------------- - The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, if more than 10 threads were used (or more than 20 threads in some modes). 9.11 beta 2010-03-15 ------------------------- - PPMd compression method support 9.09 2009-12-12 ------------------------- - The bug was fixed: Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. - Some bugs were fixed 9.06 2009-08-17 ------------------------- - Some changes in ANSI-C 7z Decoder interfaces. 9.04 2009-05-30 ------------------------- - LZMA2 compression method support - xz format support 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in Ñ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document tmp41wklro_/DOC/lzma-sdk.txt0000644000175000001440000003502214655707200017043 0ustar nabijaczleweliusersLZMA SDK 24.08 -------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use 7z / LZMA / LZMA2 / XZ compression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LZMA2 is a LZMA based compression method. LZMA2 provides better multithreading support for compression than LZMA and some other improvements. 7z is a file format for data compression and file archiving. 7z is a main file format for 7-Zip compression program (www.7-zip.org). 7z format supports different compression methods: LZMA, LZMA2 and others. 7z also supports AES-256 based encryption. XZ is a file format for data compression that uses LZMA2 compression. XZ format provides additional features: SHA/CRC check, filters for improved compression ratio, splitting to blocks and streams, LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. Some code in LZMA SDK is based on public domain code from another developers: 1) PPMd var.H (2001): Dmitry Shkarin 2) SHA-256: Wei Dai (Crypto++ library) Anyone is free to copy, modify, publish, use, compile, sell, or distribute the original LZMA SDK code, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. LZMA SDK code is compatible with open source licenses, for example, you can include it to GNU GPL or GNU LGPL code. LZMA SDK Contents ----------------- Source code: - C / C++ / C# / Java - LZMA compression and decompression - C / C++ - LZMA2 compression and decompression - C / C++ - XZ compression and decompression - C - 7z decompression - C++ - 7z compression and decompression - C - small SFXs for installers (7z decompression) - C++ - SFXs and SFXs for installers (7z decompression) Precomiled binaries: - console programs for lzma / 7z / xz compression and decompression - SFX modules for installers. UNIX/Linux version ------------------ There are several otpions to compile 7-Zip with different compilers: gcc and clang. Also 7-Zip code contains two versions for some critical parts of code: in C and in Assembeler. So if you compile the version with Assembeler code, you will get faster 7-Zip binary. 7-Zip's assembler code uses the following syntax for different platforms: 1) x86 and x86-64 (AMD64): MASM syntax. There are 2 programs that supports MASM syntax in Linux. ' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some cpu instructions used in 7-Zip. So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version of 7-Zip x86 and x86-64: https://github.com/nidud/asmc 2) arm64: GNU assembler for ARM64 with preprocessor. That systax of that arm64 assembler code in 7-Zip is supported by GCC and CLANG for ARM64. There are different binaries that can be compiled from 7-Zip source. There are 2 main files in folder for compiling: makefile - that can be used for compiling Windows version of 7-Zip with nmake command makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip with make command At first you must change the current folder to folder that contains `makefile.gcc`: cd CPP/7zip/Bundles/Alone7z Then you can compile `makefile.gcc` with the command: make -j -f makefile.gcc Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile 7-Zip binaries with optimized code and optimzing options. To compile with GCC without assembler: cd CPP/7zip/Bundles/Alone7z make -j -f ../../cmpl_gcc.mak To compile with CLANG without assembler: make -j -f ../../cmpl_clang.mak To compile 7-Zip for x86-64 with asmc assembler: make -j -f ../../cmpl_gcc_x64.mak To compile 7-Zip for arm64 with assembler: make -j -f ../../cmpl_gcc_arm64.mak To compile 7-Zip for arm64 for macOS: make -j -f ../../cmpl_mac_arm64.mak Also you can change some compiler options in the mak files: cmpl_gcc.mak var_gcc.mak warn_gcc.mak Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux): http://p7zip.sourceforge.net/ Files ----- DOC/7zC.txt - 7z ANSI-C Decoder description DOC/7zFormat.txt - 7z Format description DOC/installer.txt - information about 7-Zip for installers DOC/lzma.txt - LZMA compression description DOC/lzma-sdk.txt - LZMA SDK description (this file) DOC/lzma-history.txt - history of LZMA SDK DOC/lzma-specification.txt - Specification of LZMA DOC/Methods.txt - Compression method IDs for .7z bin/installer/ - example script to create installer that uses SFX module, bin/7zdec.exe - simplified 7z archive decoder (x86 32-bit version) bin/7zr.exe - 7-Zip console program (reduced version) (x86 32-bit version) bin/x64/7zr.exe - 7-Zip console program (reduced version) (x64 version) bin/x64/7zdec.exe - simplified 7z archive decoder (x64 version) bin/arm64/7zr.exe - 7-Zip console program (reduced version) (arm64 version) bin/arm64/7zdec.exe - simplified 7z archive decoder (arm64 version) bin/lzma.exe - file->file LZMA encoder/decoder for Windows bin/7zS2.sfx - small SFX module for installers (GUI version) bin/7zS2con.sfx - small SFX module for installers (Console version) bin/7zSD.sfx - SFX module for installers. 7zDec.exe --------- 7zDec.exe is simplified 7z archive decoder. It supports only LZMA, LZMA2, and PPMd methods. 7zDec decodes whole solid block from 7z archive to RAM. The RAM consumption can be high. Source code structure --------------------- Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption) C/ - C files (compression / decompression and other) Util/ 7z - 7z decoder program (decoding 7z files) Lzma - LZMA program (file->file LZMA encoder/decoder). LzmaLib - LZMA library (.DLL for Windows) SfxSetup - small SFX module for installers CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules (files) Alone7z - 7zr.exe: Standalone 7-Zip console program (reduced version) Format7zExtractR - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2. Format7zR - 7zr.dll: Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2 LzmaCon - lzma.exe: LZMA compression/decompression LzmaSpec - example code for LZMA Specification SFXCon - 7zCon.sfx: Console 7z SFX module SFXSetup - 7zS.sfx: 7z SFX module for installers SFXWin - 7z.sfx: GUI 7z SFX module Common - common files for 7-Zip Compress - files for compression/decompression Crypto - files for encryption / decompression UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console program (7z.exe) Explorer - Some code from 7-Zip Shell extension FileManager - Some GUI code from 7-Zip File Manager GUI - Some GUI code from 7-Zip CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Note: Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code. 7-Zip's source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on modern 2 GHz cpu - 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC) - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Mispredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA inputFile outputFile [...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html tmp41wklro_/DOC/lzma-specification.txt0000644000175000001440000010763112537344232021107 0ustar nabijaczleweliusersLZMA specification (DRAFT version) ---------------------------------- Author: Igor Pavlov Date: 2015-06-14 This specification defines the format of LZMA compressed data and lzma file format. Notation -------- We use the syntax of C++ programming language. We use the following types in C++ code: unsigned - unsigned integer, at least 16 bits in size int - signed integer, at least 16 bits in size UInt64 - 64-bit unsigned integer UInt32 - 32-bit unsigned integer UInt16 - 16-bit unsigned integer Byte - 8-bit unsigned integer bool - boolean type with two possible values: false, true lzma file format ================ The lzma file contains the raw LZMA stream and the header with related properties. The files in that format use ".lzma" extension. The lzma file format layout: Offset Size Description 0 1 LZMA model properties (lc, lp, pb) in encoded form 1 4 Dictionary size (32-bit unsigned integer, little-endian) 5 8 Uncompressed size (64-bit unsigned integer, little-endian) 13 Compressed data (LZMA stream) LZMA properties: name Range Description lc [0, 8] the number of "literal context" bits lp [0, 4] the number of "literal pos" bits pb [0, 4] the number of "pos" bits dictSize [0, 2^32 - 1] the dictionary size The following code encodes LZMA properties: void EncodeProperties(Byte *properties) { properties[0] = (Byte)((pb * 5 + lp) * 9 + lc); Set_UInt32_LittleEndian(properties + 1, dictSize); } If the value of dictionary size in properties is smaller than (1 << 12), the LZMA decoder must set the dictionary size variable to (1 << 12). #define LZMA_DIC_MIN (1 << 12) unsigned lc, pb, lp; UInt32 dictSize; UInt32 dictSizeInProperties; void DecodeProperties(const Byte *properties) { unsigned d = properties[0]; if (d >= (9 * 5 * 5)) throw "Incorrect LZMA properties"; lc = d % 9; d /= 9; pb = d / 5; lp = d % 5; dictSizeInProperties = 0; for (int i = 0; i < 4; i++) dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i); dictSize = dictSizeInProperties; if (dictSize < LZMA_DIC_MIN) dictSize = LZMA_DIC_MIN; } If "Uncompressed size" field contains ones in all 64 bits, it means that uncompressed size is unknown and there is the "end marker" in stream, that indicates the end of decoding point. In opposite case, if the value from "Uncompressed size" field is not equal to ((2^64) - 1), the LZMA stream decoding must be finished after specified number of bytes (Uncompressed size) is decoded. And if there is the "end marker", the LZMA decoder must read that marker also. The new scheme to encode LZMA properties ---------------------------------------- If LZMA compression is used for some another format, it's recommended to use a new improved scheme to encode LZMA properties. That new scheme was used in xz format that uses the LZMA2 compression algorithm. The LZMA2 is a new compression algorithm that is based on the LZMA algorithm. The dictionary size in LZMA2 is encoded with just one byte and LZMA2 supports only reduced set of dictionary sizes: (2 << 11), (3 << 11), (2 << 12), (3 << 12), ... (2 << 30), (3 << 30), (2 << 31) - 1 The dictionary size can be extracted from encoded value with the following code: dictSize = (p == 40) ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); Also there is additional limitation (lc + lp <= 4) in LZMA2 for values of "lc" and "lp" properties: if (lc + lp > 4) throw "Unsupported properties: (lc + lp) > 4"; There are some advantages for LZMA decoder with such (lc + lp) value limitation. It reduces the maximum size of tables allocated by decoder. And it reduces the complexity of initialization procedure, that can be important to keep high speed of decoding of big number of small LZMA streams. It's recommended to use that limitation (lc + lp <= 4) for any new format that uses LZMA compression. Note that the combinations of "lc" and "lp" parameters, where (lc + lp > 4), can provide significant improvement in compression ratio only in some rare cases. The LZMA properties can be encoded into two bytes in new scheme: Offset Size Description 0 1 The dictionary size encoded with LZMA2 scheme 1 1 LZMA model properties (lc, lp, pb) in encoded form The RAM usage ============= The RAM usage for LZMA decoder is determined by the following parts: 1) The Sliding Window (from 4 KiB to 4 GiB). 2) The probability model counter arrays (arrays of 16-bit variables). 3) Some additional state variables (about 10 variables of 32-bit integers). The RAM usage for Sliding Window -------------------------------- There are two main scenarios of decoding: 1) The decoding of full stream to one RAM buffer. If we decode full LZMA stream to one output buffer in RAM, the decoder can use that output buffer as sliding window. So the decoder doesn't need additional buffer allocated for sliding window. 2) The decoding to some external storage. If we decode LZMA stream to external storage, the decoder must allocate the buffer for sliding window. The size of that buffer must be equal or larger than the value of dictionary size from properties of LZMA stream. In this specification we describe the code for decoding to some external storage. The optimized version of code for decoding of full stream to one output RAM buffer can require some minor changes in code. The RAM usage for the probability model counters ------------------------------------------------ The size of the probability model counter arrays is calculated with the following formula: size_of_prob_arrays = 1846 + 768 * (1 << (lp + lc)) Each probability model counter is 11-bit unsigned integer. If we use 16-bit integer variables (2-byte integers) for these probability model counters, the RAM usage required by probability model counter arrays can be estimated with the following formula: RAM = 4 KiB + 1.5 KiB * (1 << (lp + lc)) For example, for default LZMA parameters (lp = 0 and lc = 3), the RAM usage is RAM_lc3_lp0 = 4 KiB + 1.5 KiB * 8 = 16 KiB The maximum RAM state usage is required for decoding the stream with lp = 4 and lc = 8: RAM_lc8_lp4 = 4 KiB + 1.5 KiB * 4096 = 6148 KiB If the decoder uses LZMA2's limited property condition (lc + lp <= 4), the RAM usage will be not larger than RAM_lc_lp_4 = 4 KiB + 1.5 KiB * 16 = 28 KiB The RAM usage for encoder ------------------------- There are many variants for LZMA encoding code. These variants have different values for memory consumption. Note that memory consumption for LZMA Encoder can not be smaller than memory consumption of LZMA Decoder for same stream. The RAM usage required by modern effective implementation of LZMA Encoder can be estimated with the following formula: Encoder_RAM_Usage = 4 MiB + 11 * dictionarySize. But there are some modes of the encoder that require less memory. LZMA Decoding ============= The LZMA compression algorithm uses LZ-based compression with Sliding Window and Range Encoding as entropy coding method. Sliding Window -------------- LZMA uses Sliding Window compression similar to LZ77 algorithm. LZMA stream must be decoded to the sequence that consists of MATCHES and LITERALS: - a LITERAL is a 8-bit character (one byte). The decoder just puts that LITERAL to the uncompressed stream. - a MATCH is a pair of two numbers (DISTANCE-LENGTH pair). The decoder takes one byte exactly "DISTANCE" characters behind current position in the uncompressed stream and puts it to uncompressed stream. The decoder must repeat it "LENGTH" times. The "DISTANCE" can not be larger than dictionary size. And the "DISTANCE" can not be larger than the number of bytes in the uncompressed stream that were decoded before that match. In this specification we use cyclic buffer to implement Sliding Window for LZMA decoder: class COutWindow { Byte *Buf; UInt32 Pos; UInt32 Size; bool IsFull; public: unsigned TotalPos; COutStream OutStream; COutWindow(): Buf(NULL) {} ~COutWindow() { delete []Buf; } void Create(UInt32 dictSize) { Buf = new Byte[dictSize]; Pos = 0; Size = dictSize; IsFull = false; TotalPos = 0; } void PutByte(Byte b) { TotalPos++; Buf[Pos++] = b; if (Pos == Size) { Pos = 0; IsFull = true; } OutStream.WriteByte(b); } Byte GetByte(UInt32 dist) const { return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos]; } void CopyMatch(UInt32 dist, unsigned len) { for (; len > 0; len--) PutByte(GetByte(dist)); } bool CheckDistance(UInt32 dist) const { return dist <= Pos || IsFull; } bool IsEmpty() const { return Pos == 0 && !IsFull; } }; In another implementation it's possible to use one buffer that contains Sliding Window and the whole data stream after uncompressing. Range Decoder ------------- LZMA algorithm uses Range Encoding (1) as entropy coding method. LZMA stream contains just one very big number in big-endian encoding. LZMA decoder uses the Range Decoder to extract a sequence of binary symbols from that big number. The state of the Range Decoder: struct CRangeDecoder { UInt32 Range; UInt32 Code; InputStream *InStream; bool Corrupted; } The notes about UInt32 type for the "Range" and "Code" variables: It's possible to use 64-bit (unsigned or signed) integer type for the "Range" and the "Code" variables instead of 32-bit unsigned, but some additional code must be used to truncate the values to low 32-bits after some operations. If the programming language does not support 32-bit unsigned integer type (like in case of JAVA language), it's possible to use 32-bit signed integer, but some code must be changed. For example, it's required to change the code that uses comparison operations for UInt32 variables in this specification. The Range Decoder can be in some states that can be treated as "Corruption" in LZMA stream. The Range Decoder uses the variable "Corrupted": (Corrupted == false), if the Range Decoder has not detected any corruption. (Corrupted == true), if the Range Decoder has detected some corruption. The reference LZMA Decoder ignores the value of the "Corrupted" variable. So it continues to decode the stream, even if the corruption can be detected in the Range Decoder. To provide the full compatibility with output of the reference LZMA Decoder, another LZMA Decoder implementations must also ignore the value of the "Corrupted" variable. The LZMA Encoder is required to create only such LZMA streams, that will not lead the Range Decoder to states, where the "Corrupted" variable is set to true. The Range Decoder reads first 5 bytes from input stream to initialize the state: bool CRangeDecoder::Init() { Corrupted = false; Range = 0xFFFFFFFF; Code = 0; Byte b = InStream->ReadByte(); for (int i = 0; i < 4; i++) Code = (Code << 8) | InStream->ReadByte(); if (b != 0 || Code == Range) Corrupted = true; return b == 0; } The LZMA Encoder always writes ZERO in initial byte of compressed stream. That scheme allows to simplify the code of the Range Encoder in the LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must stop decoding and report error. After the last bit of data was decoded by Range Decoder, the value of the "Code" variable must be equal to 0. The LZMA Decoder must check it by calling the IsFinishedOK() function: bool IsFinishedOK() const { return Code == 0; } If there is corruption in data stream, there is big probability that the "Code" value will be not equal to 0 in the Finish() function. So that check in the IsFinishedOK() function provides very good feature for corruption detection. The value of the "Range" variable before each bit decoding can not be smaller than ((UInt32)1 << 24). The Normalize() function keeps the "Range" value in described range. #define kTopValue ((UInt32)1 << 24) void CRangeDecoder::Normalize() { if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | InStream->ReadByte(); } } Notes: if the size of the "Code" variable is larger than 32 bits, it's required to keep only low 32 bits of the "Code" variable after the change in Normalize() function. If the LZMA Stream is not corrupted, the value of the "Code" variable is always smaller than value of the "Range" variable. But the Range Decoder ignores some types of corruptions, so the value of the "Code" variable can be equal or larger than value of the "Range" variable for some "Corrupted" archives. LZMA uses Range Encoding only with binary symbols of two types: 1) binary symbols with fixed and equal probabilities (direct bits) 2) binary symbols with predicted probabilities The DecodeDirectBits() function decodes the sequence of direct bits: UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits) { UInt32 res = 0; do { Range >>= 1; Code -= Range; UInt32 t = 0 - ((UInt32)Code >> 31); Code += Range & t; if (Code == Range) Corrupted = true; Normalize(); res <<= 1; res += t + 1; } while (--numBits); return res; } The Bit Decoding with Probability Model --------------------------------------- The task of Bit Probability Model is to estimate probabilities of binary symbols. And then it provides the Range Decoder with that information. The better prediction provides better compression ratio. The Bit Probability Model uses statistical data of previous decoded symbols. That estimated probability is presented as 11-bit unsigned integer value that represents the probability of symbol "0". #define kNumBitModelTotalBits 11 Mathematical probabilities can be presented with the following formulas: probability(symbol_0) = prob / 2048. probability(symbol_1) = 1 - Probability(symbol_0) = = 1 - prob / 2048 = = (2048 - prob) / 2048 where the "prob" variable contains 11-bit integer probability counter. It's recommended to use 16-bit unsigned integer type, to store these 11-bit probability values: typedef UInt16 CProb; Each probability value must be initialized with value ((1 << 11) / 2), that represents the state, where probabilities of symbols 0 and 1 are equal to 0.5: #define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2) The INIT_PROBS macro is used to initialize the array of CProb variables: #define INIT_PROBS(p) \ { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; } The DecodeBit() function decodes one bit. The LZMA decoder provides the pointer to CProb variable that contains information about estimated probability for symbol 0 and the Range Decoder updates that CProb variable after decoding. The Range Decoder increases estimated probability of the symbol that was decoded: #define kNumMoveBits 5 unsigned CRangeDecoder::DecodeBit(CProb *prob) { unsigned v = *prob; UInt32 bound = (Range >> kNumBitModelTotalBits) * v; unsigned symbol; if (Code < bound) { v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits; Range = bound; symbol = 0; } else { v -= v >> kNumMoveBits; Code -= bound; Range -= bound; symbol = 1; } *prob = (CProb)v; Normalize(); return symbol; } The Binary Tree of bit model counters ------------------------------------- LZMA uses a tree of Bit model variables to decode symbol that needs several bits for storing. There are two versions of such trees in LZMA: 1) the tree that decodes bits from high bit to low bit (the normal scheme). 2) the tree that decodes bits from low bit to high bit (the reverse scheme). Each binary tree structure supports different size of decoded symbol (the size of binary sequence that contains value of symbol). If that size of decoded symbol is "NumBits" bits, the tree structure uses the array of (2 << NumBits) counters of CProb type. But only ((2 << NumBits) - 1) items are used by encoder and decoder. The first item (the item with index equal to 0) in array is unused. That scheme with unused array's item allows to simplify the code. unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc) { unsigned m = 1; unsigned symbol = 0; for (unsigned i = 0; i < numBits; i++) { unsigned bit = rc->DecodeBit(&probs[m]); m <<= 1; m += bit; symbol |= (bit << i); } return symbol; } template class CBitTreeDecoder { CProb Probs[(unsigned)1 << NumBits]; public: void Init() { INIT_PROBS(Probs); } unsigned Decode(CRangeDecoder *rc) { unsigned m = 1; for (unsigned i = 0; i < NumBits; i++) m = (m << 1) + rc->DecodeBit(&Probs[m]); return m - ((unsigned)1 << NumBits); } unsigned ReverseDecode(CRangeDecoder *rc) { return BitTreeReverseDecode(Probs, NumBits, rc); } }; LZ part of LZMA --------------- LZ part of LZMA describes details about the decoding of MATCHES and LITERALS. The Literal Decoding -------------------- The LZMA Decoder uses (1 << (lc + lp)) tables with CProb values, where each table contains 0x300 CProb values: CProb *LitProbs; void CreateLiterals() { LitProbs = new CProb[(UInt32)0x300 << (lc + lp)]; } void InitLiterals() { UInt32 num = (UInt32)0x300 << (lc + lp); for (UInt32 i = 0; i < num; i++) LitProbs[i] = PROB_INIT_VAL; } To select the table for decoding it uses the context that consists of (lc) high bits from previous literal and (lp) low bits from value that represents current position in outputStream. If (State > 7), the Literal Decoder also uses "matchByte" that represents the byte in OutputStream at position the is the DISTANCE bytes before current position, where the DISTANCE is the distance in DISTANCE-LENGTH pair of latest decoded match. The following code decodes one literal and puts it to Sliding Window buffer: void DecodeLiteral(unsigned state, UInt32 rep0) { unsigned prevByte = 0; if (!OutWindow.IsEmpty()) prevByte = OutWindow.GetByte(1); unsigned symbol = 1; unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc)); CProb *probs = &LitProbs[(UInt32)0x300 * litState]; if (state >= 7) { unsigned matchByte = OutWindow.GetByte(rep0 + 1); do { unsigned matchBit = (matchByte >> 7) & 1; matchByte <<= 1; unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]); symbol = (symbol << 1) | bit; if (matchBit != bit) break; } while (symbol < 0x100); } while (symbol < 0x100) symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]); OutWindow.PutByte((Byte)(symbol - 0x100)); } The match length decoding ------------------------- The match length decoder returns normalized (zero-based value) length of match. That value can be converted to real length of the match with the following code: #define kMatchMinLen 2 matchLen = len + kMatchMinLen; The match length decoder can return the values from 0 to 271. And the corresponded real match length values can be in the range from 2 to 273. The following scheme is used for the match length encoding: Binary encoding Binary Tree structure Zero-based match length sequence (binary + decimal): 0 xxx LowCoder[posState] xxx 1 0 yyy MidCoder[posState] yyy + 8 1 1 zzzzzzzz HighCoder zzzzzzzz + 16 LZMA uses bit model variable "Choice" to decode the first selection bit. If the first selection bit is equal to 0, the decoder uses binary tree LowCoder[posState] to decode 3-bit zero-based match length (xxx). If the first selection bit is equal to 1, the decoder uses bit model variable "Choice2" to decode the second selection bit. If the second selection bit is equal to 0, the decoder uses binary tree MidCoder[posState] to decode 3-bit "yyy" value, and zero-based match length is equal to (yyy + 8). If the second selection bit is equal to 1, the decoder uses binary tree HighCoder to decode 8-bit "zzzzzzzz" value, and zero-based match length is equal to (zzzzzzzz + 16). LZMA uses "posState" value as context to select the binary tree from LowCoder and MidCoder binary tree arrays: unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); The full code of the length decoder: class CLenDecoder { CProb Choice; CProb Choice2; CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax]; CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax]; CBitTreeDecoder<8> HighCoder; public: void Init() { Choice = PROB_INIT_VAL; Choice2 = PROB_INIT_VAL; HighCoder.Init(); for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++) { LowCoder[i].Init(); MidCoder[i].Init(); } } unsigned Decode(CRangeDecoder *rc, unsigned posState) { if (rc->DecodeBit(&Choice) == 0) return LowCoder[posState].Decode(rc); if (rc->DecodeBit(&Choice2) == 0) return 8 + MidCoder[posState].Decode(rc); return 16 + HighCoder.Decode(rc); } }; The LZMA decoder uses two instances of CLenDecoder class. The first instance is for the matches of "Simple Match" type, and the second instance is for the matches of "Rep Match" type: CLenDecoder LenDecoder; CLenDecoder RepLenDecoder; The match distance decoding --------------------------- LZMA supports dictionary sizes up to 4 GiB minus 1. The value of match distance (decoded by distance decoder) can be from 1 to 2^32. But the distance value that is equal to 2^32 is used to indicate the "End of stream" marker. So real largest match distance that is used for LZ-window match is (2^32 - 1). LZMA uses normalized match length (zero-based length) to calculate the context state "lenState" do decode the distance value: #define kNumLenToPosStates 4 unsigned lenState = len; if (lenState > kNumLenToPosStates - 1) lenState = kNumLenToPosStates - 1; The distance decoder returns the "dist" value that is zero-based value of match distance. The real match distance can be calculated with the following code: matchDistance = dist + 1; The state of the distance decoder and the initialization code: #define kEndPosModelIndex 14 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #define kNumAlignBits 4 CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates]; CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex]; CBitTreeDecoder AlignDecoder; void InitDist() { for (unsigned i = 0; i < kNumLenToPosStates; i++) PosSlotDecoder[i].Init(); AlignDecoder.Init(); INIT_PROBS(PosDecoders); } At first stage the distance decoder decodes 6-bit "posSlot" value with bit tree decoder from PosSlotDecoder array. It's possible to get 2^6=64 different "posSlot" values. unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); The encoding scheme for distance value is shown in the following table: posSlot (decimal) / zero-based distance (binary) 0 0 1 1 2 10 3 11 4 10 x 5 11 x 6 10 xx 7 11 xx 8 10 xxx 9 11 xxx 10 10 xxxx 11 11 xxxx 12 10 xxxxx 13 11 xxxxx 14 10 yy zzzz 15 11 yy zzzz 16 10 yyy zzzz 17 11 yyy zzzz ... 62 10 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz 63 11 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz where "x ... x" means the sequence of binary symbols encoded with binary tree and "Reverse" scheme. It uses separated binary tree for each posSlot from 4 to 13. "y" means direct bit encoded with range coder. "zzzz" means the sequence of four binary symbols encoded with binary tree with "Reverse" scheme, where one common binary tree "AlignDecoder" is used for all posSlot values. If (posSlot < 4), the "dist" value is equal to posSlot value. If (posSlot >= 4), the decoder uses "posSlot" value to calculate the value of the high bits of "dist" value and the number of the low bits. If (4 <= posSlot < kEndPosModelIndex), the decoder uses bit tree decoders. (one separated bit tree decoder per one posSlot value) and "Reverse" scheme. In this implementation we use one CProb array "PosDecoders" that contains all CProb variables for all these bit decoders. if (posSlot >= kEndPosModelIndex), the middle bits are decoded as direct bits from RangeDecoder and the low 4 bits are decoded with a bit tree decoder "AlignDecoder" with "Reverse" scheme. The code to decode zero-based match distance: unsigned DecodeDistance(unsigned len) { unsigned lenState = len; if (lenState > kNumLenToPosStates - 1) lenState = kNumLenToPosStates - 1; unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); if (posSlot < 4) return posSlot; unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1); UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec); else { dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits; dist += AlignDecoder.ReverseDecode(&RangeDec); } return dist; } LZMA Decoding modes ------------------- There are 2 types of LZMA streams: 1) The stream with "End of stream" marker. 2) The stream without "End of stream" marker. And the LZMA Decoder supports 3 modes of decoding: 1) The unpack size is undefined. The LZMA decoder stops decoding after getting "End of stream" marker. The input variables for that case: markerIsMandatory = true unpackSizeDefined = false unpackSize contains any value 2) The unpack size is defined and LZMA decoder supports both variants, where the stream can contain "End of stream" marker or the stream is finished without "End of stream" marker. The LZMA decoder must detect any of these situations. The input variables for that case: markerIsMandatory = false unpackSizeDefined = true unpackSize contains unpack size 3) The unpack size is defined and the LZMA stream must contain "End of stream" marker The input variables for that case: markerIsMandatory = true unpackSizeDefined = true unpackSize contains unpack size The main loop of decoder ------------------------ The main loop of LZMA decoder: Initialize the LZMA state. loop { // begin of loop Check "end of stream" conditions. Decode Type of MATCH / LITERAL. If it's LITERAL, decode LITERAL value and put the LITERAL to Window. If it's MATCH, decode the length of match and the match distance. Check error conditions, check end of stream conditions and copy the sequence of match bytes from sliding window to current position in window. Go to begin of loop } The reference implementation of LZMA decoder uses "unpackSize" variable to keep the number of remaining bytes in output stream. So it reduces "unpackSize" value after each decoded LITERAL or MATCH. The following code contains the "end of stream" condition check at the start of the loop: if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory) if (RangeDec.IsFinishedOK()) return LZMA_RES_FINISHED_WITHOUT_MARKER; LZMA uses three types of matches: 1) "Simple Match" - the match with distance value encoded with bit models. 2) "Rep Match" - the match that uses the distance from distance history table. 3) "Short Rep Match" - the match of single byte length, that uses the latest distance from distance history table. The LZMA decoder keeps the history of latest 4 match distances that were used by decoder. That set of 4 variables contains zero-based match distances and these variables are initialized with zero values: UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; The LZMA decoder uses binary model variables to select type of MATCH or LITERAL: #define kNumStates 12 #define kNumPosBitsMax 4 CProb IsMatch[kNumStates << kNumPosBitsMax]; CProb IsRep[kNumStates]; CProb IsRepG0[kNumStates]; CProb IsRepG1[kNumStates]; CProb IsRepG2[kNumStates]; CProb IsRep0Long[kNumStates << kNumPosBitsMax]; The decoder uses "state" variable value to select exact variable from "IsRep", "IsRepG0", "IsRepG1" and "IsRepG2" arrays. The "state" variable can get the value from 0 to 11. Initial value for "state" variable is zero: unsigned state = 0; The "state" variable is updated after each LITERAL or MATCH with one of the following functions: unsigned UpdateState_Literal(unsigned state) { if (state < 4) return 0; else if (state < 10) return state - 3; else return state - 6; } unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; } unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; } unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; } The decoder calculates "state2" variable value to select exact variable from "IsMatch" and "IsRep0Long" arrays: unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); unsigned state2 = (state << kNumPosBitsMax) + posState; The decoder uses the following code flow scheme to select exact type of LITERAL or MATCH: IsMatch[state2] decode 0 - the Literal 1 - the Match IsRep[state] decode 0 - Simple Match 1 - Rep Match IsRepG0[state] decode 0 - the distance is rep0 IsRep0Long[state2] decode 0 - Short Rep Match 1 - Rep Match 0 1 - IsRepG1[state] decode 0 - Rep Match 1 1 - IsRepG2[state] decode 0 - Rep Match 2 1 - Rep Match 3 LITERAL symbol -------------- If the value "0" was decoded with IsMatch[state2] decoding, we have "LITERAL" type. At first the LZMA decoder must check that it doesn't exceed specified uncompressed size: if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; Then it decodes literal value and puts it to sliding window: DecodeLiteral(state, rep0); Then the decoder must update the "state" value and "unpackSize" value; state = UpdateState_Literal(state); unpackSize--; Then the decoder must go to the begin of main loop to decode next Match or Literal. Simple Match ------------ If the value "1" was decoded with IsMatch[state2] decoding, we have the "Simple Match" type. The distance history table is updated with the following scheme: rep3 = rep2; rep2 = rep1; rep1 = rep0; The zero-based length is decoded with "LenDecoder": len = LenDecoder.Decode(&RangeDec, posState); The state is update with UpdateState_Match function: state = UpdateState_Match(state); and the new "rep0" value is decoded with DecodeDistance: rep0 = DecodeDistance(len); That "rep0" will be used as zero-based distance for current match. If the value of "rep0" is equal to 0xFFFFFFFF, it means that we have "End of stream" marker, so we can stop decoding and check finishing condition in Range Decoder: if (rep0 == 0xFFFFFFFF) return RangeDec.IsFinishedOK() ? LZMA_RES_FINISHED_WITH_MARKER : LZMA_RES_ERROR; If uncompressed size is defined, LZMA decoder must check that it doesn't exceed that specified uncompressed size: if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; Also the decoder must check that "rep0" value is not larger than dictionary size and is not larger than the number of already decoded bytes: if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0)) return LZMA_RES_ERROR; Then the decoder must copy match bytes as described in "The match symbols copying" section. Rep Match --------- If the LZMA decoder has decoded the value "1" with IsRep[state] variable, we have "Rep Match" type. At first the LZMA decoder must check that it doesn't exceed specified uncompressed size: if (unpackSizeDefined && unpackSize == 0) return LZMA_RES_ERROR; Also the decoder must return error, if the LZ window is empty: if (OutWindow.IsEmpty()) return LZMA_RES_ERROR; If the match type is "Rep Match", the decoder uses one of the 4 variables of distance history table to get the value of distance for current match. And there are 4 corresponding ways of decoding flow. The decoder updates the distance history with the following scheme depending from type of match: - "Rep Match 0" or "Short Rep Match": ; LZMA doesn't update the distance history - "Rep Match 1": UInt32 dist = rep1; rep1 = rep0; rep0 = dist; - "Rep Match 2": UInt32 dist = rep2; rep2 = rep1; rep1 = rep0; rep0 = dist; - "Rep Match 3": UInt32 dist = rep3; rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = dist; Then the decoder decodes exact subtype of "Rep Match" using "IsRepG0", "IsRep0Long", "IsRepG1", "IsRepG2". If the subtype is "Short Rep Match", the decoder updates the state, puts the one byte from window to current position in window and goes to next MATCH/LITERAL symbol (the begin of main loop): state = UpdateState_ShortRep(state); OutWindow.PutByte(OutWindow.GetByte(rep0 + 1)); unpackSize--; continue; In other cases (Rep Match 0/1/2/3), it decodes the zero-based length of match with "RepLenDecoder" decoder: len = RepLenDecoder.Decode(&RangeDec, posState); Then it updates the state: state = UpdateState_Rep(state); Then the decoder must copy match bytes as described in "The Match symbols copying" section. The match symbols copying ------------------------- If we have the match (Simple Match or Rep Match 0/1/2/3), the decoder must copy the sequence of bytes with calculated match distance and match length. If uncompressed size is defined, LZMA decoder must check that it doesn't exceed that specified uncompressed size: len += kMatchMinLen; bool isError = false; if (unpackSizeDefined && unpackSize < len) { len = (unsigned)unpackSize; isError = true; } OutWindow.CopyMatch(rep0 + 1, len); unpackSize -= len; if (isError) return LZMA_RES_ERROR; Then the decoder must go to the begin of main loop to decode next MATCH or LITERAL. NOTES ----- This specification doesn't describe the variant of decoder implementation that supports partial decoding. Such partial decoding case can require some changes in "end of stream" condition checks code. Also such code can use additional status codes, returned by decoder. This specification uses C++ code with templates to simplify describing. The optimized version of LZMA decoder doesn't need templates. Such optimized version can use just two arrays of CProb variables: 1) The dynamic array of CProb variables allocated for the Literal Decoder. 2) The one common array that contains all other CProb variables. References: 1. G. N. N. Martin, Range encoding: an algorithm for removing redundancy from a digitized message, Video & Data Recording Conference, Southampton, UK, July 24-27, 1979. tmp41wklro_/DOC/lzma.txt0000644000175000001440000002567214634255240016275 0ustar nabijaczleweliusersLZMA compression ---------------- Version: 24.07 This file describes LZMA encoding and decoding functions written in C language. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. Note: you can read also LZMA Specification (lzma-specification.txt from LZMA SDK) Also you can look source code for LZMA encoding and decoding: C/Util/Lzma/LzmaUtil.c LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + 7zTypes.h + Precomp.h + Compiler.h Look example code: C/Util/Lzma/LzmaUtil.c Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); Look example code: C/Util/Lzma/LzmaUtil.c How To compress data -------------------- Compile files: 7zTypes.h Threads.h Threads.c LzmaEnc.h LzmaEnc.c LzFind.h LzFind.c LzFindMt.h LzFindMt.c LzFindOpt.c LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Look example code: C/Util/Lzma/LzmaUtil.c When to use: file->file compressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) Defines ------- Z7_LZMA_SIZE_OPT - Enable some code size optimizations in LZMA Decoder to get smaller executable code. Z7_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. Z7_DECL_Int32_AS_long - Define it if int is 16-bit on your compiler and long is 32-bit. Z7_DECL_SizeT_AS_unsigned_int - Define it if you don't want to use size_t type. Defines for 7z decoder written in C ----------------------------------- These defines are for 7zDec.c only (the decoder in C). C++ 7z decoder doesn't uses these macros. Z7_PPMD_SUPPORT - define it if you need PPMD method support. Z7_NO_METHODS_FILTERS - do not use filters (except of BCJ2 filter). Z7_USE_NATIVE_BRANCH_FILTER - use filter for native ISA: use x86 filter, if compiled to x86 executable, use arm64 filter, if compiled to arm64 executable. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for 7z archive handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator, if compiled by old MSVC compilers (MSVC before version VS 2010): operator new(size_t size) { void *p = ::malloc(size); if (!p) throw CNewException(); return p; } If the compiler is VS 2010 or newer, NewHandler.cpp doesn't redefine "new" operator. Sp if you use new compiler (VS 2010 or newer), you still can include "NewHandler.cpp" to compilation, and it will not redefine operator new. Also you can compile without "NewHandler.cpp" with new compilers. If 7-zip doesn't redefine operator "new", standard exception will be used instead of CNewException. Some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html tmp41wklro_/DOC/Methods.txt0000644000175000001440000000641714577270727016746 0ustar nabijaczleweliusers7-Zip method IDs for 7z and xz archives --------------------------------------- Version: 24.02 Date: 2024-03-22 Each compression or crypto method in 7z is associated with unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). xz and 7z formats use same ID map. If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-Zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID, if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 03 - Delta 04 - BCJ (x86) 05 - PPC (big-endian) 06 - IA64 07 - ARM (little-endian) 08 - ARMT (little-endian) 09 - SPARC 0A - ARM64 0B - RISCV 21 - LZMA2 02.. - Common 03 [Swap] - 2 Swap2 - 4 Swap4 03.. - 7z 01 - 01 - LZMA 03 - [Branch Codecs] 01 - [x86 Codecs] 03 - BCJ 1B - BCJ2 (4 packed streams) 02 - 05 - PPC (big-endian) 03 - 01 - Alpha 04 - 01 - IA64 05 - 01 - ARM (little-endian) 06 - 05 - M68 (big-endian) 07 - 01 - ARMT (little-endian) 08 - 05 - SPARC 04 - 01 - PPMD 7F - 01 - experimental method. 04.. - Misc codecs 00 - Reserved 01 - [Zip] 00 - Copy (not used. Use {00} instead) 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 0A - Imploding 0C - BZip2 (not used. Use {040202} instead) 0E - LZMA (LZMA-zip) 5D - ZSTD 5F - xz 60 - Jpeg 61 - WavPack 62 - PPMd (PPMd-zip) 63 - wzAES 02 - 02 - BZip2 03 - [Rar] 01 - Rar1 02 - Rar2 03 - Rar3 05 - Rar5 04 - [Arj] 01 - Arj(1,2,3) 02 - Arj4 05 - [Z] 06 - [Lzh] 07 - Reserved for 7z 08 - [Cab] 09 - [NSIS] 01 - DeflateNSIS 02 - BZip2NSIS F7 - External codecs (that are not included to 7-Zip) 0x xx - reserved 10 xx - reserved (LZHAM) 01 - LZHAM 11 xx - reserved (Tino Reichardt) 01 - ZSTD 02 - BROTLI 04 - LZ4 05 - LZ5 06 - LIZARD 12 xx - reserverd (Denis Anisimov) 01 - WavPack2 FE - eSplitter FF - RawSplitter 06.. - Crypto F0 - Ciphers without hashing algo 01 - [AES] 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB x4 - CTR F1 - Combine Ciphers 01 - [Zip] 01 - ZipCrypto (Main Zip crypto algo) 03 - [RAR] 02 - 03 - Rar29AES (AES-128 + modified SHA-1) 07 - [7z] 01 - 7zAES (AES-256 + SHA-256) --- End of document