diff options
Diffstat (limited to '')
223 files changed, 11244 insertions, 4282 deletions
diff --git a/Asm/x86/Sort.asm b/Asm/x86/Sort.asm new file mode 100644 index 0000000..517c615 --- /dev/null +++ b/Asm/x86/Sort.asm | |||
@@ -0,0 +1,860 @@ | |||
1 | ; SortTest.asm -- ASM version of HeapSort() function | ||
2 | ; Igor Pavlov : Public domain | ||
3 | |||
4 | include ../../../../Asm/x86/7zAsm.asm | ||
5 | |||
6 | MY_ASM_START | ||
7 | |||
8 | ifndef Z7_SORT_ASM_USE_SEGMENT | ||
9 | if (IS_LINUX gt 0) | ||
10 | ; Z7_SORT_ASM_USE_SEGMENT equ 1 | ||
11 | else | ||
12 | ; Z7_SORT_ASM_USE_SEGMENT equ 1 | ||
13 | endif | ||
14 | endif | ||
15 | |||
16 | ifdef Z7_SORT_ASM_USE_SEGMENT | ||
17 | _TEXT$Z7_SORT SEGMENT ALIGN(64) 'CODE' | ||
18 | MY_ALIGN macro num:req | ||
19 | align num | ||
20 | endm | ||
21 | else | ||
22 | MY_ALIGN macro num:req | ||
23 | ; We expect that ".text" is aligned for 16-bytes. | ||
24 | ; So we don't need large alignment inside our function. | ||
25 | align 16 | ||
26 | endm | ||
27 | endif | ||
28 | |||
29 | |||
30 | MY_ALIGN_16 macro | ||
31 | MY_ALIGN 16 | ||
32 | endm | ||
33 | |||
34 | MY_ALIGN_32 macro | ||
35 | MY_ALIGN 32 | ||
36 | endm | ||
37 | |||
38 | MY_ALIGN_64 macro | ||
39 | MY_ALIGN 64 | ||
40 | endm | ||
41 | |||
42 | ifdef x64 | ||
43 | |||
44 | NUM_PREFETCH_LEVELS equ 3 ; to prefetch 1x 64-bytes line (is good for most cases) | ||
45 | ; NUM_PREFETCH_LEVELS equ 4 ; to prefetch 2x 64-bytes lines (better for big arrays) | ||
46 | |||
47 | acc equ x0 | ||
48 | k equ r0 | ||
49 | k_x equ x0 | ||
50 | |||
51 | p equ r1 | ||
52 | |||
53 | s equ r2 | ||
54 | s_x equ x2 | ||
55 | |||
56 | a0 equ x3 | ||
57 | t0 equ a0 | ||
58 | |||
59 | a3 equ x5 | ||
60 | qq equ a3 | ||
61 | |||
62 | a1 equ x6 | ||
63 | t1 equ a1 | ||
64 | t1_r equ r6 | ||
65 | |||
66 | a2 equ x7 | ||
67 | t2 equ a2 | ||
68 | |||
69 | i equ r8 | ||
70 | e0 equ x8 | ||
71 | |||
72 | e1 equ x9 | ||
73 | |||
74 | num_last equ r10 | ||
75 | num_last_x equ x10 | ||
76 | |||
77 | next4_lim equ r11 | ||
78 | pref_lim equ r12 | ||
79 | |||
80 | |||
81 | |||
82 | SORT_2_WITH_TEMP_REG macro b0, b1, temp_reg | ||
83 | mov temp_reg, b0 | ||
84 | cmp b0, b1 | ||
85 | cmovae b0, b1 ; min | ||
86 | cmovae b1, temp_reg ; max | ||
87 | endm | ||
88 | |||
89 | SORT macro b0, b1 | ||
90 | SORT_2_WITH_TEMP_REG b0, b1, acc | ||
91 | endm | ||
92 | |||
93 | LOAD macro dest:req, index:req | ||
94 | mov dest, [p + 4 * index] | ||
95 | endm | ||
96 | |||
97 | STORE macro reg:req, index:req | ||
98 | mov [p + 4 * index], reg | ||
99 | endm | ||
100 | |||
101 | |||
102 | if (NUM_PREFETCH_LEVELS gt 3) | ||
103 | num_prefetches equ (1 SHL (NUM_PREFETCH_LEVELS - 3)) | ||
104 | else | ||
105 | num_prefetches equ 1 | ||
106 | endif | ||
107 | |||
108 | PREFETCH_OP macro offs | ||
109 | cur_offset = 7 * 4 ; it's average offset in 64-bytes cache line. | ||
110 | ; cur_offset = 0 ; we can use zero offset, if we are sure that array is aligned for 64-bytes. | ||
111 | rept num_prefetches | ||
112 | if 1 | ||
113 | prefetcht0 byte ptr [p + offs + cur_offset] | ||
114 | else | ||
115 | mov pref_x, dword ptr [p + offs + cur_offset] | ||
116 | endif | ||
117 | cur_offset = cur_offset + 64 | ||
118 | endm | ||
119 | endm | ||
120 | |||
121 | PREFETCH_MY macro | ||
122 | if 1 | ||
123 | if 1 | ||
124 | shl k, NUM_PREFETCH_LEVELS + 3 | ||
125 | else | ||
126 | ; we delay prefetch instruction to improve main loads | ||
127 | shl k, NUM_PREFETCH_LEVELS | ||
128 | shl k, 3 | ||
129 | ; shl k, 0 | ||
130 | endif | ||
131 | PREFETCH_OP k | ||
132 | elseif 1 | ||
133 | shl k, 3 | ||
134 | PREFETCH_OP k * (1 SHL NUM_PREFETCH_LEVELS) ; change it | ||
135 | endif | ||
136 | endm | ||
137 | |||
138 | |||
139 | STEP_1 macro exit_label, prefetch_macro | ||
140 | use_cmov_1 equ 1 ; set 1 for cmov, but it's slower in some cases | ||
141 | ; set 0 for LOAD after adc s, 0 | ||
142 | cmp t0, t1 | ||
143 | if use_cmov_1 | ||
144 | cmovb t0, t1 | ||
145 | ; STORE t0, k | ||
146 | endif | ||
147 | adc s, 0 | ||
148 | if use_cmov_1 eq 0 | ||
149 | LOAD t0, s | ||
150 | endif | ||
151 | cmp qq, t0 | ||
152 | jae exit_label | ||
153 | if 1 ; use_cmov_1 eq 0 | ||
154 | STORE t0, k | ||
155 | endif | ||
156 | prefetch_macro | ||
157 | mov t0, [p + s * 8] | ||
158 | mov t1, [p + s * 8 + 4] | ||
159 | mov k, s | ||
160 | add s, s ; slower for some cpus | ||
161 | ; lea s, dword ptr [s + s] ; slower for some cpus | ||
162 | ; shl s, 1 ; faster for some cpus | ||
163 | ; lea s, dword ptr [s * 2] ; faster for some cpus | ||
164 | rept 0 ; 1000 for debug : 0 for normal | ||
165 | ; number of calls in generate_stage : ~0.6 of number of items | ||
166 | shl k, 0 | ||
167 | endm | ||
168 | endm | ||
169 | |||
170 | |||
171 | STEP_2 macro exit_label, prefetch_macro | ||
172 | use_cmov_2 equ 0 ; set 1 for cmov, but it's slower in some cases | ||
173 | ; set 0 for LOAD after adc s, 0 | ||
174 | cmp t0, t1 | ||
175 | if use_cmov_2 | ||
176 | mov t2, t0 | ||
177 | cmovb t2, t1 | ||
178 | ; STORE t2, k | ||
179 | endif | ||
180 | mov t0, [p + s * 8] | ||
181 | mov t1, [p + s * 8 + 4] | ||
182 | cmovb t0, [p + s * 8 + 8] | ||
183 | cmovb t1, [p + s * 8 + 12] | ||
184 | adc s, 0 | ||
185 | if use_cmov_2 eq 0 | ||
186 | LOAD t2, s | ||
187 | endif | ||
188 | cmp qq, t2 | ||
189 | jae exit_label | ||
190 | if 1 ; use_cmov_2 eq 0 | ||
191 | STORE t2, k | ||
192 | endif | ||
193 | prefetch_macro | ||
194 | mov k, s | ||
195 | ; add s, s | ||
196 | ; lea s, [s + s] | ||
197 | shl s, 1 | ||
198 | ; lea s, [s * 2] | ||
199 | endm | ||
200 | |||
201 | |||
202 | MOVE_SMALLEST_UP macro STEP, use_prefetch, num_unrolls | ||
203 | LOCAL exit_1, exit_2, leaves, opt_loop, last_nodes | ||
204 | |||
205 | ; s == k * 2 | ||
206 | ; t0 == (p)[s] | ||
207 | ; t1 == (p)[s + 1] | ||
208 | cmp k, next4_lim | ||
209 | jae leaves | ||
210 | |||
211 | rept num_unrolls | ||
212 | STEP exit_2 | ||
213 | cmp k, next4_lim | ||
214 | jae leaves | ||
215 | endm | ||
216 | |||
217 | if use_prefetch | ||
218 | prefetch_macro equ PREFETCH_MY | ||
219 | pref_lim_2 equ pref_lim | ||
220 | ; lea pref_lim, dword ptr [num_last + 1] | ||
221 | ; shr pref_lim, NUM_PREFETCH_LEVELS + 1 | ||
222 | cmp k, pref_lim_2 | ||
223 | jae last_nodes | ||
224 | else | ||
225 | prefetch_macro equ | ||
226 | pref_lim_2 equ next4_lim | ||
227 | endif | ||
228 | |||
229 | MY_ALIGN_16 | ||
230 | opt_loop: | ||
231 | STEP exit_2, prefetch_macro | ||
232 | cmp k, pref_lim_2 | ||
233 | jb opt_loop | ||
234 | |||
235 | last_nodes: | ||
236 | ; k >= pref_lim_2 | ||
237 | ; 2 cases are possible: | ||
238 | ; case-1: num_after_prefetch_levels == 0 && next4_lim = pref_lim_2 | ||
239 | ; case-2: num_after_prefetch_levels == NUM_PREFETCH_LEVELS - 1 && | ||
240 | ; next4_lim = pref_lim_2 / (NUM_PREFETCH_LEVELS - 1) | ||
241 | if use_prefetch | ||
242 | yyy = NUM_PREFETCH_LEVELS - 1 | ||
243 | while yyy | ||
244 | yyy = yyy - 1 | ||
245 | STEP exit_2 | ||
246 | if yyy | ||
247 | cmp k, next4_lim | ||
248 | jae leaves | ||
249 | endif | ||
250 | endm | ||
251 | endif | ||
252 | |||
253 | leaves: | ||
254 | ; k >= next4_lim == (num_last + 1) / 4 must be provided by previous code. | ||
255 | ; we have 2 nodes in (s) level : always | ||
256 | ; we can have some nodes in (s * 2) level : low probability case | ||
257 | ; we have no nodes in (s * 4) level | ||
258 | ; s == k * 2 | ||
259 | ; t0 == (p)[s] | ||
260 | ; t1 == (p)[s + 1] | ||
261 | cmp t0, t1 | ||
262 | cmovb t0, t1 | ||
263 | adc s, 0 | ||
264 | STORE t0, k | ||
265 | |||
266 | ; t0 == (p)[s] | ||
267 | ; s / 2 == k : (s) is index of max item from (p)[k * 2], (p)[k * 2 + 1] | ||
268 | ; we have 3 possible cases here: | ||
269 | ; s * 2 > num_last : (s) node has no childs | ||
270 | ; s * 2 == num_last : (s) node has 1 leaf child that is last item of array | ||
271 | ; s * 2 < num_last : (s) node has 2 leaf childs. We provide (s * 4 > num_last) | ||
272 | ; we check for (s * 2 > num_last) before "cmp qq, t0" check, because | ||
273 | ; we will replace conditional jump with cmov instruction later. | ||
274 | lea t1_r, dword ptr [s + s] | ||
275 | cmp t1_r, num_last | ||
276 | ja exit_1 ; if (s * 2 > num_last), we have no childs : it's high probability branch | ||
277 | |||
278 | ; it's low probability branch | ||
279 | ; s * 2 <= num_last | ||
280 | cmp qq, t0 | ||
281 | jae exit_2 | ||
282 | |||
283 | ; qq < t0, so we go to next level | ||
284 | ; we check 1 or 2 childs in next level | ||
285 | mov t0, [p + s * 8] | ||
286 | mov k, s | ||
287 | mov s, t1_r | ||
288 | cmp t1_r, num_last | ||
289 | je @F ; (s == num_last) means that we have single child in tree | ||
290 | |||
291 | ; (s < num_last) : so we must read both childs and select max of them. | ||
292 | mov t1, [p + k * 8 + 4] | ||
293 | cmp t0, t1 | ||
294 | cmovb t0, t1 | ||
295 | adc s, 0 | ||
296 | @@: | ||
297 | STORE t0, k | ||
298 | exit_1: | ||
299 | ; t0 == (p)[s], s / 2 == k : (s) is index of max item from (p)[k * 2], (p)[k * 2 + 1] | ||
300 | cmp qq, t0 | ||
301 | cmovb k, s | ||
302 | exit_2: | ||
303 | STORE qq, k | ||
304 | endm | ||
305 | |||
306 | |||
307 | |||
308 | |||
309 | ifdef Z7_SORT_ASM_USE_SEGMENT | ||
310 | ; MY_ALIGN_64 | ||
311 | else | ||
312 | MY_ALIGN_16 | ||
313 | endif | ||
314 | |||
315 | MY_PROC HeapSort, 2 | ||
316 | |||
317 | if (IS_LINUX gt 0) | ||
318 | mov p, REG_ABI_PARAM_0 ; r1 <- r7 : linux | ||
319 | endif | ||
320 | mov num_last, REG_ABI_PARAM_1 ; r10 <- r6 : linux | ||
321 | ; r10 <- r2 : win64 | ||
322 | cmp num_last, 2 | ||
323 | jb end_1 | ||
324 | |||
325 | ; MY_PUSH_PRESERVED_ABI_REGS | ||
326 | MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 | ||
327 | push r12 | ||
328 | |||
329 | cmp num_last, 4 | ||
330 | ja sort_5 | ||
331 | |||
332 | LOAD a0, 0 | ||
333 | LOAD a1, 1 | ||
334 | SORT a0, a1 | ||
335 | cmp num_last, 3 | ||
336 | jb end_2 | ||
337 | |||
338 | LOAD a2, 2 | ||
339 | je sort_3 | ||
340 | |||
341 | LOAD a3, 3 | ||
342 | SORT a2, a3 | ||
343 | SORT a1, a3 | ||
344 | STORE a3, 3 | ||
345 | sort_3: | ||
346 | SORT a0, a2 | ||
347 | SORT a1, a2 | ||
348 | STORE a2, 2 | ||
349 | jmp end_2 | ||
350 | |||
351 | sort_5: | ||
352 | ; (num_last > 4) is required here | ||
353 | ; if (num_last >= 6) : we will use optimized loop for leaf nodes loop_down_1 | ||
354 | mov next4_lim, num_last | ||
355 | shr next4_lim, 2 | ||
356 | |||
357 | dec num_last | ||
358 | mov k, num_last | ||
359 | shr k, 1 | ||
360 | mov i, num_last | ||
361 | shr i, 2 | ||
362 | test num_last, 1 | ||
363 | jnz size_even | ||
364 | |||
365 | ; ODD number of items. So we compare parent with single child | ||
366 | LOAD t1, num_last | ||
367 | LOAD t0, k | ||
368 | SORT_2_WITH_TEMP_REG t1, t0, t2 | ||
369 | STORE t1, num_last | ||
370 | STORE t0, k | ||
371 | dec k | ||
372 | |||
373 | size_even: | ||
374 | cmp k, i | ||
375 | jbe loop_down ; jump for num_last == 4 case | ||
376 | |||
377 | if 0 ; 1 for debug | ||
378 | mov r15, k | ||
379 | mov r14d, 1 ; 100 | ||
380 | loop_benchmark: | ||
381 | endif | ||
382 | ; optimized loop for leaf nodes: | ||
383 | mov t0, [p + k * 8] | ||
384 | mov t1, [p + k * 8 + 4] | ||
385 | |||
386 | MY_ALIGN_16 | ||
387 | loop_down_1: | ||
388 | ; we compare parent with max of childs: | ||
389 | ; lea s, dword ptr [2 * k] | ||
390 | mov s, k | ||
391 | cmp t0, t1 | ||
392 | cmovb t0, t1 | ||
393 | adc s, s | ||
394 | LOAD t2, k | ||
395 | STORE t0, k | ||
396 | cmp t2, t0 | ||
397 | cmovae s, k | ||
398 | dec k | ||
399 | ; we preload next items before STORE operation for calculated address | ||
400 | mov t0, [p + k * 8] | ||
401 | mov t1, [p + k * 8 + 4] | ||
402 | STORE t2, s | ||
403 | cmp k, i | ||
404 | jne loop_down_1 | ||
405 | |||
406 | if 0 ; 1 for debug | ||
407 | mov k, r15 | ||
408 | dec r14d | ||
409 | jnz loop_benchmark | ||
410 | ; jmp end_debug | ||
411 | endif | ||
412 | |||
413 | MY_ALIGN_16 | ||
414 | loop_down: | ||
415 | mov t0, [p + i * 8] | ||
416 | mov t1, [p + i * 8 + 4] | ||
417 | LOAD qq, i | ||
418 | mov k, i | ||
419 | lea s, dword ptr [i + i] | ||
420 | ; jmp end_debug | ||
421 | DOWN_use_prefetch equ 0 | ||
422 | DOWN_num_unrolls equ 0 | ||
423 | MOVE_SMALLEST_UP STEP_1, DOWN_use_prefetch, DOWN_num_unrolls | ||
424 | sub i, 1 | ||
425 | jnb loop_down | ||
426 | |||
427 | ; jmp end_debug | ||
428 | LOAD e0, 0 | ||
429 | LOAD e1, 1 | ||
430 | |||
431 | LEVEL_3_LIMIT equ 8 ; 8 is default, but 7 also can work | ||
432 | |||
433 | cmp num_last, LEVEL_3_LIMIT + 1 | ||
434 | jb main_loop_sort_5 | ||
435 | |||
436 | MY_ALIGN_16 | ||
437 | main_loop_sort: | ||
438 | ; num_last > LEVEL_3_LIMIT | ||
439 | ; p[size--] = p[0]; | ||
440 | LOAD qq, num_last | ||
441 | STORE e0, num_last | ||
442 | mov e0, e1 | ||
443 | |||
444 | mov next4_lim, num_last | ||
445 | shr next4_lim, 2 | ||
446 | mov pref_lim, num_last | ||
447 | shr pref_lim, NUM_PREFETCH_LEVELS + 1 | ||
448 | |||
449 | dec num_last | ||
450 | if 0 ; 1 for debug | ||
451 | ; that optional optimization can improve the performance, if there are identical items in array | ||
452 | ; 3 times improvement : if all items in array are identical | ||
453 | ; 20% improvement : if items are different for 1 bit only | ||
454 | ; 1-10% improvement : if items are different for (2+) bits | ||
455 | ; no gain : if items are different | ||
456 | cmp qq, e1 | ||
457 | jae next_iter_main | ||
458 | endif | ||
459 | LOAD e1, 2 | ||
460 | LOAD t0, 3 | ||
461 | mov k_x, 2 | ||
462 | cmp e1, t0 | ||
463 | cmovb e1, t0 | ||
464 | mov t0, [p + 4 * (4 + 0)] | ||
465 | mov t1, [p + 4 * (4 + 1)] | ||
466 | cmovb t0, [p + 4 * (4 + 2)] | ||
467 | cmovb t1, [p + 4 * (4 + 3)] | ||
468 | adc k_x, 0 | ||
469 | ; (qq <= e1), because the tree is correctly sorted | ||
470 | ; also here we could check (qq >= e1) or (qq == e1) for faster exit | ||
471 | lea s, dword ptr [k + k] | ||
472 | MAIN_use_prefetch equ 1 | ||
473 | MAIN_num_unrolls equ 0 | ||
474 | MOVE_SMALLEST_UP STEP_2, MAIN_use_prefetch, MAIN_num_unrolls | ||
475 | |||
476 | next_iter_main: | ||
477 | cmp num_last, LEVEL_3_LIMIT | ||
478 | jne main_loop_sort | ||
479 | |||
480 | ; num_last == LEVEL_3_LIMIT | ||
481 | main_loop_sort_5: | ||
482 | ; 4 <= num_last <= LEVEL_3_LIMIT | ||
483 | ; p[size--] = p[0]; | ||
484 | LOAD qq, num_last | ||
485 | STORE e0, num_last | ||
486 | mov e0, e1 | ||
487 | dec num_last_x | ||
488 | |||
489 | LOAD e1, 2 | ||
490 | LOAD t0, 3 | ||
491 | mov k_x, 2 | ||
492 | cmp e1, t0 | ||
493 | cmovb e1, t0 | ||
494 | adc k_x, 0 | ||
495 | |||
496 | lea s_x, dword ptr [k * 2] | ||
497 | cmp s_x, num_last_x | ||
498 | ja exit_2 | ||
499 | |||
500 | mov t0, [p + k * 8] | ||
501 | je exit_1 | ||
502 | |||
503 | ; s < num_last | ||
504 | mov t1, [p + k * 8 + 4] | ||
505 | cmp t0, t1 | ||
506 | cmovb t0, t1 | ||
507 | adc s_x, 0 | ||
508 | exit_1: | ||
509 | STORE t0, k | ||
510 | cmp qq, t0 | ||
511 | cmovb k_x, s_x | ||
512 | exit_2: | ||
513 | STORE qq, k | ||
514 | cmp num_last_x, 3 | ||
515 | jne main_loop_sort_5 | ||
516 | |||
517 | ; num_last == 3 (real_size == 4) | ||
518 | LOAD a0, 2 | ||
519 | LOAD a1, 3 | ||
520 | STORE e1, 2 | ||
521 | STORE e0, 3 | ||
522 | SORT a0, a1 | ||
523 | end_2: | ||
524 | STORE a0, 0 | ||
525 | STORE a1, 1 | ||
526 | ; end_debug: | ||
527 | ; MY_POP_PRESERVED_ABI_REGS | ||
528 | pop r12 | ||
529 | MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 | ||
530 | end_1: | ||
531 | MY_ENDP | ||
532 | |||
533 | |||
534 | |||
535 | else | ||
536 | ; ------------ x86 32-bit ------------ | ||
537 | |||
538 | ifdef x64 | ||
539 | IS_CDECL = 0 | ||
540 | endif | ||
541 | |||
542 | acc equ x0 | ||
543 | k equ r0 | ||
544 | k_x equ acc | ||
545 | |||
546 | p equ r1 | ||
547 | |||
548 | num_last equ r2 | ||
549 | num_last_x equ x2 | ||
550 | |||
551 | a0 equ x3 | ||
552 | t0 equ a0 | ||
553 | |||
554 | a3 equ x5 | ||
555 | i equ r5 | ||
556 | e0 equ a3 | ||
557 | |||
558 | a1 equ x6 | ||
559 | qq equ a1 | ||
560 | |||
561 | a2 equ x7 | ||
562 | s equ r7 | ||
563 | s_x equ a2 | ||
564 | |||
565 | |||
566 | SORT macro b0, b1 | ||
567 | cmp b1, b0 | ||
568 | jae @F | ||
569 | if 1 | ||
570 | xchg b0, b1 | ||
571 | else | ||
572 | mov acc, b0 | ||
573 | mov b0, b1 ; min | ||
574 | mov b1, acc ; max | ||
575 | endif | ||
576 | @@: | ||
577 | endm | ||
578 | |||
579 | LOAD macro dest:req, index:req | ||
580 | mov dest, [p + 4 * index] | ||
581 | endm | ||
582 | |||
583 | STORE macro reg:req, index:req | ||
584 | mov [p + 4 * index], reg | ||
585 | endm | ||
586 | |||
587 | |||
588 | STEP_1 macro exit_label | ||
589 | mov t0, [p + k * 8] | ||
590 | cmp t0, [p + k * 8 + 4] | ||
591 | adc s, 0 | ||
592 | LOAD t0, s | ||
593 | STORE t0, k ; we lookahed stooring for most expected branch | ||
594 | cmp qq, t0 | ||
595 | jae exit_label | ||
596 | ; STORE t0, k ; use if | ||
597 | mov k, s | ||
598 | add s, s | ||
599 | ; lea s, dword ptr [s + s] | ||
600 | ; shl s, 1 | ||
601 | ; lea s, dword ptr [s * 2] | ||
602 | endm | ||
603 | |||
604 | STEP_BRANCH macro exit_label | ||
605 | mov t0, [p + k * 8] | ||
606 | cmp t0, [p + k * 8 + 4] | ||
607 | jae @F | ||
608 | inc s | ||
609 | mov t0, [p + k * 8 + 4] | ||
610 | @@: | ||
611 | cmp qq, t0 | ||
612 | jae exit_label | ||
613 | STORE t0, k | ||
614 | mov k, s | ||
615 | add s, s | ||
616 | endm | ||
617 | |||
618 | |||
619 | |||
620 | MOVE_SMALLEST_UP macro STEP, num_unrolls, exit_2 | ||
621 | LOCAL leaves, opt_loop, single | ||
622 | |||
623 | ; s == k * 2 | ||
624 | rept num_unrolls | ||
625 | cmp s, num_last | ||
626 | jae leaves | ||
627 | STEP_1 exit_2 | ||
628 | endm | ||
629 | cmp s, num_last | ||
630 | jb opt_loop | ||
631 | |||
632 | leaves: | ||
633 | ; (s >= num_last) | ||
634 | jne exit_2 | ||
635 | single: | ||
636 | ; (s == num_last) | ||
637 | mov t0, [p + k * 8] | ||
638 | cmp qq, t0 | ||
639 | jae exit_2 | ||
640 | STORE t0, k | ||
641 | mov k, s | ||
642 | jmp exit_2 | ||
643 | |||
644 | MY_ALIGN_16 | ||
645 | opt_loop: | ||
646 | STEP exit_2 | ||
647 | cmp s, num_last | ||
648 | jb opt_loop | ||
649 | je single | ||
650 | exit_2: | ||
651 | STORE qq, k | ||
652 | endm | ||
653 | |||
654 | |||
655 | |||
656 | |||
657 | ifdef Z7_SORT_ASM_USE_SEGMENT | ||
658 | ; MY_ALIGN_64 | ||
659 | else | ||
660 | MY_ALIGN_16 | ||
661 | endif | ||
662 | |||
663 | MY_PROC HeapSort, 2 | ||
664 | ifdef x64 | ||
665 | if (IS_LINUX gt 0) | ||
666 | mov num_last, REG_ABI_PARAM_1 ; r2 <- r6 : linux | ||
667 | mov p, REG_ABI_PARAM_0 ; r1 <- r7 : linux | ||
668 | endif | ||
669 | elseif (IS_CDECL gt 0) | ||
670 | mov num_last, [r4 + REG_SIZE * 2] | ||
671 | mov p, [r4 + REG_SIZE * 1] | ||
672 | endif | ||
673 | cmp num_last, 2 | ||
674 | jb end_1 | ||
675 | MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 | ||
676 | |||
677 | cmp num_last, 4 | ||
678 | ja sort_5 | ||
679 | |||
680 | LOAD a0, 0 | ||
681 | LOAD a1, 1 | ||
682 | SORT a0, a1 | ||
683 | cmp num_last, 3 | ||
684 | jb end_2 | ||
685 | |||
686 | LOAD a2, 2 | ||
687 | je sort_3 | ||
688 | |||
689 | LOAD a3, 3 | ||
690 | SORT a2, a3 | ||
691 | SORT a1, a3 | ||
692 | STORE a3, 3 | ||
693 | sort_3: | ||
694 | SORT a0, a2 | ||
695 | SORT a1, a2 | ||
696 | STORE a2, 2 | ||
697 | jmp end_2 | ||
698 | |||
699 | sort_5: | ||
700 | ; num_last > 4 | ||
701 | lea i, dword ptr [num_last - 2] | ||
702 | dec num_last | ||
703 | test i, 1 | ||
704 | jz loop_down | ||
705 | |||
706 | ; single child | ||
707 | mov t0, [p + num_last * 4] | ||
708 | mov qq, [p + num_last * 2] | ||
709 | dec i | ||
710 | cmp qq, t0 | ||
711 | jae loop_down | ||
712 | |||
713 | mov [p + num_last * 2], t0 | ||
714 | mov [p + num_last * 4], qq | ||
715 | |||
716 | MY_ALIGN_16 | ||
717 | loop_down: | ||
718 | mov t0, [p + i * 4] | ||
719 | cmp t0, [p + i * 4 + 4] | ||
720 | mov k, i | ||
721 | mov qq, [p + i * 2] | ||
722 | adc k, 0 | ||
723 | LOAD t0, k | ||
724 | cmp qq, t0 | ||
725 | jae down_next | ||
726 | mov [p + i * 2], t0 | ||
727 | lea s, dword ptr [k + k] | ||
728 | |||
729 | DOWN_num_unrolls equ 0 | ||
730 | MOVE_SMALLEST_UP STEP_1, DOWN_num_unrolls, down_exit_label | ||
731 | down_next: | ||
732 | sub i, 2 | ||
733 | jnb loop_down | ||
734 | ; jmp end_debug | ||
735 | |||
736 | LOAD e0, 0 | ||
737 | |||
738 | MY_ALIGN_16 | ||
739 | main_loop_sort: | ||
740 | ; num_last > 3 | ||
741 | mov t0, [p + 2 * 4] | ||
742 | cmp t0, [p + 3 * 4] | ||
743 | LOAD qq, num_last | ||
744 | STORE e0, num_last | ||
745 | LOAD e0, 1 | ||
746 | mov s_x, 2 | ||
747 | mov k_x, 1 | ||
748 | adc s, 0 | ||
749 | LOAD t0, s | ||
750 | dec num_last | ||
751 | cmp qq, t0 | ||
752 | jae main_exit_label | ||
753 | STORE t0, 1 | ||
754 | mov k, s | ||
755 | add s, s | ||
756 | if 1 | ||
757 | ; for branch data prefetch mode : | ||
758 | ; it's faster for large arrays : larger than (1 << 13) items. | ||
759 | MAIN_num_unrolls equ 10 | ||
760 | STEP_LOOP equ STEP_BRANCH | ||
761 | else | ||
762 | MAIN_num_unrolls equ 0 | ||
763 | STEP_LOOP equ STEP_1 | ||
764 | endif | ||
765 | |||
766 | MOVE_SMALLEST_UP STEP_LOOP, MAIN_num_unrolls, main_exit_label | ||
767 | |||
768 | ; jmp end_debug | ||
769 | cmp num_last, 3 | ||
770 | jne main_loop_sort | ||
771 | |||
772 | ; num_last == 3 (real_size == 4) | ||
773 | LOAD a0, 2 | ||
774 | LOAD a1, 3 | ||
775 | LOAD a2, 1 | ||
776 | STORE e0, 3 ; e0 is alias for a3 | ||
777 | STORE a2, 2 | ||
778 | SORT a0, a1 | ||
779 | end_2: | ||
780 | STORE a0, 0 | ||
781 | STORE a1, 1 | ||
782 | ; end_debug: | ||
783 | MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 | ||
784 | end_1: | ||
785 | MY_ENDP | ||
786 | |||
787 | endif | ||
788 | |||
789 | ifdef Z7_SORT_ASM_USE_SEGMENT | ||
790 | _TEXT$Z7_SORT ENDS | ||
791 | endif | ||
792 | |||
793 | if 0 | ||
794 | LEA_IS_D8 (R64) [R2 * 4 + 16] | ||
795 | Lat : TP | ||
796 | 2 : 1 : adl-e | ||
797 | 2 : 3 p056 adl-p | ||
798 | 1 : 2 : p15 hsw-rocket | ||
799 | 1 : 2 : p01 snb-ivb | ||
800 | 1 : 1 : p1 conroe-wsm | ||
801 | 1 : 4 : zen3,zen4 | ||
802 | 2 : 4 : zen1,zen2 | ||
803 | |||
804 | LEA_B_IS (R64) [R2 + R3 * 4] | ||
805 | Lat : TP | ||
806 | 1 : 1 : adl-e | ||
807 | 2 : 3 p056 adl-p | ||
808 | 1 : 2 : p15 hsw-rocket | ||
809 | 1 : 2 : p01 snb-ivb | ||
810 | 1 : 1 : p1 nhm-wsm | ||
811 | 1 : 1 : p0 conroe-wsm | ||
812 | 1 : 4 : zen3,zen4 | ||
813 | 2 :2,4 : zen1,zen2 | ||
814 | |||
815 | LEA_B_IS_D8 (R64) [R2 + R3 * 4 + 16] | ||
816 | Lat : TP | ||
817 | 2 : 1 : adl-e | ||
818 | 2 : 3 p056 adl-p | ||
819 | 1 : 2 : p15 ice-rocket | ||
820 | 3 : 1 : p1/p15 hsw-rocket | ||
821 | 3 : 1 : p01 snb-ivb | ||
822 | 1 : 1 : p1 nhm-wsm | ||
823 | 1 : 1 : p0 conroe-wsm | ||
824 | 2,1 : 2 : zen3,zen4 | ||
825 | 2 : 2 : zen1,zen2 | ||
826 | |||
827 | CMOVB (R64, R64) | ||
828 | Lat : TP | ||
829 | 1,2 : 2 : adl-e | ||
830 | 1 : 2 p06 adl-p | ||
831 | 1 : 2 : p06 bwd-rocket | ||
832 | 1,2 : 2 : p0156+p06 hsw | ||
833 | 1,2 :1.5 : p015+p05 snb-ivb | ||
834 | 1,2 : 1 : p015+p05 nhm | ||
835 | 1 : 1 : 2*p015 conroe | ||
836 | 1 : 2 : zen3,zen4 | ||
837 | 1 : 4 : zen1,zen2 | ||
838 | |||
839 | ADC (R64, 0) | ||
840 | Lat : TP | ||
841 | 1,2 : 2 : adl-e | ||
842 | 1 : 2 p06 adl-p | ||
843 | 1 : 2 : p06 bwd-rocket | ||
844 | 1 :1.5 : p0156+p06 hsw | ||
845 | 1 :1.5 : p015+p05 snb-ivb | ||
846 | 2 : 1 : 2*p015 conroe-wstm | ||
847 | 1 : 2 : zen1,zen2,zen3,zen4 | ||
848 | |||
849 | PREFETCHNTA : fetch data into non-temporal cache close to the processor, minimizing cache pollution. | ||
850 | L1 : Pentium3 | ||
851 | L2 : NetBurst | ||
852 | L1, not L2: Core duo, Core 2, Atom processors | ||
853 | L1, not L2, may fetch into L3 with fast replacement: Nehalem, Westmere, Sandy Bridge, ... | ||
854 | NEHALEM: Fills L1/L3, L1 LRU is not updated | ||
855 | L3 with fast replacement: Xeon Processors based on Nehalem, Westmere, Sandy Bridge, ... | ||
856 | PREFETCHT0 : fetch data into all cache levels. | ||
857 | PREFETCHT1 : fetch data into L2 and L3 | ||
858 | endif | ||
859 | |||
860 | end | ||
@@ -1,5 +1,5 @@ | |||
1 | /* 7zDec.c -- Decoding from 7z folder | 1 | /* 7zDec.c -- Decoding from 7z folder |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -312,8 +312,9 @@ static BoolInt IS_MAIN_METHOD(UInt32 m) | |||
312 | case k_PPMD: | 312 | case k_PPMD: |
313 | #endif | 313 | #endif |
314 | return True; | 314 | return True; |
315 | default: | ||
316 | return False; | ||
315 | } | 317 | } |
316 | return False; | ||
317 | } | 318 | } |
318 | 319 | ||
319 | static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c) | 320 | static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c) |
diff --git a/C/7zVersion.h b/C/7zVersion.h index 1ddef80..b6142e9 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #define MY_VER_MAJOR 24 | 1 | #define MY_VER_MAJOR 25 |
2 | #define MY_VER_MINOR 8 | 2 | #define MY_VER_MINOR 1 |
3 | #define MY_VER_BUILD 0 | 3 | #define MY_VER_BUILD 0 |
4 | #define MY_VERSION_NUMBERS "24.08" | 4 | #define MY_VERSION_NUMBERS "25.01" |
5 | #define MY_VERSION MY_VERSION_NUMBERS | 5 | #define MY_VERSION MY_VERSION_NUMBERS |
6 | 6 | ||
7 | #ifdef MY_CPU_NAME | 7 | #ifdef MY_CPU_NAME |
@@ -10,12 +10,12 @@ | |||
10 | #define MY_VERSION_CPU MY_VERSION | 10 | #define MY_VERSION_CPU MY_VERSION |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #define MY_DATE "2024-08-11" | 13 | #define MY_DATE "2025-08-03" |
14 | #undef MY_COPYRIGHT | 14 | #undef MY_COPYRIGHT |
15 | #undef MY_VERSION_COPYRIGHT_DATE | 15 | #undef MY_VERSION_COPYRIGHT_DATE |
16 | #define MY_AUTHOR_NAME "Igor Pavlov" | 16 | #define MY_AUTHOR_NAME "Igor Pavlov" |
17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" | 17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" |
18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov" | 18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov" |
19 | 19 | ||
20 | #ifdef USE_COPYRIGHT_CR | 20 | #ifdef USE_COPYRIGHT_CR |
21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR | 21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR |
@@ -1,5 +1,5 @@ | |||
1 | /* AesOpt.c -- AES optimized code for x86 AES hardware instructions | 1 | /* AesOpt.c -- AES optimized code for x86 AES hardware instructions |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -80,19 +80,39 @@ AES_FUNC_START (name) | |||
80 | 80 | ||
81 | #define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src) | 81 | #define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src) |
82 | 82 | ||
83 | #if 1 | ||
84 | // use aligned SSE load/store for data. | ||
85 | // It is required for our Aes functions, that data is aligned for 16-bytes. | ||
86 | // So we can use this branch of code. | ||
87 | // and compiler can use fused load-op SSE instructions: | ||
88 | // xorps xmm0, XMMWORD PTR [rdx] | ||
89 | #define LOAD_128(pp) (*(__m128i *)(void *)(pp)) | ||
90 | #define STORE_128(pp, _v) *(__m128i *)(void *)(pp) = _v | ||
91 | // use aligned SSE load/store for data. Alternative code with direct access | ||
92 | // #define LOAD_128(pp) _mm_load_si128(pp) | ||
93 | // #define STORE_128(pp, _v) _mm_store_si128(pp, _v) | ||
94 | #else | ||
95 | // use unaligned load/store for data: movdqu XMMWORD PTR [rdx] | ||
96 | #define LOAD_128(pp) _mm_loadu_si128(pp) | ||
97 | #define STORE_128(pp, _v) _mm_storeu_si128(pp, _v) | ||
98 | #endif | ||
99 | |||
83 | AES_FUNC_START2 (AesCbc_Encode_HW) | 100 | AES_FUNC_START2 (AesCbc_Encode_HW) |
84 | { | 101 | { |
102 | if (numBlocks == 0) | ||
103 | return; | ||
104 | { | ||
85 | __m128i *p = (__m128i *)(void *)ivAes; | 105 | __m128i *p = (__m128i *)(void *)ivAes; |
86 | __m128i *data = (__m128i *)(void *)data8; | 106 | __m128i *data = (__m128i *)(void *)data8; |
87 | __m128i m = *p; | 107 | __m128i m = *p; |
88 | const __m128i k0 = p[2]; | 108 | const __m128i k0 = p[2]; |
89 | const __m128i k1 = p[3]; | 109 | const __m128i k1 = p[3]; |
90 | const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; | 110 | const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; |
91 | for (; numBlocks != 0; numBlocks--, data++) | 111 | do |
92 | { | 112 | { |
93 | UInt32 r = numRounds2; | 113 | UInt32 r = numRounds2; |
94 | const __m128i *w = p + 4; | 114 | const __m128i *w = p + 4; |
95 | __m128i temp = *data; | 115 | __m128i temp = LOAD_128(data); |
96 | MM_XOR (temp, k0) | 116 | MM_XOR (temp, k0) |
97 | MM_XOR (m, temp) | 117 | MM_XOR (m, temp) |
98 | MM_OP_m (_mm_aesenc_si128, k1) | 118 | MM_OP_m (_mm_aesenc_si128, k1) |
@@ -104,9 +124,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
104 | } | 124 | } |
105 | while (--r); | 125 | while (--r); |
106 | MM_OP_m (_mm_aesenclast_si128, w[0]) | 126 | MM_OP_m (_mm_aesenclast_si128, w[0]) |
107 | *data = m; | 127 | STORE_128(data, m); |
128 | data++; | ||
108 | } | 129 | } |
130 | while (--numBlocks); | ||
109 | *p = m; | 131 | *p = m; |
132 | } | ||
110 | } | 133 | } |
111 | 134 | ||
112 | 135 | ||
@@ -139,12 +162,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
139 | 162 | ||
140 | #define WOP(op) op (m0, 0) WOP_M1(op) | 163 | #define WOP(op) op (m0, 0) WOP_M1(op) |
141 | 164 | ||
142 | |||
143 | #define DECLARE_VAR(reg, ii) __m128i reg; | 165 | #define DECLARE_VAR(reg, ii) __m128i reg; |
144 | #define LOAD_data( reg, ii) reg = data[ii]; | 166 | #define LOAD_data_ii(ii) LOAD_128(data + (ii)) |
145 | #define STORE_data( reg, ii) data[ii] = reg; | 167 | #define LOAD_data( reg, ii) reg = LOAD_data_ii(ii); |
168 | #define STORE_data( reg, ii) STORE_128(data + (ii), reg); | ||
146 | #if (NUM_WAYS > 1) | 169 | #if (NUM_WAYS > 1) |
147 | #define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]) | 170 | #define XOR_data_M1(reg, ii) MM_XOR (reg, LOAD_128(data + (ii- 1))) |
148 | #endif | 171 | #endif |
149 | 172 | ||
150 | #define MM_OP_key(op, reg) MM_OP(op, reg, key); | 173 | #define MM_OP_key(op, reg) MM_OP(op, reg, key); |
@@ -156,25 +179,22 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
156 | #define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) | 179 | #define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) |
157 | 180 | ||
158 | #define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr; | 181 | #define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr; |
159 | #define CTR_END( reg, ii) MM_XOR (data[ii], reg) | 182 | #define CTR_END( reg, ii) STORE_128(data + (ii), _mm_xor_si128(reg, \ |
160 | 183 | LOAD_128 (data + (ii)))); | |
161 | #define WOP_KEY(op, n) { \ | 184 | #define WOP_KEY(op, n) { \ |
162 | const __m128i key = w[n]; \ | 185 | const __m128i key = w[n]; \ |
163 | WOP(op); } | 186 | WOP(op) } |
164 | |||
165 | 187 | ||
166 | #define WIDE_LOOP_START \ | 188 | #define WIDE_LOOP_START \ |
167 | dataEnd = data + numBlocks; \ | 189 | dataEnd = data + numBlocks; \ |
168 | if (numBlocks >= NUM_WAYS) \ | 190 | if (numBlocks >= NUM_WAYS) \ |
169 | { dataEnd -= NUM_WAYS; do { \ | 191 | { dataEnd -= NUM_WAYS; do { \ |
170 | 192 | ||
171 | |||
172 | #define WIDE_LOOP_END \ | 193 | #define WIDE_LOOP_END \ |
173 | data += NUM_WAYS; \ | 194 | data += NUM_WAYS; \ |
174 | } while (data <= dataEnd); \ | 195 | } while (data <= dataEnd); \ |
175 | dataEnd += NUM_WAYS; } \ | 196 | dataEnd += NUM_WAYS; } \ |
176 | 197 | ||
177 | |||
178 | #define SINGLE_LOOP \ | 198 | #define SINGLE_LOOP \ |
179 | for (; data < dataEnd; data++) | 199 | for (; data < dataEnd; data++) |
180 | 200 | ||
@@ -184,54 +204,73 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
184 | 204 | ||
185 | #define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src) | 205 | #define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src) |
186 | #define AVX_DECLARE_VAR(reg, ii) __m256i reg; | 206 | #define AVX_DECLARE_VAR(reg, ii) __m256i reg; |
187 | #define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii]; | 207 | |
188 | #define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg; | 208 | #if 1 |
209 | // use unaligned AVX load/store for data. | ||
210 | // It is required for our Aes functions, that data is aligned for 16-bytes. | ||
211 | // But we need 32-bytes reading. | ||
212 | // So we use intrinsics for unaligned AVX load/store. | ||
213 | // notes for _mm256_storeu_si256: | ||
214 | // msvc2022: uses vmovdqu and keeps the order of instruction sequence. | ||
215 | // new gcc11 uses vmovdqu | ||
216 | // old gcc9 could use pair of instructions: | ||
217 | // vmovups %xmm7, -224(%rax) | ||
218 | // vextracti128 $0x1, %ymm7, -208(%rax) | ||
219 | #define AVX_LOAD(p) _mm256_loadu_si256((const __m256i *)(const void *)(p)) | ||
220 | #define AVX_STORE(p, _v) _mm256_storeu_si256((__m256i *)(void *)(p), _v); | ||
221 | #else | ||
222 | // use aligned AVX load/store for data. | ||
223 | // for debug: we can use this branch, if we are sure that data is aligned for 32-bytes. | ||
224 | // msvc2022 uses vmovdqu still | ||
225 | // gcc uses vmovdqa (that requires 32-bytes alignment) | ||
226 | #define AVX_LOAD(p) (*(const __m256i *)(const void *)(p)) | ||
227 | #define AVX_STORE(p, _v) (*(__m256i *)(void *)(p)) = _v; | ||
228 | #endif | ||
229 | |||
230 | #define AVX_LOAD_data( reg, ii) reg = AVX_LOAD((const __m256i *)(const void *)data + (ii)); | ||
231 | #define AVX_STORE_data( reg, ii) AVX_STORE((__m256i *)(void *)data + (ii), reg) | ||
189 | /* | 232 | /* |
190 | AVX_XOR_data_M1() needs unaligned memory load | 233 | AVX_XOR_data_M1() needs unaligned memory load, even if (data) |
191 | if (we don't use _mm256_loadu_si256() here) | 234 | is aligned for 256-bits, because we read 32-bytes chunk that |
192 | { | 235 | crosses (data) position: from (data - 16bytes) to (data + 16bytes). |
193 | Most compilers with enabled optimizations generate fused AVX (LOAD + OP) | ||
194 | instruction that can load unaligned data. | ||
195 | But GCC and CLANG without -O2 or -O1 optimizations can generate separated | ||
196 | LOAD-ALIGNED (vmovdqa) instruction that will fail on execution. | ||
197 | } | ||
198 | Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here. | ||
199 | v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler. | ||
200 | */ | 236 | */ |
201 | #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii]))) | 237 | #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256((const __m256i *)(const void *)(data - 1) + (ii))) |
202 | // for debug only: the following code will fail on execution, if compiled by some compilers: | ||
203 | // #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii])) | ||
204 | 238 | ||
205 | #define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg) | 239 | #define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg) |
206 | #define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg) | 240 | #define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg) |
207 | #define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg) | 241 | #define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg) |
208 | #define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg) | 242 | #define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg) |
209 | #define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg) | 243 | #define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg) |
210 | #define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key); | 244 | #define AVX_CTR_START(reg, ii) \ |
211 | #define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg) | 245 | MM_OP (_mm256_add_epi64, ctr2, two) \ |
246 | reg = _mm256_xor_si256(ctr2, key); | ||
247 | |||
248 | #define AVX_CTR_END(reg, ii) \ | ||
249 | AVX_STORE((__m256i *)(void *)data + (ii), _mm256_xor_si256(reg, \ | ||
250 | AVX_LOAD ((__m256i *)(void *)data + (ii)))); | ||
251 | |||
212 | #define AVX_WOP_KEY(op, n) { \ | 252 | #define AVX_WOP_KEY(op, n) { \ |
213 | const __m256i key = w[n]; \ | 253 | const __m256i key = w[n]; \ |
214 | WOP(op); } | 254 | WOP(op) } |
215 | 255 | ||
216 | #define NUM_AES_KEYS_MAX 15 | 256 | #define NUM_AES_KEYS_MAX 15 |
217 | 257 | ||
218 | #define WIDE_LOOP_START_AVX(OP) \ | 258 | #define WIDE_LOOP_START_AVX(OP) \ |
219 | dataEnd = data + numBlocks; \ | 259 | dataEnd = data + numBlocks; \ |
220 | if (numBlocks >= NUM_WAYS * 2) \ | 260 | if (numBlocks >= NUM_WAYS * 2) \ |
221 | { __m256i keys[NUM_AES_KEYS_MAX]; \ | 261 | { __m256i keys[NUM_AES_KEYS_MAX]; \ |
222 | UInt32 ii; \ | 262 | OP \ |
223 | OP \ | 263 | { UInt32 ii; for (ii = 0; ii < numRounds; ii++) \ |
224 | for (ii = 0; ii < numRounds; ii++) \ | 264 | keys[ii] = _mm256_broadcastsi128_si256(p[ii]); } \ |
225 | keys[ii] = _mm256_broadcastsi128_si256(p[ii]); \ | 265 | dataEnd -= NUM_WAYS * 2; \ |
226 | dataEnd -= NUM_WAYS * 2; do { \ | 266 | do { \ |
227 | |||
228 | 267 | ||
229 | #define WIDE_LOOP_END_AVX(OP) \ | 268 | #define WIDE_LOOP_END_AVX(OP) \ |
230 | data += NUM_WAYS * 2; \ | 269 | data += NUM_WAYS * 2; \ |
231 | } while (data <= dataEnd); \ | 270 | } while (data <= dataEnd); \ |
232 | dataEnd += NUM_WAYS * 2; \ | 271 | dataEnd += NUM_WAYS * 2; \ |
233 | OP \ | 272 | OP \ |
234 | _mm256_zeroupper(); \ | 273 | _mm256_zeroupper(); \ |
235 | } \ | 274 | } \ |
236 | 275 | ||
237 | /* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, | 276 | /* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, |
@@ -246,21 +285,20 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
246 | __m128i *p = (__m128i *)(void *)ivAes; | 285 | __m128i *p = (__m128i *)(void *)ivAes; |
247 | __m128i *data = (__m128i *)(void *)data8; | 286 | __m128i *data = (__m128i *)(void *)data8; |
248 | __m128i iv = *p; | 287 | __m128i iv = *p; |
249 | const __m128i *wStart = p + *(const UInt32 *)(p + 1) * 2 + 2 - 1; | 288 | const __m128i * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2 + 2 - 1; |
250 | const __m128i *dataEnd; | 289 | const __m128i *dataEnd; |
251 | p += 2; | 290 | p += 2; |
252 | 291 | ||
253 | WIDE_LOOP_START | 292 | WIDE_LOOP_START |
254 | { | 293 | { |
255 | const __m128i *w = wStart; | 294 | const __m128i *w = wStart; |
256 | |||
257 | WOP (DECLARE_VAR) | 295 | WOP (DECLARE_VAR) |
258 | WOP (LOAD_data) | 296 | WOP (LOAD_data) |
259 | WOP_KEY (AES_XOR, 1) | 297 | WOP_KEY (AES_XOR, 1) |
260 | |||
261 | do | 298 | do |
262 | { | 299 | { |
263 | WOP_KEY (AES_DEC, 0) | 300 | WOP_KEY (AES_DEC, 0) |
301 | |||
264 | w--; | 302 | w--; |
265 | } | 303 | } |
266 | while (w != p); | 304 | while (w != p); |
@@ -268,7 +306,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
268 | 306 | ||
269 | MM_XOR (m0, iv) | 307 | MM_XOR (m0, iv) |
270 | WOP_M1 (XOR_data_M1) | 308 | WOP_M1 (XOR_data_M1) |
271 | iv = data[NUM_WAYS - 1]; | 309 | LOAD_data(iv, NUM_WAYS - 1) |
272 | WOP (STORE_data) | 310 | WOP (STORE_data) |
273 | } | 311 | } |
274 | WIDE_LOOP_END | 312 | WIDE_LOOP_END |
@@ -276,7 +314,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
276 | SINGLE_LOOP | 314 | SINGLE_LOOP |
277 | { | 315 | { |
278 | const __m128i *w = wStart - 1; | 316 | const __m128i *w = wStart - 1; |
279 | __m128i m = _mm_xor_si128 (w[2], *data); | 317 | __m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0)); |
318 | |||
280 | do | 319 | do |
281 | { | 320 | { |
282 | MM_OP_m (_mm_aesdec_si128, w[1]) | 321 | MM_OP_m (_mm_aesdec_si128, w[1]) |
@@ -286,10 +325,9 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
286 | while (w != p); | 325 | while (w != p); |
287 | MM_OP_m (_mm_aesdec_si128, w[1]) | 326 | MM_OP_m (_mm_aesdec_si128, w[1]) |
288 | MM_OP_m (_mm_aesdeclast_si128, w[0]) | 327 | MM_OP_m (_mm_aesdeclast_si128, w[0]) |
289 | |||
290 | MM_XOR (m, iv) | 328 | MM_XOR (m, iv) |
291 | iv = *data; | 329 | LOAD_data(iv, 0) |
292 | *data = m; | 330 | STORE_data(m, 0) |
293 | } | 331 | } |
294 | 332 | ||
295 | p[-2] = iv; | 333 | p[-2] = iv; |
@@ -301,9 +339,9 @@ AES_FUNC_START2 (AesCtr_Code_HW) | |||
301 | __m128i *p = (__m128i *)(void *)ivAes; | 339 | __m128i *p = (__m128i *)(void *)ivAes; |
302 | __m128i *data = (__m128i *)(void *)data8; | 340 | __m128i *data = (__m128i *)(void *)data8; |
303 | __m128i ctr = *p; | 341 | __m128i ctr = *p; |
304 | UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1; | 342 | const UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1; |
305 | const __m128i *dataEnd; | 343 | const __m128i *dataEnd; |
306 | __m128i one = _mm_cvtsi32_si128(1); | 344 | const __m128i one = _mm_cvtsi32_si128(1); |
307 | 345 | ||
308 | p += 2; | 346 | p += 2; |
309 | 347 | ||
@@ -322,7 +360,6 @@ AES_FUNC_START2 (AesCtr_Code_HW) | |||
322 | } | 360 | } |
323 | while (--r); | 361 | while (--r); |
324 | WOP_KEY (AES_ENC_LAST, 0) | 362 | WOP_KEY (AES_ENC_LAST, 0) |
325 | |||
326 | WOP (CTR_END) | 363 | WOP (CTR_END) |
327 | } | 364 | } |
328 | WIDE_LOOP_END | 365 | WIDE_LOOP_END |
@@ -344,7 +381,7 @@ AES_FUNC_START2 (AesCtr_Code_HW) | |||
344 | while (--numRounds2); | 381 | while (--numRounds2); |
345 | MM_OP_m (_mm_aesenc_si128, w[0]) | 382 | MM_OP_m (_mm_aesenc_si128, w[0]) |
346 | MM_OP_m (_mm_aesenclast_si128, w[1]) | 383 | MM_OP_m (_mm_aesenclast_si128, w[1]) |
347 | MM_XOR (*data, m) | 384 | CTR_END (m, 0) |
348 | } | 385 | } |
349 | 386 | ||
350 | p[-2] = ctr; | 387 | p[-2] = ctr; |
@@ -421,7 +458,7 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256) | |||
421 | __m128i *data = (__m128i *)(void *)data8; | 458 | __m128i *data = (__m128i *)(void *)data8; |
422 | __m128i iv = *p; | 459 | __m128i iv = *p; |
423 | const __m128i *dataEnd; | 460 | const __m128i *dataEnd; |
424 | UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; | 461 | const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; |
425 | p += 2; | 462 | p += 2; |
426 | 463 | ||
427 | WIDE_LOOP_START_AVX(;) | 464 | WIDE_LOOP_START_AVX(;) |
@@ -440,17 +477,17 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256) | |||
440 | while (w != keys); | 477 | while (w != keys); |
441 | AVX_WOP_KEY (AVX_AES_DEC_LAST, 0) | 478 | AVX_WOP_KEY (AVX_AES_DEC_LAST, 0) |
442 | 479 | ||
443 | AVX_XOR (m0, _mm256_setr_m128i(iv, data[0])) | 480 | AVX_XOR (m0, _mm256_setr_m128i(iv, LOAD_data_ii(0))) |
444 | WOP_M1 (AVX_XOR_data_M1) | 481 | WOP_M1 (AVX_XOR_data_M1) |
445 | iv = data[NUM_WAYS * 2 - 1]; | 482 | LOAD_data (iv, NUM_WAYS * 2 - 1) |
446 | WOP (AVX_STORE_data) | 483 | WOP (AVX_STORE_data) |
447 | } | 484 | } |
448 | WIDE_LOOP_END_AVX(;) | 485 | WIDE_LOOP_END_AVX(;) |
449 | 486 | ||
450 | SINGLE_LOOP | 487 | SINGLE_LOOP |
451 | { | 488 | { |
452 | const __m128i *w = p + *(const UInt32 *)(p + 1 - 2) * 2 + 1 - 3; | 489 | const __m128i *w = p - 2 + (size_t)*(const UInt32 *)(p + 1 - 2) * 2; |
453 | __m128i m = _mm_xor_si128 (w[2], *data); | 490 | __m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0)); |
454 | do | 491 | do |
455 | { | 492 | { |
456 | MM_OP_m (_mm_aesdec_si128, w[1]) | 493 | MM_OP_m (_mm_aesdec_si128, w[1]) |
@@ -462,8 +499,8 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256) | |||
462 | MM_OP_m (_mm_aesdeclast_si128, w[0]) | 499 | MM_OP_m (_mm_aesdeclast_si128, w[0]) |
463 | 500 | ||
464 | MM_XOR (m, iv) | 501 | MM_XOR (m, iv) |
465 | iv = *data; | 502 | LOAD_data(iv, 0) |
466 | *data = m; | 503 | STORE_data(m, 0) |
467 | } | 504 | } |
468 | 505 | ||
469 | p[-2] = iv; | 506 | p[-2] = iv; |
@@ -493,9 +530,9 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256) | |||
493 | __m128i *p = (__m128i *)(void *)ivAes; | 530 | __m128i *p = (__m128i *)(void *)ivAes; |
494 | __m128i *data = (__m128i *)(void *)data8; | 531 | __m128i *data = (__m128i *)(void *)data8; |
495 | __m128i ctr = *p; | 532 | __m128i ctr = *p; |
496 | UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; | 533 | const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; |
497 | const __m128i *dataEnd; | 534 | const __m128i *dataEnd; |
498 | __m128i one = _mm_cvtsi32_si128(1); | 535 | const __m128i one = _mm_cvtsi32_si128(1); |
499 | __m256i ctr2, two; | 536 | __m256i ctr2, two; |
500 | p += 2; | 537 | p += 2; |
501 | 538 | ||
@@ -536,7 +573,7 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256) | |||
536 | while (--numRounds2); | 573 | while (--numRounds2); |
537 | MM_OP_m (_mm_aesenc_si128, w[0]) | 574 | MM_OP_m (_mm_aesenc_si128, w[0]) |
538 | MM_OP_m (_mm_aesenclast_si128, w[1]) | 575 | MM_OP_m (_mm_aesenclast_si128, w[1]) |
539 | MM_XOR (*data, m) | 576 | CTR_END (m, 0) |
540 | } | 577 | } |
541 | 578 | ||
542 | p[-2] = ctr; | 579 | p[-2] = ctr; |
@@ -731,9 +768,14 @@ AES_FUNC_START (name) | |||
731 | 768 | ||
732 | AES_FUNC_START2 (AesCbc_Encode_HW) | 769 | AES_FUNC_START2 (AesCbc_Encode_HW) |
733 | { | 770 | { |
734 | v128 * const p = (v128*)(void*)ivAes; | 771 | if (numBlocks == 0) |
735 | v128 *data = (v128*)(void*)data8; | 772 | return; |
773 | { | ||
774 | v128 * const p = (v128 *)(void *)ivAes; | ||
775 | v128 *data = (v128 *)(void *)data8; | ||
736 | v128 m = *p; | 776 | v128 m = *p; |
777 | const UInt32 numRounds2 = *(const UInt32 *)(p + 1); | ||
778 | const v128 *w = p + (size_t)numRounds2 * 2; | ||
737 | const v128 k0 = p[2]; | 779 | const v128 k0 = p[2]; |
738 | const v128 k1 = p[3]; | 780 | const v128 k1 = p[3]; |
739 | const v128 k2 = p[4]; | 781 | const v128 k2 = p[4]; |
@@ -744,11 +786,14 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
744 | const v128 k7 = p[9]; | 786 | const v128 k7 = p[9]; |
745 | const v128 k8 = p[10]; | 787 | const v128 k8 = p[10]; |
746 | const v128 k9 = p[11]; | 788 | const v128 k9 = p[11]; |
747 | const UInt32 numRounds2 = *(const UInt32 *)(p + 1); | 789 | const v128 k_z4 = w[-2]; |
748 | const v128 *w = p + ((size_t)numRounds2 * 2); | 790 | const v128 k_z3 = w[-1]; |
791 | const v128 k_z2 = w[0]; | ||
749 | const v128 k_z1 = w[1]; | 792 | const v128 k_z1 = w[1]; |
750 | const v128 k_z0 = w[2]; | 793 | const v128 k_z0 = w[2]; |
751 | for (; numBlocks != 0; numBlocks--, data++) | 794 | // we don't use optimization veorq_u8(*data, k_z0) that can reduce one cycle, |
795 | // because gcc/clang compilers are not good for that optimization. | ||
796 | do | ||
752 | { | 797 | { |
753 | MM_XOR_m (*data) | 798 | MM_XOR_m (*data) |
754 | AES_E_MC_m (k0) | 799 | AES_E_MC_m (k0) |
@@ -757,24 +802,26 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
757 | AES_E_MC_m (k3) | 802 | AES_E_MC_m (k3) |
758 | AES_E_MC_m (k4) | 803 | AES_E_MC_m (k4) |
759 | AES_E_MC_m (k5) | 804 | AES_E_MC_m (k5) |
760 | AES_E_MC_m (k6) | ||
761 | AES_E_MC_m (k7) | ||
762 | AES_E_MC_m (k8) | ||
763 | if (numRounds2 >= 6) | 805 | if (numRounds2 >= 6) |
764 | { | 806 | { |
765 | AES_E_MC_m (k9) | 807 | AES_E_MC_m (k6) |
766 | AES_E_MC_m (p[12]) | 808 | AES_E_MC_m (k7) |
767 | if (numRounds2 != 6) | 809 | if (numRounds2 != 6) |
768 | { | 810 | { |
769 | AES_E_MC_m (p[13]) | 811 | AES_E_MC_m (k8) |
770 | AES_E_MC_m (p[14]) | 812 | AES_E_MC_m (k9) |
771 | } | 813 | } |
772 | } | 814 | } |
773 | AES_E_m (k_z1) | 815 | AES_E_MC_m (k_z4) |
774 | MM_XOR_m (k_z0) | 816 | AES_E_MC_m (k_z3) |
775 | *data = m; | 817 | AES_E_MC_m (k_z2) |
818 | AES_E_m (k_z1) | ||
819 | MM_XOR_m (k_z0) | ||
820 | *data++ = m; | ||
776 | } | 821 | } |
822 | while (--numBlocks); | ||
777 | *p = m; | 823 | *p = m; |
824 | } | ||
778 | } | 825 | } |
779 | 826 | ||
780 | 827 | ||
@@ -834,10 +881,10 @@ AES_FUNC_START2 (AesCbc_Encode_HW) | |||
834 | 881 | ||
835 | AES_FUNC_START2 (AesCbc_Decode_HW) | 882 | AES_FUNC_START2 (AesCbc_Decode_HW) |
836 | { | 883 | { |
837 | v128 *p = (v128*)(void*)ivAes; | 884 | v128 *p = (v128 *)(void *)ivAes; |
838 | v128 *data = (v128*)(void*)data8; | 885 | v128 *data = (v128 *)(void *)data8; |
839 | v128 iv = *p; | 886 | v128 iv = *p; |
840 | const v128 *wStart = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; | 887 | const v128 * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2; |
841 | const v128 *dataEnd; | 888 | const v128 *dataEnd; |
842 | p += 2; | 889 | p += 2; |
843 | 890 | ||
@@ -858,7 +905,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
858 | WOP_KEY (AES_XOR, 0) | 905 | WOP_KEY (AES_XOR, 0) |
859 | MM_XOR (m0, iv) | 906 | MM_XOR (m0, iv) |
860 | WOP_M1 (XOR_data_M1) | 907 | WOP_M1 (XOR_data_M1) |
861 | iv = data[NUM_WAYS - 1]; | 908 | LOAD_data(iv, NUM_WAYS - 1) |
862 | WOP (STORE_data) | 909 | WOP (STORE_data) |
863 | } | 910 | } |
864 | WIDE_LOOP_END | 911 | WIDE_LOOP_END |
@@ -866,7 +913,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
866 | SINGLE_LOOP | 913 | SINGLE_LOOP |
867 | { | 914 | { |
868 | const v128 *w = wStart; | 915 | const v128 *w = wStart; |
869 | v128 m = *data; | 916 | v128 m; LOAD_data(m, 0) |
870 | AES_D_IMC_m (w[2]) | 917 | AES_D_IMC_m (w[2]) |
871 | do | 918 | do |
872 | { | 919 | { |
@@ -878,8 +925,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
878 | AES_D_m (w[1]) | 925 | AES_D_m (w[1]) |
879 | MM_XOR_m (w[0]) | 926 | MM_XOR_m (w[0]) |
880 | MM_XOR_m (iv) | 927 | MM_XOR_m (iv) |
881 | iv = *data; | 928 | LOAD_data(iv, 0) |
882 | *data = m; | 929 | STORE_data(m, 0) |
883 | } | 930 | } |
884 | 931 | ||
885 | p[-2] = iv; | 932 | p[-2] = iv; |
@@ -888,19 +935,17 @@ AES_FUNC_START2 (AesCbc_Decode_HW) | |||
888 | 935 | ||
889 | AES_FUNC_START2 (AesCtr_Code_HW) | 936 | AES_FUNC_START2 (AesCtr_Code_HW) |
890 | { | 937 | { |
891 | v128 *p = (v128*)(void*)ivAes; | 938 | v128 *p = (v128 *)(void *)ivAes; |
892 | v128 *data = (v128*)(void*)data8; | 939 | v128 *data = (v128 *)(void *)data8; |
893 | uint64x2_t ctr = vreinterpretq_u64_u8(*p); | 940 | uint64x2_t ctr = vreinterpretq_u64_u8(*p); |
894 | const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; | 941 | const v128 * const wEnd = p + (size_t)*(const UInt32 *)(p + 1) * 2; |
895 | const v128 *dataEnd; | 942 | const v128 *dataEnd; |
896 | uint64x2_t one = vdupq_n_u64(0); | ||
897 | |||
898 | // the bug in clang: | 943 | // the bug in clang: |
899 | // __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2); | 944 | // __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2); |
900 | #if defined(__clang__) && (__clang_major__ <= 9) | 945 | #if defined(__clang__) && (__clang_major__ <= 9) |
901 | #pragma GCC diagnostic ignored "-Wvector-conversion" | 946 | #pragma GCC diagnostic ignored "-Wvector-conversion" |
902 | #endif | 947 | #endif |
903 | one = vsetq_lane_u64(1, one, 0); | 948 | const uint64x2_t one = vsetq_lane_u64(1, vdupq_n_u64(0), 0); |
904 | p += 2; | 949 | p += 2; |
905 | 950 | ||
906 | WIDE_LOOP_START | 951 | WIDE_LOOP_START |
diff --git a/C/BwtSort.c b/C/BwtSort.c index 05ad6de..8f64f9d 100644 --- a/C/BwtSort.c +++ b/C/BwtSort.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* BwtSort.c -- BWT block sorting | 1 | /* BwtSort.c -- BWT block sorting |
2 | 2023-04-02 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -7,6 +7,44 @@ | |||
7 | #include "Sort.h" | 7 | #include "Sort.h" |
8 | 8 | ||
9 | /* #define BLOCK_SORT_USE_HEAP_SORT */ | 9 | /* #define BLOCK_SORT_USE_HEAP_SORT */ |
10 | // #define BLOCK_SORT_USE_HEAP_SORT | ||
11 | |||
12 | #ifdef BLOCK_SORT_USE_HEAP_SORT | ||
13 | |||
14 | #define HeapSortRefDown(p, vals, n, size, temp) \ | ||
15 | { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ | ||
16 | size_t s = k << 1; \ | ||
17 | if (s > size) break; \ | ||
18 | if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ | ||
19 | if (val >= vals[p[s]]) break; \ | ||
20 | p[k] = p[s]; k = s; \ | ||
21 | } p[k] = temp; } | ||
22 | |||
23 | void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) | ||
24 | { | ||
25 | if (size <= 1) | ||
26 | return; | ||
27 | p--; | ||
28 | { | ||
29 | size_t i = size / 2; | ||
30 | do | ||
31 | { | ||
32 | UInt32 temp = p[i]; | ||
33 | HeapSortRefDown(p, vals, i, size, temp); | ||
34 | } | ||
35 | while (--i != 0); | ||
36 | } | ||
37 | do | ||
38 | { | ||
39 | UInt32 temp = p[size]; | ||
40 | p[size--] = p[1]; | ||
41 | HeapSortRefDown(p, vals, 1, size, temp); | ||
42 | } | ||
43 | while (size > 1); | ||
44 | } | ||
45 | |||
46 | #endif // BLOCK_SORT_USE_HEAP_SORT | ||
47 | |||
10 | 48 | ||
11 | /* Don't change it !!! */ | 49 | /* Don't change it !!! */ |
12 | #define kNumHashBytes 2 | 50 | #define kNumHashBytes 2 |
@@ -27,26 +65,27 @@ | |||
27 | 65 | ||
28 | #else | 66 | #else |
29 | 67 | ||
30 | #define kNumBitsMax 20 | 68 | #define kNumBitsMax 20 |
31 | #define kIndexMask ((1 << kNumBitsMax) - 1) | 69 | #define kIndexMask (((UInt32)1 << kNumBitsMax) - 1) |
32 | #define kNumExtraBits (32 - kNumBitsMax) | 70 | #define kNumExtraBits (32 - kNumBitsMax) |
33 | #define kNumExtra0Bits (kNumExtraBits - 2) | 71 | #define kNumExtra0Bits (kNumExtraBits - 2) |
34 | #define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1) | 72 | #define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1) |
35 | 73 | ||
36 | #define SetFinishedGroupSize(p, size) \ | 74 | #define SetFinishedGroupSize(p, size) \ |
37 | { *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \ | 75 | { *(p) |= ((((UInt32)(size) - 1) & kNumExtra0Mask) << kNumBitsMax); \ |
38 | if ((size) > (1 << kNumExtra0Bits)) { \ | 76 | if ((size) > (1 << kNumExtra0Bits)) { \ |
39 | *(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \ | 77 | *(p) |= 0x40000000; \ |
78 | *((p) + 1) |= (((UInt32)(size) - 1) >> kNumExtra0Bits) << kNumBitsMax; } } \ | ||
40 | 79 | ||
41 | static void SetGroupSize(UInt32 *p, UInt32 size) | 80 | static void SetGroupSize(UInt32 *p, size_t size) |
42 | { | 81 | { |
43 | if (--size == 0) | 82 | if (--size == 0) |
44 | return; | 83 | return; |
45 | *p |= 0x80000000 | ((size & kNumExtra0Mask) << kNumBitsMax); | 84 | *p |= 0x80000000 | (((UInt32)size & kNumExtra0Mask) << kNumBitsMax); |
46 | if (size >= (1 << kNumExtra0Bits)) | 85 | if (size >= (1 << kNumExtra0Bits)) |
47 | { | 86 | { |
48 | *p |= 0x40000000; | 87 | *p |= 0x40000000; |
49 | p[1] |= ((size >> kNumExtra0Bits) << kNumBitsMax); | 88 | p[1] |= (((UInt32)size >> kNumExtra0Bits) << kNumBitsMax); |
50 | } | 89 | } |
51 | } | 90 | } |
52 | 91 | ||
@@ -59,12 +98,14 @@ returns: 1 - if there are groups, 0 - no more groups | |||
59 | */ | 98 | */ |
60 | 99 | ||
61 | static | 100 | static |
62 | UInt32 | 101 | unsigned |
63 | Z7_FASTCALL | 102 | Z7_FASTCALL |
64 | SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices | 103 | SortGroup(size_t BlockSize, size_t NumSortedBytes, |
65 | #ifndef BLOCK_SORT_USE_HEAP_SORT | 104 | size_t groupOffset, size_t groupSize, |
66 | , UInt32 left, UInt32 range | 105 | unsigned NumRefBits, UInt32 *Indices |
67 | #endif | 106 | #ifndef BLOCK_SORT_USE_HEAP_SORT |
107 | , size_t left, size_t range | ||
108 | #endif | ||
68 | ) | 109 | ) |
69 | { | 110 | { |
70 | UInt32 *ind2 = Indices + groupOffset; | 111 | UInt32 *ind2 = Indices + groupOffset; |
@@ -79,90 +120,93 @@ SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 gr | |||
79 | return 0; | 120 | return 0; |
80 | } | 121 | } |
81 | Groups = Indices + BlockSize + BS_TEMP_SIZE; | 122 | Groups = Indices + BlockSize + BS_TEMP_SIZE; |
82 | if (groupSize <= ((UInt32)1 << NumRefBits) | 123 | if (groupSize <= ((size_t)1 << NumRefBits) |
83 | #ifndef BLOCK_SORT_USE_HEAP_SORT | 124 | #ifndef BLOCK_SORT_USE_HEAP_SORT |
84 | && groupSize <= range | 125 | && groupSize <= range |
85 | #endif | 126 | #endif |
86 | ) | 127 | ) |
87 | { | 128 | { |
88 | UInt32 *temp = Indices + BlockSize; | 129 | UInt32 *temp = Indices + BlockSize; |
89 | UInt32 j; | 130 | size_t j, group; |
90 | UInt32 mask, thereAreGroups, group, cg; | 131 | UInt32 mask, cg; |
132 | unsigned thereAreGroups; | ||
91 | { | 133 | { |
92 | UInt32 gPrev; | 134 | UInt32 gPrev; |
93 | UInt32 gRes = 0; | 135 | UInt32 gRes = 0; |
94 | { | 136 | { |
95 | UInt32 sp = ind2[0] + NumSortedBytes; | 137 | size_t sp = ind2[0] + NumSortedBytes; |
96 | if (sp >= BlockSize) sp -= BlockSize; | 138 | if (sp >= BlockSize) |
139 | sp -= BlockSize; | ||
97 | gPrev = Groups[sp]; | 140 | gPrev = Groups[sp]; |
98 | temp[0] = (gPrev << NumRefBits); | 141 | temp[0] = gPrev << NumRefBits; |
99 | } | 142 | } |
100 | 143 | ||
101 | for (j = 1; j < groupSize; j++) | 144 | for (j = 1; j < groupSize; j++) |
102 | { | 145 | { |
103 | UInt32 sp = ind2[j] + NumSortedBytes; | 146 | size_t sp = ind2[j] + NumSortedBytes; |
104 | UInt32 g; | 147 | UInt32 g; |
105 | if (sp >= BlockSize) sp -= BlockSize; | 148 | if (sp >= BlockSize) |
149 | sp -= BlockSize; | ||
106 | g = Groups[sp]; | 150 | g = Groups[sp]; |
107 | temp[j] = (g << NumRefBits) | j; | 151 | temp[j] = (g << NumRefBits) | (UInt32)j; |
108 | gRes |= (gPrev ^ g); | 152 | gRes |= (gPrev ^ g); |
109 | } | 153 | } |
110 | if (gRes == 0) | 154 | if (gRes == 0) |
111 | { | 155 | { |
112 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 156 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
113 | SetGroupSize(ind2, groupSize); | 157 | SetGroupSize(ind2, groupSize); |
114 | #endif | 158 | #endif |
115 | return 1; | 159 | return 1; |
116 | } | 160 | } |
117 | } | 161 | } |
118 | 162 | ||
119 | HeapSort(temp, groupSize); | 163 | HeapSort(temp, groupSize); |
120 | mask = (((UInt32)1 << NumRefBits) - 1); | 164 | mask = ((UInt32)1 << NumRefBits) - 1; |
121 | thereAreGroups = 0; | 165 | thereAreGroups = 0; |
122 | 166 | ||
123 | group = groupOffset; | 167 | group = groupOffset; |
124 | cg = (temp[0] >> NumRefBits); | 168 | cg = temp[0] >> NumRefBits; |
125 | temp[0] = ind2[temp[0] & mask]; | 169 | temp[0] = ind2[temp[0] & mask]; |
126 | 170 | ||
127 | { | 171 | { |
128 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 172 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
129 | UInt32 *Flags = Groups + BlockSize; | 173 | UInt32 *Flags = Groups + BlockSize; |
130 | #else | 174 | #else |
131 | UInt32 prevGroupStart = 0; | 175 | size_t prevGroupStart = 0; |
132 | #endif | 176 | #endif |
133 | 177 | ||
134 | for (j = 1; j < groupSize; j++) | 178 | for (j = 1; j < groupSize; j++) |
135 | { | 179 | { |
136 | UInt32 val = temp[j]; | 180 | const UInt32 val = temp[j]; |
137 | UInt32 cgCur = (val >> NumRefBits); | 181 | const UInt32 cgCur = val >> NumRefBits; |
138 | 182 | ||
139 | if (cgCur != cg) | 183 | if (cgCur != cg) |
140 | { | 184 | { |
141 | cg = cgCur; | 185 | cg = cgCur; |
142 | group = groupOffset + j; | 186 | group = groupOffset + j; |
143 | 187 | ||
144 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 188 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
145 | { | 189 | { |
146 | UInt32 t = group - 1; | 190 | const size_t t = group - 1; |
147 | Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); | 191 | Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask)); |
148 | } | 192 | } |
149 | #else | 193 | #else |
150 | SetGroupSize(temp + prevGroupStart, j - prevGroupStart); | 194 | SetGroupSize(temp + prevGroupStart, j - prevGroupStart); |
151 | prevGroupStart = j; | 195 | prevGroupStart = j; |
152 | #endif | 196 | #endif |
153 | } | 197 | } |
154 | else | 198 | else |
155 | thereAreGroups = 1; | 199 | thereAreGroups = 1; |
156 | { | 200 | { |
157 | UInt32 ind = ind2[val & mask]; | 201 | const UInt32 ind = ind2[val & mask]; |
158 | temp[j] = ind; | 202 | temp[j] = ind; |
159 | Groups[ind] = group; | 203 | Groups[ind] = (UInt32)group; |
160 | } | 204 | } |
161 | } | 205 | } |
162 | 206 | ||
163 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 207 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
164 | SetGroupSize(temp + prevGroupStart, j - prevGroupStart); | 208 | SetGroupSize(temp + prevGroupStart, j - prevGroupStart); |
165 | #endif | 209 | #endif |
166 | } | 210 | } |
167 | 211 | ||
168 | for (j = 0; j < groupSize; j++) | 212 | for (j = 0; j < groupSize; j++) |
@@ -172,37 +216,42 @@ SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 gr | |||
172 | 216 | ||
173 | /* Check that all strings are in one group (cannot sort) */ | 217 | /* Check that all strings are in one group (cannot sort) */ |
174 | { | 218 | { |
175 | UInt32 group, j; | 219 | UInt32 group; |
176 | UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; | 220 | size_t j; |
221 | size_t sp = ind2[0] + NumSortedBytes; | ||
222 | if (sp >= BlockSize) | ||
223 | sp -= BlockSize; | ||
177 | group = Groups[sp]; | 224 | group = Groups[sp]; |
178 | for (j = 1; j < groupSize; j++) | 225 | for (j = 1; j < groupSize; j++) |
179 | { | 226 | { |
180 | sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; | 227 | sp = ind2[j] + NumSortedBytes; |
228 | if (sp >= BlockSize) | ||
229 | sp -= BlockSize; | ||
181 | if (Groups[sp] != group) | 230 | if (Groups[sp] != group) |
182 | break; | 231 | break; |
183 | } | 232 | } |
184 | if (j == groupSize) | 233 | if (j == groupSize) |
185 | { | 234 | { |
186 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 235 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
187 | SetGroupSize(ind2, groupSize); | 236 | SetGroupSize(ind2, groupSize); |
188 | #endif | 237 | #endif |
189 | return 1; | 238 | return 1; |
190 | } | 239 | } |
191 | } | 240 | } |
192 | 241 | ||
193 | #ifndef BLOCK_SORT_USE_HEAP_SORT | 242 | #ifndef BLOCK_SORT_USE_HEAP_SORT |
194 | { | 243 | { |
195 | /* ---------- Range Sort ---------- */ | 244 | /* ---------- Range Sort ---------- */ |
196 | UInt32 i; | 245 | size_t i; |
197 | UInt32 mid; | 246 | size_t mid; |
198 | for (;;) | 247 | for (;;) |
199 | { | 248 | { |
200 | UInt32 j; | 249 | size_t j; |
201 | if (range <= 1) | 250 | if (range <= 1) |
202 | { | 251 | { |
203 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 252 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
204 | SetGroupSize(ind2, groupSize); | 253 | SetGroupSize(ind2, groupSize); |
205 | #endif | 254 | #endif |
206 | return 1; | 255 | return 1; |
207 | } | 256 | } |
208 | mid = left + ((range + 1) >> 1); | 257 | mid = left + ((range + 1) >> 1); |
@@ -210,7 +259,7 @@ SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 gr | |||
210 | i = 0; | 259 | i = 0; |
211 | do | 260 | do |
212 | { | 261 | { |
213 | UInt32 sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; | 262 | size_t sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; |
214 | if (Groups[sp] >= mid) | 263 | if (Groups[sp] >= mid) |
215 | { | 264 | { |
216 | for (j--; j > i; j--) | 265 | for (j--; j > i; j--) |
@@ -238,51 +287,53 @@ SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 gr | |||
238 | break; | 287 | break; |
239 | } | 288 | } |
240 | 289 | ||
241 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 290 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
242 | { | 291 | { |
243 | UInt32 t = (groupOffset + i - 1); | 292 | const size_t t = groupOffset + i - 1; |
244 | UInt32 *Flags = Groups + BlockSize; | 293 | UInt32 *Flags = Groups + BlockSize; |
245 | Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); | 294 | Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask)); |
246 | } | 295 | } |
247 | #endif | 296 | #endif |
248 | 297 | ||
249 | { | 298 | { |
250 | UInt32 j; | 299 | size_t j; |
251 | for (j = i; j < groupSize; j++) | 300 | for (j = i; j < groupSize; j++) |
252 | Groups[ind2[j]] = groupOffset + i; | 301 | Groups[ind2[j]] = (UInt32)(groupOffset + i); |
253 | } | 302 | } |
254 | 303 | ||
255 | { | 304 | { |
256 | UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left); | 305 | unsigned res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left); |
257 | return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left)); | 306 | return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left)); |
258 | } | 307 | } |
259 | 308 | ||
260 | } | 309 | } |
261 | 310 | ||
262 | #else | 311 | #else // BLOCK_SORT_USE_HEAP_SORT |
263 | 312 | ||
264 | /* ---------- Heap Sort ---------- */ | 313 | /* ---------- Heap Sort ---------- */ |
265 | 314 | ||
266 | { | 315 | { |
267 | UInt32 j; | 316 | size_t j; |
268 | for (j = 0; j < groupSize; j++) | 317 | for (j = 0; j < groupSize; j++) |
269 | { | 318 | { |
270 | UInt32 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize; | 319 | size_t sp = ind2[j] + NumSortedBytes; |
271 | ind2[j] = sp; | 320 | if (sp >= BlockSize) |
321 | sp -= BlockSize; | ||
322 | ind2[j] = (UInt32)sp; | ||
272 | } | 323 | } |
273 | 324 | ||
274 | HeapSortRef(ind2, Groups, groupSize); | 325 | HeapSortRef(ind2, Groups, groupSize); |
275 | 326 | ||
276 | /* Write Flags */ | 327 | /* Write Flags */ |
277 | { | 328 | { |
278 | UInt32 sp = ind2[0]; | 329 | size_t sp = ind2[0]; |
279 | UInt32 group = Groups[sp]; | 330 | UInt32 group = Groups[sp]; |
280 | 331 | ||
281 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 332 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
282 | UInt32 *Flags = Groups + BlockSize; | 333 | UInt32 *Flags = Groups + BlockSize; |
283 | #else | 334 | #else |
284 | UInt32 prevGroupStart = 0; | 335 | size_t prevGroupStart = 0; |
285 | #endif | 336 | #endif |
286 | 337 | ||
287 | for (j = 1; j < groupSize; j++) | 338 | for (j = 1; j < groupSize; j++) |
288 | { | 339 | { |
@@ -290,149 +341,210 @@ SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 gr | |||
290 | if (Groups[sp] != group) | 341 | if (Groups[sp] != group) |
291 | { | 342 | { |
292 | group = Groups[sp]; | 343 | group = Groups[sp]; |
293 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 344 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
294 | { | 345 | { |
295 | UInt32 t = groupOffset + j - 1; | 346 | const size_t t = groupOffset + j - 1; |
296 | Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); | 347 | Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); |
297 | } | 348 | } |
298 | #else | 349 | #else |
299 | SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); | 350 | SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); |
300 | prevGroupStart = j; | 351 | prevGroupStart = j; |
301 | #endif | 352 | #endif |
302 | } | 353 | } |
303 | } | 354 | } |
304 | 355 | ||
305 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 356 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
306 | SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); | 357 | SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart); |
307 | #endif | 358 | #endif |
308 | } | 359 | } |
309 | { | 360 | { |
310 | /* Write new Groups values and Check that there are groups */ | 361 | /* Write new Groups values and Check that there are groups */ |
311 | UInt32 thereAreGroups = 0; | 362 | unsigned thereAreGroups = 0; |
312 | for (j = 0; j < groupSize; j++) | 363 | for (j = 0; j < groupSize; j++) |
313 | { | 364 | { |
314 | UInt32 group = groupOffset + j; | 365 | size_t group = groupOffset + j; |
315 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 366 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
316 | UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax); | 367 | UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax); |
317 | if ((ind2[j] & 0x40000000) != 0) | 368 | if (ind2[j] & 0x40000000) |
318 | subGroupSize += ((ind2[(size_t)j + 1] >> kNumBitsMax) << kNumExtra0Bits); | 369 | subGroupSize += ((ind2[(size_t)j + 1] >> kNumBitsMax) << kNumExtra0Bits); |
319 | subGroupSize++; | 370 | subGroupSize++; |
320 | for (;;) | 371 | for (;;) |
321 | { | 372 | { |
322 | UInt32 original = ind2[j]; | 373 | const UInt32 original = ind2[j]; |
323 | UInt32 sp = original & kIndexMask; | 374 | size_t sp = original & kIndexMask; |
324 | if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes; | 375 | if (sp < NumSortedBytes) |
325 | ind2[j] = sp | (original & ~kIndexMask); | 376 | sp += BlockSize; |
326 | Groups[sp] = group; | 377 | sp -= NumSortedBytes; |
378 | ind2[j] = (UInt32)sp | (original & ~kIndexMask); | ||
379 | Groups[sp] = (UInt32)group; | ||
327 | if (--subGroupSize == 0) | 380 | if (--subGroupSize == 0) |
328 | break; | 381 | break; |
329 | j++; | 382 | j++; |
330 | thereAreGroups = 1; | 383 | thereAreGroups = 1; |
331 | } | 384 | } |
332 | #else | 385 | #else |
333 | UInt32 *Flags = Groups + BlockSize; | 386 | UInt32 *Flags = Groups + BlockSize; |
334 | for (;;) | 387 | for (;;) |
335 | { | 388 | { |
336 | UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes; | 389 | size_t sp = ind2[j]; |
337 | ind2[j] = sp; | 390 | if (sp < NumSortedBytes) |
338 | Groups[sp] = group; | 391 | sp += BlockSize; |
392 | sp -= NumSortedBytes; | ||
393 | ind2[j] = (UInt32)sp; | ||
394 | Groups[sp] = (UInt32)group; | ||
339 | if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0) | 395 | if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0) |
340 | break; | 396 | break; |
341 | j++; | 397 | j++; |
342 | thereAreGroups = 1; | 398 | thereAreGroups = 1; |
343 | } | 399 | } |
344 | #endif | 400 | #endif |
345 | } | 401 | } |
346 | return thereAreGroups; | 402 | return thereAreGroups; |
347 | } | 403 | } |
348 | } | 404 | } |
349 | #endif | 405 | #endif // BLOCK_SORT_USE_HEAP_SORT |
350 | } | 406 | } |
351 | 407 | ||
408 | |||
352 | /* conditions: blockSize > 0 */ | 409 | /* conditions: blockSize > 0 */ |
353 | UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize) | 410 | UInt32 BlockSort(UInt32 *Indices, const Byte *data, size_t blockSize) |
354 | { | 411 | { |
355 | UInt32 *counters = Indices + blockSize; | 412 | UInt32 *counters = Indices + blockSize; |
356 | UInt32 i; | 413 | size_t i; |
357 | UInt32 *Groups; | 414 | UInt32 *Groups; |
358 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 415 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
359 | UInt32 *Flags; | 416 | UInt32 *Flags; |
360 | #endif | 417 | #endif |
361 | 418 | ||
362 | /* Radix-Sort for 2 bytes */ | 419 | /* Radix-Sort for 2 bytes */ |
420 | // { UInt32 yyy; for (yyy = 0; yyy < 100; yyy++) { | ||
363 | for (i = 0; i < kNumHashValues; i++) | 421 | for (i = 0; i < kNumHashValues; i++) |
364 | counters[i] = 0; | 422 | counters[i] = 0; |
365 | for (i = 0; i < blockSize - 1; i++) | 423 | { |
366 | counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++; | 424 | const Byte *data2 = data; |
367 | counters[((UInt32)data[i] << 8) | data[0]]++; | 425 | size_t a = data[(size_t)blockSize - 1]; |
426 | const Byte *data_lim = data + blockSize; | ||
427 | if (blockSize >= 4) | ||
428 | { | ||
429 | data_lim -= 3; | ||
430 | do | ||
431 | { | ||
432 | size_t b; | ||
433 | b = data2[0]; counters[(a << 8) | b]++; | ||
434 | a = data2[1]; counters[(b << 8) | a]++; | ||
435 | b = data2[2]; counters[(a << 8) | b]++; | ||
436 | a = data2[3]; counters[(b << 8) | a]++; | ||
437 | data2 += 4; | ||
438 | } | ||
439 | while (data2 < data_lim); | ||
440 | data_lim += 3; | ||
441 | } | ||
442 | while (data2 != data_lim) | ||
443 | { | ||
444 | size_t b = *data2++; | ||
445 | counters[(a << 8) | b]++; | ||
446 | a = b; | ||
447 | } | ||
448 | } | ||
449 | // }} | ||
368 | 450 | ||
369 | Groups = counters + BS_TEMP_SIZE; | 451 | Groups = counters + BS_TEMP_SIZE; |
370 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 452 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
371 | Flags = Groups + blockSize; | 453 | Flags = Groups + blockSize; |
372 | { | 454 | { |
373 | UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits; | 455 | const size_t numWords = (blockSize + kFlagsMask) >> kNumFlagsBits; |
374 | for (i = 0; i < numWords; i++) | 456 | for (i = 0; i < numWords; i++) |
375 | Flags[i] = kAllFlags; | 457 | Flags[i] = kAllFlags; |
376 | } | 458 | } |
377 | #endif | 459 | #endif |
378 | 460 | ||
379 | { | 461 | { |
380 | UInt32 sum = 0; | 462 | UInt32 sum = 0; |
381 | for (i = 0; i < kNumHashValues; i++) | 463 | for (i = 0; i < kNumHashValues; i++) |
382 | { | 464 | { |
383 | UInt32 groupSize = counters[i]; | 465 | const UInt32 groupSize = counters[i]; |
384 | if (groupSize > 0) | 466 | counters[i] = sum; |
467 | sum += groupSize; | ||
468 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | ||
469 | if (groupSize) | ||
385 | { | 470 | { |
386 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 471 | const UInt32 t = sum - 1; |
387 | UInt32 t = sum + groupSize - 1; | 472 | Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask)); |
388 | Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); | ||
389 | #endif | ||
390 | sum += groupSize; | ||
391 | } | 473 | } |
392 | counters[i] = sum - groupSize; | 474 | #endif |
393 | } | 475 | } |
476 | } | ||
394 | 477 | ||
395 | for (i = 0; i < blockSize - 1; i++) | 478 | for (i = 0; i < blockSize - 1; i++) |
396 | Groups[i] = counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]; | 479 | Groups[i] = counters[((unsigned)data[i] << 8) | data[(size_t)i + 1]]; |
397 | Groups[i] = counters[((UInt32)data[i] << 8) | data[0]]; | 480 | Groups[i] = counters[((unsigned)data[i] << 8) | data[0]]; |
481 | |||
482 | { | ||
483 | #define SET_Indices(a, b, i) \ | ||
484 | { UInt32 c; \ | ||
485 | a = (a << 8) | (b); \ | ||
486 | c = counters[a]; \ | ||
487 | Indices[c] = (UInt32)i++; \ | ||
488 | counters[a] = c + 1; \ | ||
489 | } | ||
398 | 490 | ||
399 | for (i = 0; i < blockSize - 1; i++) | 491 | size_t a = data[0]; |
400 | Indices[counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++] = i; | 492 | const Byte *data_ptr = data + 1; |
401 | Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i; | 493 | i = 0; |
402 | 494 | if (blockSize >= 3) | |
403 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 495 | { |
496 | blockSize -= 2; | ||
497 | do | ||
498 | { | ||
499 | size_t b; | ||
500 | b = data_ptr[0]; SET_Indices(a, b, i) | ||
501 | a = data_ptr[1]; SET_Indices(b, a, i) | ||
502 | data_ptr += 2; | ||
503 | } | ||
504 | while (i < blockSize); | ||
505 | blockSize += 2; | ||
506 | } | ||
507 | if (i < blockSize - 1) | ||
404 | { | 508 | { |
509 | SET_Indices(a, data[(size_t)i + 1], i) | ||
510 | a = (Byte)a; | ||
511 | } | ||
512 | SET_Indices(a, data[0], i) | ||
513 | } | ||
514 | |||
515 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | ||
516 | { | ||
405 | UInt32 prev = 0; | 517 | UInt32 prev = 0; |
406 | for (i = 0; i < kNumHashValues; i++) | 518 | for (i = 0; i < kNumHashValues; i++) |
407 | { | 519 | { |
408 | UInt32 prevGroupSize = counters[i] - prev; | 520 | const UInt32 prevGroupSize = counters[i] - prev; |
409 | if (prevGroupSize == 0) | 521 | if (prevGroupSize == 0) |
410 | continue; | 522 | continue; |
411 | SetGroupSize(Indices + prev, prevGroupSize); | 523 | SetGroupSize(Indices + prev, prevGroupSize); |
412 | prev = counters[i]; | 524 | prev = counters[i]; |
413 | } | 525 | } |
414 | } | ||
415 | #endif | ||
416 | } | 526 | } |
527 | #endif | ||
417 | 528 | ||
418 | { | 529 | { |
419 | int NumRefBits; | 530 | unsigned NumRefBits; |
420 | UInt32 NumSortedBytes; | 531 | size_t NumSortedBytes; |
421 | for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++); | 532 | for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++) |
533 | {} | ||
422 | NumRefBits = 32 - NumRefBits; | 534 | NumRefBits = 32 - NumRefBits; |
423 | if (NumRefBits > kNumRefBitsMax) | 535 | if (NumRefBits > kNumRefBitsMax) |
424 | NumRefBits = kNumRefBitsMax; | 536 | NumRefBits = kNumRefBitsMax; |
425 | 537 | ||
426 | for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1) | 538 | for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1) |
427 | { | 539 | { |
428 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 540 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
429 | UInt32 finishedGroupSize = 0; | 541 | size_t finishedGroupSize = 0; |
430 | #endif | 542 | #endif |
431 | UInt32 newLimit = 0; | 543 | size_t newLimit = 0; |
432 | for (i = 0; i < blockSize;) | 544 | for (i = 0; i < blockSize;) |
433 | { | 545 | { |
434 | UInt32 groupSize; | 546 | size_t groupSize; |
435 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 547 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
436 | 548 | ||
437 | if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0) | 549 | if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0) |
438 | { | 550 | { |
@@ -441,56 +553,56 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize) | |||
441 | } | 553 | } |
442 | for (groupSize = 1; | 554 | for (groupSize = 1; |
443 | (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0; | 555 | (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0; |
444 | groupSize++); | 556 | groupSize++) |
445 | 557 | {} | |
446 | groupSize++; | 558 | groupSize++; |
447 | 559 | ||
448 | #else | 560 | #else |
449 | 561 | ||
450 | groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax); | 562 | groupSize = (Indices[i] & ~0xC0000000) >> kNumBitsMax; |
451 | { | 563 | { |
452 | BoolInt finishedGroup = ((Indices[i] & 0x80000000) == 0); | 564 | const BoolInt finishedGroup = ((Indices[i] & 0x80000000) == 0); |
453 | if ((Indices[i] & 0x40000000) != 0) | 565 | if (Indices[i] & 0x40000000) |
454 | { | ||
455 | groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits); | ||
456 | Indices[(size_t)i + 1] &= kIndexMask; | ||
457 | } | ||
458 | Indices[i] &= kIndexMask; | ||
459 | groupSize++; | ||
460 | if (finishedGroup || groupSize == 1) | ||
461 | { | ||
462 | Indices[i - finishedGroupSize] &= kIndexMask; | ||
463 | if (finishedGroupSize > 1) | ||
464 | Indices[(size_t)(i - finishedGroupSize) + 1] &= kIndexMask; | ||
465 | { | 566 | { |
466 | UInt32 newGroupSize = groupSize + finishedGroupSize; | 567 | groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits); |
467 | SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize) | 568 | Indices[(size_t)i + 1] &= kIndexMask; |
468 | finishedGroupSize = newGroupSize; | ||
469 | } | 569 | } |
470 | i += groupSize; | 570 | Indices[i] &= kIndexMask; |
471 | continue; | 571 | groupSize++; |
472 | } | 572 | if (finishedGroup || groupSize == 1) |
473 | finishedGroupSize = 0; | 573 | { |
574 | Indices[i - finishedGroupSize] &= kIndexMask; | ||
575 | if (finishedGroupSize > 1) | ||
576 | Indices[(size_t)(i - finishedGroupSize) + 1] &= kIndexMask; | ||
577 | { | ||
578 | const size_t newGroupSize = groupSize + finishedGroupSize; | ||
579 | SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize) | ||
580 | finishedGroupSize = newGroupSize; | ||
581 | } | ||
582 | i += groupSize; | ||
583 | continue; | ||
584 | } | ||
585 | finishedGroupSize = 0; | ||
474 | } | 586 | } |
475 | 587 | ||
476 | #endif | 588 | #endif |
477 | 589 | ||
478 | if (NumSortedBytes >= blockSize) | 590 | if (NumSortedBytes >= blockSize) |
479 | { | 591 | { |
480 | UInt32 j; | 592 | size_t j; |
481 | for (j = 0; j < groupSize; j++) | 593 | for (j = 0; j < groupSize; j++) |
482 | { | 594 | { |
483 | UInt32 t = (i + j); | 595 | size_t t = i + j; |
484 | /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */ | 596 | /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */ |
485 | Groups[Indices[t]] = t; | 597 | Groups[Indices[t]] = (UInt32)t; |
486 | } | 598 | } |
487 | } | 599 | } |
488 | else | 600 | else |
489 | if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices | 601 | if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices |
490 | #ifndef BLOCK_SORT_USE_HEAP_SORT | 602 | #ifndef BLOCK_SORT_USE_HEAP_SORT |
491 | , 0, blockSize | 603 | , 0, blockSize |
492 | #endif | 604 | #endif |
493 | ) != 0) | 605 | )) |
494 | newLimit = i + groupSize; | 606 | newLimit = i + groupSize; |
495 | i += groupSize; | 607 | i += groupSize; |
496 | } | 608 | } |
@@ -498,19 +610,19 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize) | |||
498 | break; | 610 | break; |
499 | } | 611 | } |
500 | } | 612 | } |
501 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS | 613 | #ifndef BLOCK_SORT_EXTERNAL_FLAGS |
502 | for (i = 0; i < blockSize;) | 614 | for (i = 0; i < blockSize;) |
503 | { | 615 | { |
504 | UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax); | 616 | size_t groupSize = (Indices[i] & ~0xC0000000) >> kNumBitsMax; |
505 | if ((Indices[i] & 0x40000000) != 0) | 617 | if (Indices[i] & 0x40000000) |
506 | { | 618 | { |
507 | groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits); | 619 | groupSize += (Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits; |
508 | Indices[(size_t)i + 1] &= kIndexMask; | 620 | Indices[(size_t)i + 1] &= kIndexMask; |
509 | } | 621 | } |
510 | Indices[i] &= kIndexMask; | 622 | Indices[i] &= kIndexMask; |
511 | groupSize++; | 623 | groupSize++; |
512 | i += groupSize; | 624 | i += groupSize; |
513 | } | 625 | } |
514 | #endif | 626 | #endif |
515 | return Groups[0]; | 627 | return Groups[0]; |
516 | } | 628 | } |
diff --git a/C/BwtSort.h b/C/BwtSort.h index a34b243..1bd2316 100644 --- a/C/BwtSort.h +++ b/C/BwtSort.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* BwtSort.h -- BWT block sorting | 1 | /* BwtSort.h -- BWT block sorting |
2 | 2023-03-03 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_BWT_SORT_H | 4 | #ifndef ZIP7_INC_BWT_SORT_H |
5 | #define ZIP7_INC_BWT_SORT_H | 5 | #define ZIP7_INC_BWT_SORT_H |
@@ -10,16 +10,17 @@ EXTERN_C_BEGIN | |||
10 | 10 | ||
11 | /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ | 11 | /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ |
12 | /* #define BLOCK_SORT_EXTERNAL_FLAGS */ | 12 | /* #define BLOCK_SORT_EXTERNAL_FLAGS */ |
13 | // #define BLOCK_SORT_EXTERNAL_FLAGS | ||
13 | 14 | ||
14 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS | 15 | #ifdef BLOCK_SORT_EXTERNAL_FLAGS |
15 | #define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5)) | 16 | #define BLOCK_SORT_EXTERNAL_SIZE(blockSize) (((blockSize) + 31) >> 5) |
16 | #else | 17 | #else |
17 | #define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0 | 18 | #define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0 |
18 | #endif | 19 | #endif |
19 | 20 | ||
20 | #define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16)) | 21 | #define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16)) |
21 | 22 | ||
22 | UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); | 23 | UInt32 BlockSort(UInt32 *indices, const Byte *data, size_t blockSize); |
23 | 24 | ||
24 | EXTERN_C_END | 25 | EXTERN_C_END |
25 | 26 | ||
diff --git a/C/Compiler.h b/C/Compiler.h index 2a9c2b7..b266b27 100644 --- a/C/Compiler.h +++ b/C/Compiler.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Compiler.h : Compiler specific defines and pragmas | 1 | /* Compiler.h : Compiler specific defines and pragmas |
2 | 2024-01-22 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_COMPILER_H | 4 | #ifndef ZIP7_INC_COMPILER_H |
5 | #define ZIP7_INC_COMPILER_H | 5 | #define ZIP7_INC_COMPILER_H |
@@ -183,6 +183,16 @@ typedef void (*Z7_void_Function)(void); | |||
183 | #define Z7_ATTRIB_NO_VECTORIZE | 183 | #define Z7_ATTRIB_NO_VECTORIZE |
184 | #endif | 184 | #endif |
185 | 185 | ||
186 | #if defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1920) | ||
187 | #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE _Pragma("optimize ( \"s\", on )") | ||
188 | #define Z7_PRAGMA_OPTIMIZE_DEFAULT _Pragma("optimize ( \"\", on )") | ||
189 | #else | ||
190 | #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE | ||
191 | #define Z7_PRAGMA_OPTIMIZE_DEFAULT | ||
192 | #endif | ||
193 | |||
194 | |||
195 | |||
186 | #if defined(MY_CPU_X86_OR_AMD64) && ( \ | 196 | #if defined(MY_CPU_X86_OR_AMD64) && ( \ |
187 | defined(__clang__) && (__clang_major__ >= 4) \ | 197 | defined(__clang__) && (__clang_major__ >= 4) \ |
188 | || defined(__GNUC__) && (__GNUC__ >= 5)) | 198 | || defined(__GNUC__) && (__GNUC__ >= 5)) |
diff --git a/C/CpuArch.c b/C/CpuArch.c index e792f39..6e02551 100644 --- a/C/CpuArch.c +++ b/C/CpuArch.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* CpuArch.c -- CPU specific code | 1 | /* CpuArch.c -- CPU specific code |
2 | 2024-07-04 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -17,7 +17,7 @@ | |||
17 | /* | 17 | /* |
18 | cpuid instruction supports (subFunction) parameter in ECX, | 18 | cpuid instruction supports (subFunction) parameter in ECX, |
19 | that is used only with some specific (function) parameter values. | 19 | that is used only with some specific (function) parameter values. |
20 | But we always use only (subFunction==0). | 20 | most functions use only (subFunction==0). |
21 | */ | 21 | */ |
22 | /* | 22 | /* |
23 | __cpuid(): MSVC and GCC/CLANG use same function/macro name | 23 | __cpuid(): MSVC and GCC/CLANG use same function/macro name |
@@ -49,43 +49,49 @@ | |||
49 | #if defined(MY_CPU_AMD64) && defined(__PIC__) \ | 49 | #if defined(MY_CPU_AMD64) && defined(__PIC__) \ |
50 | && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) | 50 | && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) |
51 | 51 | ||
52 | #define x86_cpuid_MACRO(p, func) { \ | 52 | /* "=&r" selects free register. It can select even rbx, if that register is free. |
53 | "=&D" for (RDI) also works, but the code can be larger with "=&D" | ||
54 | "2"(subFun) : 2 is (zero-based) index in the output constraint list "=c" (ECX). */ | ||
55 | |||
56 | #define x86_cpuid_MACRO_2(p, func, subFunc) { \ | ||
53 | __asm__ __volatile__ ( \ | 57 | __asm__ __volatile__ ( \ |
54 | ASM_LN "mov %%rbx, %q1" \ | 58 | ASM_LN "mov %%rbx, %q1" \ |
55 | ASM_LN "cpuid" \ | 59 | ASM_LN "cpuid" \ |
56 | ASM_LN "xchg %%rbx, %q1" \ | 60 | ASM_LN "xchg %%rbx, %q1" \ |
57 | : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } | 61 | : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } |
58 | |||
59 | /* "=&r" selects free register. It can select even rbx, if that register is free. | ||
60 | "=&D" for (RDI) also works, but the code can be larger with "=&D" | ||
61 | "2"(0) means (subFunction = 0), | ||
62 | 2 is (zero-based) index in the output constraint list "=c" (ECX). */ | ||
63 | 62 | ||
64 | #elif defined(MY_CPU_X86) && defined(__PIC__) \ | 63 | #elif defined(MY_CPU_X86) && defined(__PIC__) \ |
65 | && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) | 64 | && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__)) |
66 | 65 | ||
67 | #define x86_cpuid_MACRO(p, func) { \ | 66 | #define x86_cpuid_MACRO_2(p, func, subFunc) { \ |
68 | __asm__ __volatile__ ( \ | 67 | __asm__ __volatile__ ( \ |
69 | ASM_LN "mov %%ebx, %k1" \ | 68 | ASM_LN "mov %%ebx, %k1" \ |
70 | ASM_LN "cpuid" \ | 69 | ASM_LN "cpuid" \ |
71 | ASM_LN "xchg %%ebx, %k1" \ | 70 | ASM_LN "xchg %%ebx, %k1" \ |
72 | : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } | 71 | : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } |
73 | 72 | ||
74 | #else | 73 | #else |
75 | 74 | ||
76 | #define x86_cpuid_MACRO(p, func) { \ | 75 | #define x86_cpuid_MACRO_2(p, func, subFunc) { \ |
77 | __asm__ __volatile__ ( \ | 76 | __asm__ __volatile__ ( \ |
78 | ASM_LN "cpuid" \ | 77 | ASM_LN "cpuid" \ |
79 | : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); } | 78 | : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); } |
80 | 79 | ||
81 | #endif | 80 | #endif |
82 | 81 | ||
82 | #define x86_cpuid_MACRO(p, func) x86_cpuid_MACRO_2(p, func, 0) | ||
83 | 83 | ||
84 | void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) | 84 | void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) |
85 | { | 85 | { |
86 | x86_cpuid_MACRO(p, func) | 86 | x86_cpuid_MACRO(p, func) |
87 | } | 87 | } |
88 | 88 | ||
89 | static | ||
90 | void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc) | ||
91 | { | ||
92 | x86_cpuid_MACRO_2(p, func, subFunc) | ||
93 | } | ||
94 | |||
89 | 95 | ||
90 | Z7_NO_INLINE | 96 | Z7_NO_INLINE |
91 | UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) | 97 | UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) |
@@ -205,11 +211,39 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) | |||
205 | __asm ret 0 | 211 | __asm ret 0 |
206 | } | 212 | } |
207 | 213 | ||
214 | static | ||
215 | void __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc) | ||
216 | { | ||
217 | UNUSED_VAR(p) | ||
218 | UNUSED_VAR(func) | ||
219 | UNUSED_VAR(subFunc) | ||
220 | __asm push ebx | ||
221 | __asm push edi | ||
222 | __asm mov edi, ecx // p | ||
223 | __asm mov eax, edx // func | ||
224 | __asm mov ecx, [esp + 12] // subFunc | ||
225 | __asm cpuid | ||
226 | __asm mov [edi ], eax | ||
227 | __asm mov [edi + 4], ebx | ||
228 | __asm mov [edi + 8], ecx | ||
229 | __asm mov [edi + 12], edx | ||
230 | __asm pop edi | ||
231 | __asm pop ebx | ||
232 | __asm ret 4 | ||
233 | } | ||
234 | |||
208 | #else // MY_CPU_AMD64 | 235 | #else // MY_CPU_AMD64 |
209 | 236 | ||
210 | #if _MSC_VER >= 1600 | 237 | #if _MSC_VER >= 1600 |
211 | #include <intrin.h> | 238 | #include <intrin.h> |
212 | #define MY_cpuidex __cpuidex | 239 | #define MY_cpuidex __cpuidex |
240 | |||
241 | static | ||
242 | void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc) | ||
243 | { | ||
244 | __cpuidex((int *)p, func, subFunc); | ||
245 | } | ||
246 | |||
213 | #else | 247 | #else |
214 | /* | 248 | /* |
215 | __cpuid (func == (0 or 7)) requires subfunction number in ECX. | 249 | __cpuid (func == (0 or 7)) requires subfunction number in ECX. |
@@ -219,7 +253,7 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) | |||
219 | We still can use __cpuid for low (func) values that don't require ECX, | 253 | We still can use __cpuid for low (func) values that don't require ECX, |
220 | but __cpuid() in old MSVC will be incorrect for some func values: (func == 7). | 254 | but __cpuid() in old MSVC will be incorrect for some func values: (func == 7). |
221 | So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, | 255 | So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, |
222 | where ECX value is first parameter for FASTCALL / NO_INLINE func, | 256 | where ECX value is first parameter for FASTCALL / NO_INLINE func. |
223 | So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and | 257 | So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and |
224 | old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. | 258 | old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. |
225 | 259 | ||
@@ -233,6 +267,11 @@ Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int | |||
233 | } | 267 | } |
234 | #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info) | 268 | #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info) |
235 | #pragma message("======== MY_cpuidex_HACK WAS USED ========") | 269 | #pragma message("======== MY_cpuidex_HACK WAS USED ========") |
270 | static | ||
271 | void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc) | ||
272 | { | ||
273 | MY_cpuidex_HACK(subFunc, func, (Int32 *)p); | ||
274 | } | ||
236 | #endif // _MSC_VER >= 1600 | 275 | #endif // _MSC_VER >= 1600 |
237 | 276 | ||
238 | #if !defined(MY_CPU_AMD64) | 277 | #if !defined(MY_CPU_AMD64) |
@@ -445,6 +484,23 @@ BoolInt CPU_IsSupported_SHA(void) | |||
445 | } | 484 | } |
446 | } | 485 | } |
447 | 486 | ||
487 | |||
488 | BoolInt CPU_IsSupported_SHA512(void) | ||
489 | { | ||
490 | if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here | ||
491 | |||
492 | if (z7_x86_cpuid_GetMaxFunc() < 7) | ||
493 | return False; | ||
494 | { | ||
495 | UInt32 d[4]; | ||
496 | z7_x86_cpuid_subFunc(d, 7, 0); | ||
497 | if (d[0] < 1) // d[0] - is max supported subleaf value | ||
498 | return False; | ||
499 | z7_x86_cpuid_subFunc(d, 7, 1); | ||
500 | return (BoolInt)(d[0]) & 1; | ||
501 | } | ||
502 | } | ||
503 | |||
448 | /* | 504 | /* |
449 | MSVC: _xgetbv() intrinsic is available since VS2010SP1. | 505 | MSVC: _xgetbv() intrinsic is available since VS2010SP1. |
450 | MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in | 506 | MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in |
@@ -776,6 +832,18 @@ BoolInt CPU_IsSupported_NEON(void) | |||
776 | return z7_sysctlbyname_Get_BoolInt("hw.optional.neon"); | 832 | return z7_sysctlbyname_Get_BoolInt("hw.optional.neon"); |
777 | } | 833 | } |
778 | 834 | ||
835 | BoolInt CPU_IsSupported_SHA512(void) | ||
836 | { | ||
837 | return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha512"); | ||
838 | } | ||
839 | |||
840 | /* | ||
841 | BoolInt CPU_IsSupported_SHA3(void) | ||
842 | { | ||
843 | return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha3"); | ||
844 | } | ||
845 | */ | ||
846 | |||
779 | #ifdef MY_CPU_ARM64 | 847 | #ifdef MY_CPU_ARM64 |
780 | #define APPLE_CRYPTO_SUPPORT_VAL 1 | 848 | #define APPLE_CRYPTO_SUPPORT_VAL 1 |
781 | #else | 849 | #else |
@@ -860,6 +928,19 @@ MY_HWCAP_CHECK_FUNC (CRC32) | |||
860 | MY_HWCAP_CHECK_FUNC (SHA1) | 928 | MY_HWCAP_CHECK_FUNC (SHA1) |
861 | MY_HWCAP_CHECK_FUNC (SHA2) | 929 | MY_HWCAP_CHECK_FUNC (SHA2) |
862 | MY_HWCAP_CHECK_FUNC (AES) | 930 | MY_HWCAP_CHECK_FUNC (AES) |
931 | #ifdef MY_CPU_ARM64 | ||
932 | // <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017. | ||
933 | // we define them here, if they are not defined | ||
934 | #ifndef HWCAP_SHA3 | ||
935 | // #define HWCAP_SHA3 (1 << 17) | ||
936 | #endif | ||
937 | #ifndef HWCAP_SHA512 | ||
938 | // #pragma message("=== HWCAP_SHA512 define === ") | ||
939 | #define HWCAP_SHA512 (1 << 21) | ||
940 | #endif | ||
941 | MY_HWCAP_CHECK_FUNC (SHA512) | ||
942 | // MY_HWCAP_CHECK_FUNC (SHA3) | ||
943 | #endif | ||
863 | 944 | ||
864 | #endif // __APPLE__ | 945 | #endif // __APPLE__ |
865 | #endif // _WIN32 | 946 | #endif // _WIN32 |
diff --git a/C/CpuArch.h b/C/CpuArch.h index 683cfaa..1690a5b 100644 --- a/C/CpuArch.h +++ b/C/CpuArch.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* CpuArch.h -- CPU specific code | 1 | /* CpuArch.h -- CPU specific code |
2 | 2024-06-17 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_CPU_ARCH_H | 4 | #ifndef ZIP7_INC_CPU_ARCH_H |
5 | #define ZIP7_INC_CPU_ARCH_H | 5 | #define ZIP7_INC_CPU_ARCH_H |
@@ -47,6 +47,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. | |||
47 | #define MY_CPU_SIZEOF_POINTER 4 | 47 | #define MY_CPU_SIZEOF_POINTER 4 |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #if defined(__SSE2__) \ | ||
51 | || defined(MY_CPU_AMD64) \ | ||
52 | || defined(_M_IX86_FP) && (_M_IX86_FP >= 2) | ||
53 | #define MY_CPU_SSE2 | ||
54 | #endif | ||
55 | |||
50 | 56 | ||
51 | #if defined(_M_ARM64) \ | 57 | #if defined(_M_ARM64) \ |
52 | || defined(_M_ARM64EC) \ | 58 | || defined(_M_ARM64EC) \ |
@@ -509,11 +515,19 @@ problem-4 : performace: | |||
509 | 515 | ||
510 | #if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) | 516 | #if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) |
511 | 517 | ||
518 | #if 0 | ||
519 | // Z7_BSWAP16 can be slow for x86-msvc | ||
520 | #define GetBe16_to32(p) (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p))) | ||
521 | #else | ||
522 | #define GetBe16_to32(p) (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16) | ||
523 | #endif | ||
524 | |||
512 | #define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) | 525 | #define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) |
513 | #define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } | 526 | #define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } |
514 | 527 | ||
515 | #if defined(MY_CPU_LE_UNALIGN_64) | 528 | #if defined(MY_CPU_LE_UNALIGN_64) |
516 | #define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) | 529 | #define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) |
530 | #define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); } | ||
517 | #endif | 531 | #endif |
518 | 532 | ||
519 | #else | 533 | #else |
@@ -536,21 +550,39 @@ problem-4 : performace: | |||
536 | #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) | 550 | #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) |
537 | #endif | 551 | #endif |
538 | 552 | ||
553 | #ifndef SetBe64 | ||
554 | #define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \ | ||
555 | _ppp_[0] = (Byte)(_vvv_ >> 56); \ | ||
556 | _ppp_[1] = (Byte)(_vvv_ >> 48); \ | ||
557 | _ppp_[2] = (Byte)(_vvv_ >> 40); \ | ||
558 | _ppp_[3] = (Byte)(_vvv_ >> 32); \ | ||
559 | _ppp_[4] = (Byte)(_vvv_ >> 24); \ | ||
560 | _ppp_[5] = (Byte)(_vvv_ >> 16); \ | ||
561 | _ppp_[6] = (Byte)(_vvv_ >> 8); \ | ||
562 | _ppp_[7] = (Byte)_vvv_; } | ||
563 | #endif | ||
564 | |||
539 | #ifndef GetBe16 | 565 | #ifndef GetBe16 |
566 | #ifdef GetBe16_to32 | ||
567 | #define GetBe16(p) ( (UInt16) GetBe16_to32(p)) | ||
568 | #else | ||
540 | #define GetBe16(p) ( (UInt16) ( \ | 569 | #define GetBe16(p) ( (UInt16) ( \ |
541 | ((UInt16)((const Byte *)(p))[0] << 8) | \ | 570 | ((UInt16)((const Byte *)(p))[0] << 8) | \ |
542 | ((const Byte *)(p))[1] )) | 571 | ((const Byte *)(p))[1] )) |
543 | #endif | 572 | #endif |
573 | #endif | ||
544 | 574 | ||
545 | 575 | ||
546 | #if defined(MY_CPU_BE) | 576 | #if defined(MY_CPU_BE) |
547 | #define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) | 577 | #define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) |
548 | #define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) | 578 | #define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) |
549 | #define Z7_CONV_NATIVE_TO_BE_32(v) (v) | 579 | #define Z7_CONV_NATIVE_TO_BE_32(v) (v) |
580 | // #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b1) | ((b0) << 8)) | ||
550 | #elif defined(MY_CPU_LE) | 581 | #elif defined(MY_CPU_LE) |
551 | #define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) | 582 | #define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) |
552 | #define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) | 583 | #define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) |
553 | #define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v) | 584 | #define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v) |
585 | // #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b0) | ((b1) << 8)) | ||
554 | #else | 586 | #else |
555 | #error Stop_Compiling_Unknown_Endian_CONV | 587 | #error Stop_Compiling_Unknown_Endian_CONV |
556 | #endif | 588 | #endif |
@@ -589,6 +621,11 @@ problem-4 : performace: | |||
589 | #endif | 621 | #endif |
590 | 622 | ||
591 | 623 | ||
624 | #ifndef GetBe16_to32 | ||
625 | #define GetBe16_to32(p) GetBe16(p) | ||
626 | #endif | ||
627 | |||
628 | |||
592 | #if defined(MY_CPU_X86_OR_AMD64) \ | 629 | #if defined(MY_CPU_X86_OR_AMD64) \ |
593 | || defined(MY_CPU_ARM_OR_ARM64) \ | 630 | || defined(MY_CPU_ARM_OR_ARM64) \ |
594 | || defined(MY_CPU_PPC_OR_PPC64) | 631 | || defined(MY_CPU_PPC_OR_PPC64) |
@@ -617,6 +654,7 @@ BoolInt CPU_IsSupported_SSE2(void); | |||
617 | BoolInt CPU_IsSupported_SSSE3(void); | 654 | BoolInt CPU_IsSupported_SSSE3(void); |
618 | BoolInt CPU_IsSupported_SSE41(void); | 655 | BoolInt CPU_IsSupported_SSE41(void); |
619 | BoolInt CPU_IsSupported_SHA(void); | 656 | BoolInt CPU_IsSupported_SHA(void); |
657 | BoolInt CPU_IsSupported_SHA512(void); | ||
620 | BoolInt CPU_IsSupported_PageGB(void); | 658 | BoolInt CPU_IsSupported_PageGB(void); |
621 | 659 | ||
622 | #elif defined(MY_CPU_ARM_OR_ARM64) | 660 | #elif defined(MY_CPU_ARM_OR_ARM64) |
@@ -634,6 +672,7 @@ BoolInt CPU_IsSupported_SHA1(void); | |||
634 | BoolInt CPU_IsSupported_SHA2(void); | 672 | BoolInt CPU_IsSupported_SHA2(void); |
635 | BoolInt CPU_IsSupported_AES(void); | 673 | BoolInt CPU_IsSupported_AES(void); |
636 | #endif | 674 | #endif |
675 | BoolInt CPU_IsSupported_SHA512(void); | ||
637 | 676 | ||
638 | #endif | 677 | #endif |
639 | 678 | ||
diff --git a/C/HuffEnc.c b/C/HuffEnc.c index 996da30..cbf8c22 100644 --- a/C/HuffEnc.c +++ b/C/HuffEnc.c | |||
@@ -1,60 +1,125 @@ | |||
1 | /* HuffEnc.c -- functions for Huffman encoding | 1 | /* HuffEnc.c -- functions for Huffman encoding |
2 | 2023-09-07 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
6 | #include <string.h> | ||
7 | |||
6 | #include "HuffEnc.h" | 8 | #include "HuffEnc.h" |
7 | #include "Sort.h" | 9 | #include "Sort.h" |
10 | #include "CpuArch.h" | ||
8 | 11 | ||
9 | #define kMaxLen 16 | 12 | #define kMaxLen Z7_HUFFMAN_LEN_MAX |
10 | #define NUM_BITS 10 | 13 | #define NUM_BITS 10 |
11 | #define MASK ((1u << NUM_BITS) - 1) | 14 | #define MASK ((1u << NUM_BITS) - 1) |
12 | 15 | #define FREQ_MASK (~(UInt32)MASK) | |
13 | #define NUM_COUNTERS 64 | 16 | #define NUM_COUNTERS (48 * 2) |
14 | 17 | ||
15 | #define HUFFMAN_SPEED_OPT | 18 | #if 1 && (defined(MY_CPU_LE) || defined(MY_CPU_BE)) |
19 | #if defined(MY_CPU_LE) | ||
20 | #define HI_HALF_OFFSET 1 | ||
21 | #else | ||
22 | #define HI_HALF_OFFSET 0 | ||
23 | #endif | ||
24 | #define LOAD_PARENT(p) ((unsigned)*((const UInt16 *)(p) + HI_HALF_OFFSET)) | ||
25 | #define STORE_PARENT(p, fb, val) *((UInt16 *)(p) + HI_HALF_OFFSET) = (UInt16)(val); | ||
26 | #define STORE_PARENT_DIRECT(p, fb, hi) STORE_PARENT(p, fb, hi) | ||
27 | #define UPDATE_E(eHi) eHi++; | ||
28 | #else | ||
29 | #define LOAD_PARENT(p) ((unsigned)(*(p) >> NUM_BITS)) | ||
30 | #define STORE_PARENT_DIRECT(p, fb, hi) *(p) = ((fb) & MASK) | (hi); // set parent field | ||
31 | #define STORE_PARENT(p, fb, val) STORE_PARENT_DIRECT(p, fb, ((UInt32)(val) << NUM_BITS)) | ||
32 | #define UPDATE_E(eHi) eHi += 1 << NUM_BITS; | ||
33 | #endif | ||
16 | 34 | ||
17 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) | 35 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned numSymbols, unsigned maxLen) |
18 | { | 36 | { |
19 | UInt32 num = 0; | 37 | #if NUM_COUNTERS > 2 |
20 | /* if (maxLen > 10) maxLen = 10; */ | 38 | unsigned counters[NUM_COUNTERS]; |
39 | #endif | ||
40 | #if 1 && NUM_COUNTERS > (kMaxLen + 4) * 2 | ||
41 | #define lenCounters (counters) | ||
42 | #define codes (counters + kMaxLen + 4) | ||
43 | #else | ||
44 | unsigned lenCounters[kMaxLen + 1]; | ||
45 | UInt32 codes[kMaxLen + 1]; | ||
46 | #endif | ||
47 | |||
48 | unsigned num; | ||
21 | { | 49 | { |
22 | UInt32 i; | 50 | unsigned i; |
23 | 51 | // UInt32 sum = 0; | |
24 | #ifdef HUFFMAN_SPEED_OPT | 52 | |
53 | #if NUM_COUNTERS > 2 | ||
25 | 54 | ||
26 | UInt32 counters[NUM_COUNTERS]; | 55 | #define CTR_ITEM_FOR_FREQ(freq) \ |
56 | counters[(freq) >= NUM_COUNTERS - 1 ? NUM_COUNTERS - 1 : (unsigned)(freq)] | ||
57 | |||
27 | for (i = 0; i < NUM_COUNTERS; i++) | 58 | for (i = 0; i < NUM_COUNTERS; i++) |
28 | counters[i] = 0; | 59 | counters[i] = 0; |
29 | for (i = 0; i < numSymbols; i++) | 60 | memset(lens, 0, numSymbols); |
30 | { | 61 | { |
31 | UInt32 freq = freqs[i]; | 62 | const UInt32 *fp = freqs + numSymbols; |
32 | counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; | 63 | #define NUM_UNROLLS 1 |
64 | #if NUM_UNROLLS > 1 // use 1 if odd (numSymbols) is possisble | ||
65 | if (numSymbols & 1) | ||
66 | { | ||
67 | UInt32 f; | ||
68 | f = *--fp; CTR_ITEM_FOR_FREQ(f)++; | ||
69 | // sum += f; | ||
70 | } | ||
71 | #endif | ||
72 | do | ||
73 | { | ||
74 | UInt32 f; | ||
75 | fp -= NUM_UNROLLS; | ||
76 | f = fp[0]; CTR_ITEM_FOR_FREQ(f)++; | ||
77 | // sum += f; | ||
78 | #if NUM_UNROLLS > 1 | ||
79 | f = fp[1]; CTR_ITEM_FOR_FREQ(f)++; | ||
80 | // sum += f; | ||
81 | #endif | ||
82 | } | ||
83 | while (fp != freqs); | ||
33 | } | 84 | } |
34 | 85 | #if 0 | |
35 | for (i = 1; i < NUM_COUNTERS; i++) | 86 | printf("\nsum=%8u numSymbols =%3u ctrs:", sum, numSymbols); |
36 | { | 87 | { |
37 | UInt32 temp = counters[i]; | 88 | unsigned k = 0; |
38 | counters[i] = num; | 89 | for (k = 0; k < NUM_COUNTERS; k++) |
39 | num += temp; | 90 | printf(" %u", counters[k]); |
40 | } | 91 | } |
41 | 92 | #endif | |
42 | for (i = 0; i < numSymbols; i++) | 93 | |
94 | num = counters[1]; | ||
95 | counters[1] = 0; | ||
96 | for (i = 2; i != NUM_COUNTERS; i += 2) | ||
43 | { | 97 | { |
44 | UInt32 freq = freqs[i]; | 98 | unsigned c; |
45 | if (freq == 0) | 99 | c = (counters )[i]; (counters )[i] = num; num += c; |
46 | lens[i] = 0; | 100 | c = (counters + 1)[i]; (counters + 1)[i] = num; num += c; |
47 | else | 101 | } |
48 | p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); | 102 | counters[0] = num; // we want to write (freq==0) symbols to the end of (p) array |
103 | { | ||
104 | i = 0; | ||
105 | do | ||
106 | { | ||
107 | const UInt32 f = freqs[i]; | ||
108 | #if 0 | ||
109 | if (f == 0) lens[i] = 0; else | ||
110 | #endif | ||
111 | p[CTR_ITEM_FOR_FREQ(f)++] = i | (f << NUM_BITS); | ||
112 | } | ||
113 | while (++i != numSymbols); | ||
49 | } | 114 | } |
50 | counters[0] = 0; | ||
51 | HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); | 115 | HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); |
52 | 116 | ||
53 | #else | 117 | #else // NUM_COUNTERS <= 2 |
54 | 118 | ||
119 | num = 0; | ||
55 | for (i = 0; i < numSymbols; i++) | 120 | for (i = 0; i < numSymbols; i++) |
56 | { | 121 | { |
57 | UInt32 freq = freqs[i]; | 122 | const UInt32 freq = freqs[i]; |
58 | if (freq == 0) | 123 | if (freq == 0) |
59 | lens[i] = 0; | 124 | lens[i] = 0; |
60 | else | 125 | else |
@@ -62,17 +127,27 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb | |||
62 | } | 127 | } |
63 | HeapSort(p, num); | 128 | HeapSort(p, num); |
64 | 129 | ||
65 | #endif | 130 | #endif |
66 | } | 131 | } |
67 | 132 | ||
68 | if (num < 2) | 133 | if (num <= 2) |
69 | { | 134 | { |
70 | unsigned minCode = 0; | 135 | unsigned minCode = 0; |
71 | unsigned maxCode = 1; | 136 | unsigned maxCode = 1; |
72 | if (num == 1) | 137 | if (num) |
73 | { | 138 | { |
74 | maxCode = (unsigned)p[0] & MASK; | 139 | maxCode = (unsigned)p[(size_t)num - 1] & MASK; |
75 | if (maxCode == 0) | 140 | if (num == 2) |
141 | { | ||
142 | minCode = (unsigned)p[0] & MASK; | ||
143 | if (minCode > maxCode) | ||
144 | { | ||
145 | const unsigned temp = minCode; | ||
146 | minCode = maxCode; | ||
147 | maxCode = temp; | ||
148 | } | ||
149 | } | ||
150 | else if (maxCode == 0) | ||
76 | maxCode++; | 151 | maxCode++; |
77 | } | 152 | } |
78 | p[minCode] = 0; | 153 | p[minCode] = 0; |
@@ -80,69 +155,191 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb | |||
80 | lens[minCode] = lens[maxCode] = 1; | 155 | lens[minCode] = lens[maxCode] = 1; |
81 | return; | 156 | return; |
82 | } | 157 | } |
83 | |||
84 | { | 158 | { |
85 | UInt32 b, e, i; | 159 | unsigned i; |
86 | 160 | for (i = 0; i <= kMaxLen; i++) | |
87 | i = b = e = 0; | 161 | lenCounters[i] = 0; |
88 | do | 162 | lenCounters[1] = 2; // by default root node has 2 child leaves at level 1. |
163 | } | ||
164 | // if (num != 2) | ||
165 | { | ||
166 | // num > 2 | ||
167 | // the binary tree will contain (num - 1) internal nodes. | ||
168 | // p[num - 2] will be root node of binary tree. | ||
169 | UInt32 *b; | ||
170 | UInt32 *n; | ||
171 | // first node will have two leaf childs: p[0] and p[1]: | ||
172 | // p[0] += p[1] & FREQ_MASK; // set frequency sum of child leafs | ||
173 | // if (pi == n) exit(0); | ||
174 | // if (pi != n) | ||
89 | { | 175 | { |
90 | UInt32 n, m, freq; | 176 | UInt32 fb = (p[1] & FREQ_MASK) + p[0]; |
91 | n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; | 177 | UInt32 f = p[2] & FREQ_MASK; |
92 | freq = (p[n] & ~MASK); | 178 | const UInt32 *pi = p + 2; |
93 | p[n] = (p[n] & MASK) | (e << NUM_BITS); | 179 | UInt32 *e = p; |
94 | m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; | 180 | UInt32 eHi = 0; |
95 | freq += (p[m] & ~MASK); | 181 | n = p + num; |
96 | p[m] = (p[m] & MASK) | (e << NUM_BITS); | 182 | b = p; |
97 | p[e] = (p[e] & MASK) | freq; | 183 | // p[0] = fb; |
98 | e++; | 184 | for (;;) |
185 | { | ||
186 | // (b <= e) | ||
187 | UInt32 sum; | ||
188 | e++; | ||
189 | UPDATE_E(eHi) | ||
190 | |||
191 | // (b < e) | ||
192 | |||
193 | // p range : high bits | ||
194 | // [0, b) : parent : processed nodes that have parent and childs | ||
195 | // [b, e) : FREQ : non-processed nodes that have no parent but have childs | ||
196 | // [e, pi) : FREQ : processed leaves for which parent node was created | ||
197 | // [pi, n) : FREQ : non-processed leaves for which parent node was not created | ||
198 | |||
199 | // first child | ||
200 | // note : (*b < f) is same result as ((*b & FREQ_MASK) < f) | ||
201 | if (fb < f) | ||
202 | { | ||
203 | // node freq is smaller | ||
204 | sum = fb & FREQ_MASK; | ||
205 | STORE_PARENT_DIRECT (b, fb, eHi) | ||
206 | b++; | ||
207 | fb = *b; | ||
208 | if (b == e) | ||
209 | { | ||
210 | if (++pi == n) | ||
211 | break; | ||
212 | sum += f; | ||
213 | fb &= MASK; | ||
214 | fb |= sum; | ||
215 | *e = fb; | ||
216 | f = *pi & FREQ_MASK; | ||
217 | continue; | ||
218 | } | ||
219 | } | ||
220 | else if (++pi == n) | ||
221 | { | ||
222 | STORE_PARENT_DIRECT (b, fb, eHi) | ||
223 | b++; | ||
224 | break; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | sum = f; | ||
229 | f = *pi & FREQ_MASK; | ||
230 | } | ||
231 | |||
232 | // (b < e) | ||
233 | |||
234 | // second child | ||
235 | if (fb < f) | ||
236 | { | ||
237 | sum += fb; | ||
238 | sum &= FREQ_MASK; | ||
239 | STORE_PARENT_DIRECT (b, fb, eHi) | ||
240 | b++; | ||
241 | *e = (*e & MASK) | sum; // set frequency sum | ||
242 | // (b <= e) is possible here | ||
243 | fb = *b; | ||
244 | } | ||
245 | else if (++pi == n) | ||
246 | break; | ||
247 | else | ||
248 | { | ||
249 | sum += f; | ||
250 | f = *pi & FREQ_MASK; | ||
251 | *e = (*e & MASK) | sum; // set frequency sum | ||
252 | } | ||
253 | } | ||
99 | } | 254 | } |
100 | while (num - e > 1); | ||
101 | 255 | ||
256 | // printf("\nnum-e=%3u, numSymbols=%3u, num=%3u, b=%3u", n - e, numSymbols, n - p, b - p); | ||
102 | { | 257 | { |
103 | UInt32 lenCounters[kMaxLen + 1]; | 258 | n -= 2; |
104 | for (i = 0; i <= kMaxLen; i++) | 259 | *n &= MASK; // root node : we clear high bits (zero bits mean level == 0) |
105 | lenCounters[i] = 0; | 260 | if (n != b) |
106 | |||
107 | p[--e] &= MASK; | ||
108 | lenCounters[1] = 2; | ||
109 | while (e != 0) | ||
110 | { | ||
111 | UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; | ||
112 | p[e] = (p[e] & MASK) | (len << NUM_BITS); | ||
113 | if (len >= maxLen) | ||
114 | for (len = maxLen - 1; lenCounters[len] == 0; len--); | ||
115 | lenCounters[len]--; | ||
116 | lenCounters[(size_t)len + 1] += 2; | ||
117 | } | ||
118 | |||
119 | { | 261 | { |
120 | UInt32 len; | 262 | // We go here, if we have some number of non-created nodes up to root. |
121 | i = 0; | 263 | // We process them in simplified code: |
122 | for (len = maxLen; len != 0; len--) | 264 | // position of parent for each pair of nodes is known. |
265 | // n[-2], n[-1] : current pair of child nodes | ||
266 | // (p1) : parent node for current pair. | ||
267 | UInt32 *p1 = n; | ||
268 | do | ||
123 | { | 269 | { |
124 | UInt32 k; | 270 | const unsigned len = LOAD_PARENT(p1) + 1; |
125 | for (k = lenCounters[len]; k != 0; k--) | 271 | p1--; |
126 | lens[p[i++] & MASK] = (Byte)len; | 272 | (lenCounters )[len] -= 2; // we remove 2 leaves from level (len) |
273 | (lenCounters + 1)[len] += 2 * 2; // we add 4 leaves at level (len + 1) | ||
274 | n -= 2; | ||
275 | STORE_PARENT (n , n[0], len) | ||
276 | STORE_PARENT (n + 1, n[1], len) | ||
127 | } | 277 | } |
278 | while (n != b); | ||
128 | } | 279 | } |
129 | 280 | } | |
281 | |||
282 | if (b != p) | ||
283 | { | ||
284 | // we detect level of each node (realtive to root), | ||
285 | // and update lenCounters[]. | ||
286 | // We process only intermediate nodes and we don't process leaves. | ||
287 | do | ||
130 | { | 288 | { |
131 | UInt32 nextCodes[kMaxLen + 1]; | 289 | // if (ii < b) : parent_bits_of (p[ii]) == index of parent node : ii < (p[ii]) |
132 | { | 290 | // if (ii >= b) : parent_bits_of (p[ii]) == level of this (ii) node in tree |
133 | UInt32 code = 0; | 291 | unsigned len; |
134 | UInt32 len; | 292 | b--; |
135 | for (len = 1; len <= kMaxLen; len++) | 293 | len = (unsigned)LOAD_PARENT(p + LOAD_PARENT(b)) + 1; |
136 | nextCodes[len] = code = (code + lenCounters[(size_t)len - 1]) << 1; | 294 | STORE_PARENT (b, *b, len) |
137 | } | 295 | if (len >= maxLen) |
138 | /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ | ||
139 | |||
140 | { | 296 | { |
141 | UInt32 k; | 297 | // We are not allowed to create node at level (maxLen) and higher, |
142 | for (k = 0; k < numSymbols; k++) | 298 | // because all leaves must be placed to level (maxLen) or lower. |
143 | p[k] = nextCodes[lens[k]]++; | 299 | // We find nearest allowed leaf and place current node to level of that leaf: |
300 | for (len = maxLen - 1; lenCounters[len] == 0; len--) {} | ||
144 | } | 301 | } |
302 | lenCounters[len]--; // we remove 1 leaf from level (len) | ||
303 | (lenCounters + 1)[len] += 2; // we add 2 leaves at level (len + 1) | ||
304 | } | ||
305 | while (b != p); | ||
306 | } | ||
307 | } | ||
308 | { | ||
309 | { | ||
310 | unsigned len = maxLen; | ||
311 | const UInt32 *p2 = p; | ||
312 | do | ||
313 | { | ||
314 | unsigned k = lenCounters[len]; | ||
315 | if (k) | ||
316 | do | ||
317 | lens[(unsigned)*p2++ & MASK] = (Byte)len; | ||
318 | while (--k); | ||
319 | } | ||
320 | while (--len); | ||
321 | } | ||
322 | codes[0] = 0; // we don't want garbage values to be written to p[] array. | ||
323 | // codes[1] = 0; | ||
324 | { | ||
325 | UInt32 code = 0; | ||
326 | unsigned len; | ||
327 | for (len = 0; len < kMaxLen; len++) | ||
328 | (codes + 1)[len] = code = (code + lenCounters[len]) << 1; | ||
329 | } | ||
330 | /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ | ||
331 | { | ||
332 | const Byte * const limit = lens + numSymbols; | ||
333 | do | ||
334 | { | ||
335 | unsigned len; | ||
336 | UInt32 c; | ||
337 | len = lens[0]; c = codes[len]; p[0] = c; codes[len] = c + 1; | ||
338 | // len = lens[1]; c = codes[len]; p[1] = c; codes[len] = c + 1; | ||
339 | p += 1; | ||
340 | lens += 1; | ||
145 | } | 341 | } |
342 | while (lens != limit); | ||
146 | } | 343 | } |
147 | } | 344 | } |
148 | } | 345 | } |
@@ -150,5 +347,14 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb | |||
150 | #undef kMaxLen | 347 | #undef kMaxLen |
151 | #undef NUM_BITS | 348 | #undef NUM_BITS |
152 | #undef MASK | 349 | #undef MASK |
350 | #undef FREQ_MASK | ||
153 | #undef NUM_COUNTERS | 351 | #undef NUM_COUNTERS |
154 | #undef HUFFMAN_SPEED_OPT | 352 | #undef CTR_ITEM_FOR_FREQ |
353 | #undef LOAD_PARENT | ||
354 | #undef STORE_PARENT | ||
355 | #undef STORE_PARENT_DIRECT | ||
356 | #undef UPDATE_E | ||
357 | #undef HI_HALF_OFFSET | ||
358 | #undef NUM_UNROLLS | ||
359 | #undef lenCounters | ||
360 | #undef codes | ||
diff --git a/C/HuffEnc.h b/C/HuffEnc.h index cbc5d11..2217f55 100644 --- a/C/HuffEnc.h +++ b/C/HuffEnc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* HuffEnc.h -- Huffman encoding | 1 | /* HuffEnc.h -- Huffman encoding |
2 | 2023-03-05 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_HUFF_ENC_H | 4 | #ifndef ZIP7_INC_HUFF_ENC_H |
5 | #define ZIP7_INC_HUFF_ENC_H | 5 | #define ZIP7_INC_HUFF_ENC_H |
@@ -8,14 +8,14 @@ | |||
8 | 8 | ||
9 | EXTERN_C_BEGIN | 9 | EXTERN_C_BEGIN |
10 | 10 | ||
11 | #define Z7_HUFFMAN_LEN_MAX 16 | ||
11 | /* | 12 | /* |
12 | Conditions: | 13 | Conditions: |
13 | num <= 1024 = 2 ^ NUM_BITS | 14 | 2 <= num <= 1024 = 2 ^ NUM_BITS |
14 | Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) | 15 | Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) |
15 | maxLen <= 16 = kMaxLen | 16 | 1 <= maxLen <= 16 = Z7_HUFFMAN_LEN_MAX |
16 | Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) | 17 | Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) |
17 | */ | 18 | */ |
18 | |||
19 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); | 19 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); |
20 | 20 | ||
21 | EXTERN_C_END | 21 | EXTERN_C_END |
@@ -1,5 +1,5 @@ | |||
1 | /* LzFind.c -- Match finder for LZ algorithms | 1 | /* LzFind.c -- Match finder for LZ algorithms |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -404,7 +404,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, | |||
404 | const unsigned nbMax = | 404 | const unsigned nbMax = |
405 | (p->numHashBytes == 2 ? 16 : | 405 | (p->numHashBytes == 2 ? 16 : |
406 | (p->numHashBytes == 3 ? 24 : 32)); | 406 | (p->numHashBytes == 3 ? 24 : 32)); |
407 | if (numBits > nbMax) | 407 | if (numBits >= nbMax) |
408 | numBits = nbMax; | 408 | numBits = nbMax; |
409 | if (numBits >= 32) | 409 | if (numBits >= 32) |
410 | hs = (UInt32)0 - 1; | 410 | hs = (UInt32)0 - 1; |
@@ -416,14 +416,14 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, | |||
416 | hs |= (256 << kLzHash_CrcShift_2) - 1; | 416 | hs |= (256 << kLzHash_CrcShift_2) - 1; |
417 | { | 417 | { |
418 | const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize); | 418 | const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize); |
419 | if (hs > hs2) | 419 | if (hs >= hs2) |
420 | hs = hs2; | 420 | hs = hs2; |
421 | } | 421 | } |
422 | hsCur = hs; | 422 | hsCur = hs; |
423 | if (p->expectedDataSize < historySize) | 423 | if (p->expectedDataSize < historySize) |
424 | { | 424 | { |
425 | const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize); | 425 | const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize); |
426 | if (hsCur > hs2) | 426 | if (hsCur >= hs2) |
427 | hsCur = hs2; | 427 | hsCur = hs2; |
428 | } | 428 | } |
429 | } | 429 | } |
@@ -434,7 +434,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, | |||
434 | if (p->expectedDataSize < historySize) | 434 | if (p->expectedDataSize < historySize) |
435 | { | 435 | { |
436 | hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize); | 436 | hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize); |
437 | if (hsCur > hs) // is it possible? | 437 | if (hsCur >= hs) // is it possible? |
438 | hsCur = hs; | 438 | hsCur = hs; |
439 | } | 439 | } |
440 | } | 440 | } |
@@ -598,7 +598,7 @@ void MatchFinder_Init(void *_p) | |||
598 | 598 | ||
599 | #ifdef MY_CPU_X86_OR_AMD64 | 599 | #ifdef MY_CPU_X86_OR_AMD64 |
600 | #if defined(__clang__) && (__clang_major__ >= 4) \ | 600 | #if defined(__clang__) && (__clang_major__ >= 4) \ |
601 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) | 601 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) |
602 | // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) | 602 | // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) |
603 | 603 | ||
604 | #define USE_LZFIND_SATUR_SUB_128 | 604 | #define USE_LZFIND_SATUR_SUB_128 |
@@ -890,7 +890,7 @@ static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, | |||
890 | return d; | 890 | return d; |
891 | { | 891 | { |
892 | const Byte *pb = cur - delta; | 892 | const Byte *pb = cur - delta; |
893 | curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; | 893 | curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)]; |
894 | if (pb[maxLen] == cur[maxLen] && *pb == *cur) | 894 | if (pb[maxLen] == cur[maxLen] && *pb == *cur) |
895 | { | 895 | { |
896 | UInt32 len = 0; | 896 | UInt32 len = 0; |
@@ -925,7 +925,7 @@ static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, | |||
925 | break; | 925 | break; |
926 | { | 926 | { |
927 | ptrdiff_t diff; | 927 | ptrdiff_t diff; |
928 | curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; | 928 | curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)]; |
929 | diff = (ptrdiff_t)0 - (ptrdiff_t)delta; | 929 | diff = (ptrdiff_t)0 - (ptrdiff_t)delta; |
930 | if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) | 930 | if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) |
931 | { | 931 | { |
@@ -972,7 +972,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt | |||
972 | // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } | 972 | // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } |
973 | 973 | ||
974 | cmCheck = (UInt32)(pos - _cyclicBufferSize); | 974 | cmCheck = (UInt32)(pos - _cyclicBufferSize); |
975 | if ((UInt32)pos <= _cyclicBufferSize) | 975 | if ((UInt32)pos < _cyclicBufferSize) |
976 | cmCheck = 0; | 976 | cmCheck = 0; |
977 | 977 | ||
978 | if (cmCheck < curMatch) | 978 | if (cmCheck < curMatch) |
@@ -980,7 +980,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt | |||
980 | { | 980 | { |
981 | const UInt32 delta = pos - curMatch; | 981 | const UInt32 delta = pos - curMatch; |
982 | { | 982 | { |
983 | CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); | 983 | CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1); |
984 | const Byte *pb = cur - delta; | 984 | const Byte *pb = cur - delta; |
985 | unsigned len = (len0 < len1 ? len0 : len1); | 985 | unsigned len = (len0 < len1 ? len0 : len1); |
986 | const UInt32 pair0 = pair[0]; | 986 | const UInt32 pair0 = pair[0]; |
@@ -1039,7 +1039,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const | |||
1039 | UInt32 cmCheck; | 1039 | UInt32 cmCheck; |
1040 | 1040 | ||
1041 | cmCheck = (UInt32)(pos - _cyclicBufferSize); | 1041 | cmCheck = (UInt32)(pos - _cyclicBufferSize); |
1042 | if ((UInt32)pos <= _cyclicBufferSize) | 1042 | if ((UInt32)pos < _cyclicBufferSize) |
1043 | cmCheck = 0; | 1043 | cmCheck = 0; |
1044 | 1044 | ||
1045 | if (// curMatch >= pos || // failure | 1045 | if (// curMatch >= pos || // failure |
@@ -1048,7 +1048,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const | |||
1048 | { | 1048 | { |
1049 | const UInt32 delta = pos - curMatch; | 1049 | const UInt32 delta = pos - curMatch; |
1050 | { | 1050 | { |
1051 | CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); | 1051 | CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1); |
1052 | const Byte *pb = cur - delta; | 1052 | const Byte *pb = cur - delta; |
1053 | unsigned len = (len0 < len1 ? len0 : len1); | 1053 | unsigned len = (len0 < len1 ? len0 : len1); |
1054 | if (pb[len] == cur[len]) | 1054 | if (pb[len] == cur[len]) |
@@ -1595,7 +1595,7 @@ static void Bt5_MatchFinder_Skip(void *_p, UInt32 num) | |||
1595 | UInt32 pos = p->pos; \ | 1595 | UInt32 pos = p->pos; \ |
1596 | UInt32 num2 = num; \ | 1596 | UInt32 num2 = num; \ |
1597 | /* (p->pos == p->posLimit) is not allowed here !!! */ \ | 1597 | /* (p->pos == p->posLimit) is not allowed here !!! */ \ |
1598 | { const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \ | 1598 | { const UInt32 rem = p->posLimit - pos; if (num2 >= rem) num2 = rem; } \ |
1599 | num -= num2; \ | 1599 | num -= num2; \ |
1600 | { const UInt32 cycPos = p->cyclicBufferPos; \ | 1600 | { const UInt32 cycPos = p->cyclicBufferPos; \ |
1601 | son = p->son + cycPos; \ | 1601 | son = p->son + cycPos; \ |
diff --git a/C/LzFindMt.c b/C/LzFindMt.c index ac9d59d..25fcc46 100644 --- a/C/LzFindMt.c +++ b/C/LzFindMt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* LzFindMt.c -- multithreaded Match finder for LZ algorithms | 1 | /* LzFindMt.c -- multithreaded Match finder for LZ algorithms |
2 | 2024-01-22 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -82,6 +82,8 @@ extern UInt64 g_NumIters_Bytes; | |||
82 | Z7_NO_INLINE | 82 | Z7_NO_INLINE |
83 | static void MtSync_Construct(CMtSync *p) | 83 | static void MtSync_Construct(CMtSync *p) |
84 | { | 84 | { |
85 | p->affinityGroup = -1; | ||
86 | p->affinityInGroup = 0; | ||
85 | p->affinity = 0; | 87 | p->affinity = 0; |
86 | p->wasCreated = False; | 88 | p->wasCreated = False; |
87 | p->csWasInitialized = False; | 89 | p->csWasInitialized = False; |
@@ -259,6 +261,12 @@ static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void * | |||
259 | // return ERROR_TOO_MANY_POSTS; // for debug | 261 | // return ERROR_TOO_MANY_POSTS; // for debug |
260 | // return EINVAL; // for debug | 262 | // return EINVAL; // for debug |
261 | 263 | ||
264 | #ifdef _WIN32 | ||
265 | if (p->affinityGroup >= 0) | ||
266 | wres = Thread_Create_With_Group(&p->thread, startAddress, obj, | ||
267 | (unsigned)(UInt32)p->affinityGroup, (CAffinityMask)p->affinityInGroup); | ||
268 | else | ||
269 | #endif | ||
262 | if (p->affinity != 0) | 270 | if (p->affinity != 0) |
263 | wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); | 271 | wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); |
264 | else | 272 | else |
diff --git a/C/LzFindMt.h b/C/LzFindMt.h index fcb479d..89984f5 100644 --- a/C/LzFindMt.h +++ b/C/LzFindMt.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* LzFindMt.h -- multithreaded Match finder for LZ algorithms | 1 | /* LzFindMt.h -- multithreaded Match finder for LZ algorithms |
2 | 2024-01-22 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_LZ_FIND_MT_H | 4 | #ifndef ZIP7_INC_LZ_FIND_MT_H |
5 | #define ZIP7_INC_LZ_FIND_MT_H | 5 | #define ZIP7_INC_LZ_FIND_MT_H |
@@ -12,8 +12,10 @@ EXTERN_C_BEGIN | |||
12 | typedef struct | 12 | typedef struct |
13 | { | 13 | { |
14 | UInt32 numProcessedBlocks; | 14 | UInt32 numProcessedBlocks; |
15 | CThread thread; | 15 | Int32 affinityGroup; |
16 | UInt64 affinityInGroup; | ||
16 | UInt64 affinity; | 17 | UInt64 affinity; |
18 | CThread thread; | ||
17 | 19 | ||
18 | BoolInt wasCreated; | 20 | BoolInt wasCreated; |
19 | BoolInt needStart; | 21 | BoolInt needStart; |
diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c index 703e146..72aec69 100644 --- a/C/Lzma2Enc.c +++ b/C/Lzma2Enc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Lzma2Enc.c -- LZMA2 Encoder | 1 | /* Lzma2Enc.c -- LZMA2 Encoder |
2 | 2023-04-13 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -235,6 +235,7 @@ void Lzma2EncProps_Init(CLzma2EncProps *p) | |||
235 | p->numBlockThreads_Reduced = -1; | 235 | p->numBlockThreads_Reduced = -1; |
236 | p->numBlockThreads_Max = -1; | 236 | p->numBlockThreads_Max = -1; |
237 | p->numTotalThreads = -1; | 237 | p->numTotalThreads = -1; |
238 | p->numThreadGroups = 0; | ||
238 | } | 239 | } |
239 | 240 | ||
240 | void Lzma2EncProps_Normalize(CLzma2EncProps *p) | 241 | void Lzma2EncProps_Normalize(CLzma2EncProps *p) |
@@ -781,6 +782,7 @@ SRes Lzma2Enc_Encode2(CLzma2EncHandle p, | |||
781 | } | 782 | } |
782 | 783 | ||
783 | p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max; | 784 | p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max; |
785 | p->mtCoder.numThreadGroups = p->props.numThreadGroups; | ||
784 | p->mtCoder.expectedDataSize = p->expectedDataSize; | 786 | p->mtCoder.expectedDataSize = p->expectedDataSize; |
785 | 787 | ||
786 | { | 788 | { |
diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h index cb25275..1e6b50c 100644 --- a/C/Lzma2Enc.h +++ b/C/Lzma2Enc.h | |||
@@ -18,6 +18,7 @@ typedef struct | |||
18 | int numBlockThreads_Reduced; | 18 | int numBlockThreads_Reduced; |
19 | int numBlockThreads_Max; | 19 | int numBlockThreads_Max; |
20 | int numTotalThreads; | 20 | int numTotalThreads; |
21 | unsigned numThreadGroups; // 0 : no groups | ||
21 | } CLzma2EncProps; | 22 | } CLzma2EncProps; |
22 | 23 | ||
23 | void Lzma2EncProps_Init(CLzma2EncProps *p); | 24 | void Lzma2EncProps_Init(CLzma2EncProps *p); |
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index 37b2787..84a29a5 100644 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* LzmaEnc.c -- LZMA Encoder | 1 | /* LzmaEnc.c -- LZMA Encoder |
2 | 2024-01-24: Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -62,7 +62,9 @@ void LzmaEncProps_Init(CLzmaEncProps *p) | |||
62 | p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; | 62 | p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; |
63 | p->numHashOutBits = 0; | 63 | p->numHashOutBits = 0; |
64 | p->writeEndMark = 0; | 64 | p->writeEndMark = 0; |
65 | p->affinityGroup = -1; | ||
65 | p->affinity = 0; | 66 | p->affinity = 0; |
67 | p->affinityInGroup = 0; | ||
66 | } | 68 | } |
67 | 69 | ||
68 | void LzmaEncProps_Normalize(CLzmaEncProps *p) | 70 | void LzmaEncProps_Normalize(CLzmaEncProps *p) |
@@ -72,11 +74,11 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) | |||
72 | p->level = level; | 74 | p->level = level; |
73 | 75 | ||
74 | if (p->dictSize == 0) | 76 | if (p->dictSize == 0) |
75 | p->dictSize = | 77 | p->dictSize = (unsigned)level <= 4 ? |
76 | ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : | 78 | (UInt32)1 << (level * 2 + 16) : |
77 | ( level <= 6 ? ((UInt32)1 << (level + 19)) : | 79 | (unsigned)level <= sizeof(size_t) / 2 + 4 ? |
78 | ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) | 80 | (UInt32)1 << (level + 20) : |
79 | ))); | 81 | (UInt32)1 << (sizeof(size_t) / 2 + 24); |
80 | 82 | ||
81 | if (p->dictSize > p->reduceSize) | 83 | if (p->dictSize > p->reduceSize) |
82 | { | 84 | { |
@@ -92,8 +94,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) | |||
92 | if (p->lp < 0) p->lp = 0; | 94 | if (p->lp < 0) p->lp = 0; |
93 | if (p->pb < 0) p->pb = 2; | 95 | if (p->pb < 0) p->pb = 2; |
94 | 96 | ||
95 | if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); | 97 | if (p->algo < 0) p->algo = (unsigned)level < 5 ? 0 : 1; |
96 | if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); | 98 | if (p->fb < 0) p->fb = (unsigned)level < 7 ? 32 : 64; |
97 | if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); | 99 | if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); |
98 | if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); | 100 | if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); |
99 | if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); | 101 | if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); |
@@ -598,6 +600,10 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2) | |||
598 | p->multiThread = (props.numThreads > 1); | 600 | p->multiThread = (props.numThreads > 1); |
599 | p->matchFinderMt.btSync.affinity = | 601 | p->matchFinderMt.btSync.affinity = |
600 | p->matchFinderMt.hashSync.affinity = props.affinity; | 602 | p->matchFinderMt.hashSync.affinity = props.affinity; |
603 | p->matchFinderMt.btSync.affinityGroup = | ||
604 | p->matchFinderMt.hashSync.affinityGroup = props.affinityGroup; | ||
605 | p->matchFinderMt.btSync.affinityInGroup = | ||
606 | p->matchFinderMt.hashSync.affinityInGroup = props.affinityInGroup; | ||
601 | #endif | 607 | #endif |
602 | 608 | ||
603 | return SZ_OK; | 609 | return SZ_OK; |
diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h index 9f8039a..3feb5b4 100644 --- a/C/LzmaEnc.h +++ b/C/LzmaEnc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* LzmaEnc.h -- LZMA Encoder | 1 | /* LzmaEnc.h -- LZMA Encoder |
2 | 2023-04-13 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_LZMA_ENC_H | 4 | #ifndef ZIP7_INC_LZMA_ENC_H |
5 | #define ZIP7_INC_LZMA_ENC_H | 5 | #define ZIP7_INC_LZMA_ENC_H |
@@ -29,11 +29,13 @@ typedef struct | |||
29 | int numThreads; /* 1 or 2, default = 2 */ | 29 | int numThreads; /* 1 or 2, default = 2 */ |
30 | 30 | ||
31 | // int _pad; | 31 | // int _pad; |
32 | Int32 affinityGroup; | ||
32 | 33 | ||
33 | UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. | 34 | UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. |
34 | Encoder uses this value to reduce dictionary size */ | 35 | Encoder uses this value to reduce dictionary size */ |
35 | 36 | ||
36 | UInt64 affinity; | 37 | UInt64 affinity; |
38 | UInt64 affinityInGroup; | ||
37 | } CLzmaEncProps; | 39 | } CLzmaEncProps; |
38 | 40 | ||
39 | void LzmaEncProps_Init(CLzmaEncProps *p); | 41 | void LzmaEncProps_Init(CLzmaEncProps *p); |
@@ -0,0 +1,206 @@ | |||
1 | /* Md5.c -- MD5 Hash | ||
2 | : Igor Pavlov : Public domain | ||
3 | This code is based on Colin Plumb's public domain md5.c code */ | ||
4 | |||
5 | #include "Precomp.h" | ||
6 | |||
7 | #include <string.h> | ||
8 | |||
9 | #include "Md5.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "CpuArch.h" | ||
12 | |||
13 | #define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks | ||
14 | |||
15 | Z7_NO_INLINE | ||
16 | void Md5_Init(CMd5 *p) | ||
17 | { | ||
18 | p->count = 0; | ||
19 | p->state[0] = 0x67452301; | ||
20 | p->state[1] = 0xefcdab89; | ||
21 | p->state[2] = 0x98badcfe; | ||
22 | p->state[3] = 0x10325476; | ||
23 | } | ||
24 | |||
25 | #if 0 && !defined(MY_CPU_LE_UNALIGN) | ||
26 | // optional optimization for Big-endian processors or processors without unaligned access: | ||
27 | // it is intended to reduce the number of complex LE32 memory reading from 64 to 16. | ||
28 | // But some compilers (sparc, armt) are better without this optimization. | ||
29 | #define Z7_MD5_USE_DATA32_ARRAY | ||
30 | #endif | ||
31 | |||
32 | #define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i)) | ||
33 | |||
34 | #ifdef Z7_MD5_USE_DATA32_ARRAY | ||
35 | #define D(i) data32[i] | ||
36 | #else | ||
37 | #define D(i) LOAD_DATA(i) | ||
38 | #endif | ||
39 | |||
40 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | ||
41 | #define F2(x, y, z) F1(z, x, y) | ||
42 | #define F3(x, y, z) (x ^ y ^ z) | ||
43 | #define F4(x, y, z) (y ^ (x | ~z)) | ||
44 | |||
45 | #define R1(i, f, start, step, w, x, y, z, s, k) \ | ||
46 | w += D((start + step * (i)) % 16) + k; \ | ||
47 | w += f(x, y, z); \ | ||
48 | w = rotlFixed(w, s) + x; \ | ||
49 | |||
50 | #define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \ | ||
51 | R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \ | ||
52 | R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \ | ||
53 | R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \ | ||
54 | R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \ | ||
55 | |||
56 | #define R16(f, start, step, s0,s1,s2,s3, k00,k01,k02,k03, k10,k11,k12,k13, k20,k21,k22,k23, k30,k31,k32,k33) \ | ||
57 | R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \ | ||
58 | R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \ | ||
59 | R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \ | ||
60 | R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \ | ||
61 | |||
62 | static | ||
63 | Z7_NO_INLINE | ||
64 | void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks) | ||
65 | { | ||
66 | UInt32 a, b, c, d; | ||
67 | // if (numBlocks == 0) return; | ||
68 | a = state[0]; | ||
69 | b = state[1]; | ||
70 | c = state[2]; | ||
71 | d = state[3]; | ||
72 | do | ||
73 | { | ||
74 | #ifdef Z7_MD5_USE_DATA32_ARRAY | ||
75 | UInt32 data32[MD5_NUM_BLOCK_WORDS]; | ||
76 | { | ||
77 | #define LOAD_data32_x4(i) { \ | ||
78 | data32[i ] = LOAD_DATA(i ); \ | ||
79 | data32[i + 1] = LOAD_DATA(i + 1); \ | ||
80 | data32[i + 2] = LOAD_DATA(i + 2); \ | ||
81 | data32[i + 3] = LOAD_DATA(i + 3); } | ||
82 | #if 1 | ||
83 | LOAD_data32_x4 (0 * 4) | ||
84 | LOAD_data32_x4 (1 * 4) | ||
85 | LOAD_data32_x4 (2 * 4) | ||
86 | LOAD_data32_x4 (3 * 4) | ||
87 | #else | ||
88 | unsigned i; | ||
89 | for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4) | ||
90 | { | ||
91 | LOAD_data32_x4(i) | ||
92 | } | ||
93 | #endif | ||
94 | } | ||
95 | #endif | ||
96 | |||
97 | R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | ||
98 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | ||
99 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | ||
100 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821) | ||
101 | R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | ||
102 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | ||
103 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | ||
104 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a) | ||
105 | R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | ||
106 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, | ||
107 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, | ||
108 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665) | ||
109 | R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, | ||
110 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, | ||
111 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, | ||
112 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391) | ||
113 | |||
114 | a += state[0]; | ||
115 | b += state[1]; | ||
116 | c += state[2]; | ||
117 | d += state[3]; | ||
118 | |||
119 | state[0] = a; | ||
120 | state[1] = b; | ||
121 | state[2] = c; | ||
122 | state[3] = d; | ||
123 | |||
124 | data += MD5_BLOCK_SIZE; | ||
125 | } | ||
126 | while (--numBlocks); | ||
127 | } | ||
128 | |||
129 | |||
130 | #define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) | ||
131 | |||
132 | void Md5_Update(CMd5 *p, const Byte *data, size_t size) | ||
133 | { | ||
134 | if (size == 0) | ||
135 | return; | ||
136 | { | ||
137 | const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1); | ||
138 | const unsigned num = MD5_BLOCK_SIZE - pos; | ||
139 | p->count += size; | ||
140 | if (num > size) | ||
141 | { | ||
142 | memcpy(p->buffer + pos, data, size); | ||
143 | return; | ||
144 | } | ||
145 | if (pos != 0) | ||
146 | { | ||
147 | size -= num; | ||
148 | memcpy(p->buffer + pos, data, num); | ||
149 | data += num; | ||
150 | Md5_UpdateBlock(p); | ||
151 | } | ||
152 | } | ||
153 | { | ||
154 | const size_t numBlocks = size >> 6; | ||
155 | if (numBlocks) | ||
156 | MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks); | ||
157 | size &= MD5_BLOCK_SIZE - 1; | ||
158 | if (size == 0) | ||
159 | return; | ||
160 | data += (numBlocks << 6); | ||
161 | memcpy(p->buffer, data, size); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | |||
166 | void Md5_Final(CMd5 *p, Byte *digest) | ||
167 | { | ||
168 | unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1); | ||
169 | p->buffer[pos++] = 0x80; | ||
170 | if (pos > (MD5_BLOCK_SIZE - 4 * 2)) | ||
171 | { | ||
172 | while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; } | ||
173 | // memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos); | ||
174 | Md5_UpdateBlock(p); | ||
175 | pos = 0; | ||
176 | } | ||
177 | memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos); | ||
178 | { | ||
179 | const UInt64 numBits = p->count << 3; | ||
180 | #if defined(MY_CPU_LE_UNALIGN) | ||
181 | SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits) | ||
182 | #else | ||
183 | SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits)) | ||
184 | SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32)) | ||
185 | #endif | ||
186 | } | ||
187 | Md5_UpdateBlock(p); | ||
188 | |||
189 | SetUi32(digest, p->state[0]) | ||
190 | SetUi32(digest + 4, p->state[1]) | ||
191 | SetUi32(digest + 8, p->state[2]) | ||
192 | SetUi32(digest + 12, p->state[3]) | ||
193 | |||
194 | Md5_Init(p); | ||
195 | } | ||
196 | |||
197 | #undef R1 | ||
198 | #undef R4 | ||
199 | #undef R16 | ||
200 | #undef D | ||
201 | #undef LOAD_DATA | ||
202 | #undef LOAD_data32_x4 | ||
203 | #undef F1 | ||
204 | #undef F2 | ||
205 | #undef F3 | ||
206 | #undef F4 | ||
@@ -0,0 +1,34 @@ | |||
1 | /* Md5.h -- MD5 Hash | ||
2 | : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #ifndef ZIP7_INC_MD5_H | ||
5 | #define ZIP7_INC_MD5_H | ||
6 | |||
7 | #include "7zTypes.h" | ||
8 | |||
9 | EXTERN_C_BEGIN | ||
10 | |||
11 | #define MD5_NUM_BLOCK_WORDS 16 | ||
12 | #define MD5_NUM_DIGEST_WORDS 4 | ||
13 | |||
14 | #define MD5_BLOCK_SIZE (MD5_NUM_BLOCK_WORDS * 4) | ||
15 | #define MD5_DIGEST_SIZE (MD5_NUM_DIGEST_WORDS * 4) | ||
16 | |||
17 | typedef struct | ||
18 | { | ||
19 | UInt64 count; | ||
20 | UInt64 _pad_1; | ||
21 | // we want 16-bytes alignment here | ||
22 | UInt32 state[MD5_NUM_DIGEST_WORDS]; | ||
23 | UInt64 _pad_2[4]; | ||
24 | // we want 64-bytes alignment here | ||
25 | Byte buffer[MD5_BLOCK_SIZE]; | ||
26 | } CMd5; | ||
27 | |||
28 | void Md5_Init(CMd5 *p); | ||
29 | void Md5_Update(CMd5 *p, const Byte *data, size_t size); | ||
30 | void Md5_Final(CMd5 *p, Byte *digest); | ||
31 | |||
32 | EXTERN_C_END | ||
33 | |||
34 | #endif | ||
diff --git a/C/MtCoder.c b/C/MtCoder.c index 03959b6..923b19a 100644 --- a/C/MtCoder.c +++ b/C/MtCoder.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* MtCoder.c -- Multi-thread Coder | 1 | /* MtCoder.c -- Multi-thread Coder |
2 | 2023-09-07 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -39,14 +39,28 @@ void MtProgressThunk_CreateVTable(CMtProgressThunk *p) | |||
39 | static THREAD_FUNC_DECL ThreadFunc(void *pp); | 39 | static THREAD_FUNC_DECL ThreadFunc(void *pp); |
40 | 40 | ||
41 | 41 | ||
42 | static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) | 42 | static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t |
43 | #ifdef _WIN32 | ||
44 | , CMtCoder * const mtc | ||
45 | #endif | ||
46 | ) | ||
43 | { | 47 | { |
44 | WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent); | 48 | WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent); |
49 | // printf("\n====== MtCoderThread_CreateAndStart : \n"); | ||
45 | if (wres == 0) | 50 | if (wres == 0) |
46 | { | 51 | { |
47 | t->stop = False; | 52 | t->stop = False; |
48 | if (!Thread_WasCreated(&t->thread)) | 53 | if (!Thread_WasCreated(&t->thread)) |
49 | wres = Thread_Create(&t->thread, ThreadFunc, t); | 54 | { |
55 | #ifdef _WIN32 | ||
56 | if (mtc->numThreadGroups) | ||
57 | wres = Thread_Create_With_Group(&t->thread, ThreadFunc, t, | ||
58 | ThreadNextGroup_GetNext(&mtc->nextGroup), // group | ||
59 | 0); // affinityMask | ||
60 | else | ||
61 | #endif | ||
62 | wres = Thread_Create(&t->thread, ThreadFunc, t); | ||
63 | } | ||
50 | if (wres == 0) | 64 | if (wres == 0) |
51 | wres = Event_Set(&t->startEvent); | 65 | wres = Event_Set(&t->startEvent); |
52 | } | 66 | } |
@@ -56,6 +70,7 @@ static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) | |||
56 | } | 70 | } |
57 | 71 | ||
58 | 72 | ||
73 | Z7_FORCE_INLINE | ||
59 | static void MtCoderThread_Destruct(CMtCoderThread *t) | 74 | static void MtCoderThread_Destruct(CMtCoderThread *t) |
60 | { | 75 | { |
61 | if (Thread_WasCreated(&t->thread)) | 76 | if (Thread_WasCreated(&t->thread)) |
@@ -85,7 +100,7 @@ static void MtCoderThread_Destruct(CMtCoderThread *t) | |||
85 | 100 | ||
86 | static SRes ThreadFunc2(CMtCoderThread *t) | 101 | static SRes ThreadFunc2(CMtCoderThread *t) |
87 | { | 102 | { |
88 | CMtCoder *mtc = t->mtCoder; | 103 | CMtCoder * const mtc = t->mtCoder; |
89 | 104 | ||
90 | for (;;) | 105 | for (;;) |
91 | { | 106 | { |
@@ -185,7 +200,11 @@ static SRes ThreadFunc2(CMtCoderThread *t) | |||
185 | if (mtc->numStartedThreads < mtc->numStartedThreadsLimit | 200 | if (mtc->numStartedThreads < mtc->numStartedThreadsLimit |
186 | && mtc->expectedDataSize != readProcessed) | 201 | && mtc->expectedDataSize != readProcessed) |
187 | { | 202 | { |
188 | res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]); | 203 | res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads] |
204 | #ifdef _WIN32 | ||
205 | , mtc | ||
206 | #endif | ||
207 | ); | ||
189 | if (res == SZ_OK) | 208 | if (res == SZ_OK) |
190 | mtc->numStartedThreads++; | 209 | mtc->numStartedThreads++; |
191 | else | 210 | else |
@@ -221,7 +240,7 @@ static SRes ThreadFunc2(CMtCoderThread *t) | |||
221 | } | 240 | } |
222 | 241 | ||
223 | { | 242 | { |
224 | CMtCoderBlock *block = &mtc->blocks[bi]; | 243 | CMtCoderBlock * const block = &mtc->blocks[bi]; |
225 | block->res = res; | 244 | block->res = res; |
226 | block->bufIndex = bufIndex; | 245 | block->bufIndex = bufIndex; |
227 | block->finished = finished; | 246 | block->finished = finished; |
@@ -311,7 +330,7 @@ static SRes ThreadFunc2(CMtCoderThread *t) | |||
311 | 330 | ||
312 | static THREAD_FUNC_DECL ThreadFunc(void *pp) | 331 | static THREAD_FUNC_DECL ThreadFunc(void *pp) |
313 | { | 332 | { |
314 | CMtCoderThread *t = (CMtCoderThread *)pp; | 333 | CMtCoderThread * const t = (CMtCoderThread *)pp; |
315 | for (;;) | 334 | for (;;) |
316 | { | 335 | { |
317 | if (Event_Wait(&t->startEvent) != 0) | 336 | if (Event_Wait(&t->startEvent) != 0) |
@@ -319,7 +338,7 @@ static THREAD_FUNC_DECL ThreadFunc(void *pp) | |||
319 | if (t->stop) | 338 | if (t->stop) |
320 | return 0; | 339 | return 0; |
321 | { | 340 | { |
322 | SRes res = ThreadFunc2(t); | 341 | const SRes res = ThreadFunc2(t); |
323 | CMtCoder *mtc = t->mtCoder; | 342 | CMtCoder *mtc = t->mtCoder; |
324 | if (res != SZ_OK) | 343 | if (res != SZ_OK) |
325 | { | 344 | { |
@@ -328,7 +347,7 @@ static THREAD_FUNC_DECL ThreadFunc(void *pp) | |||
328 | 347 | ||
329 | #ifndef MTCODER_USE_WRITE_THREAD | 348 | #ifndef MTCODER_USE_WRITE_THREAD |
330 | { | 349 | { |
331 | unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); | 350 | const unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); |
332 | if (numFinished == mtc->numStartedThreads) | 351 | if (numFinished == mtc->numStartedThreads) |
333 | if (Event_Set(&mtc->finishedEvent) != 0) | 352 | if (Event_Set(&mtc->finishedEvent) != 0) |
334 | return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; | 353 | return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; |
@@ -346,6 +365,7 @@ void MtCoder_Construct(CMtCoder *p) | |||
346 | 365 | ||
347 | p->blockSize = 0; | 366 | p->blockSize = 0; |
348 | p->numThreadsMax = 0; | 367 | p->numThreadsMax = 0; |
368 | p->numThreadGroups = 0; | ||
349 | p->expectedDataSize = (UInt64)(Int64)-1; | 369 | p->expectedDataSize = (UInt64)(Int64)-1; |
350 | 370 | ||
351 | p->inStream = NULL; | 371 | p->inStream = NULL; |
@@ -429,6 +449,8 @@ SRes MtCoder_Code(CMtCoder *p) | |||
429 | unsigned i; | 449 | unsigned i; |
430 | SRes res = SZ_OK; | 450 | SRes res = SZ_OK; |
431 | 451 | ||
452 | // printf("\n====== MtCoder_Code : \n"); | ||
453 | |||
432 | if (numThreads > MTCODER_THREADS_MAX) | 454 | if (numThreads > MTCODER_THREADS_MAX) |
433 | numThreads = MTCODER_THREADS_MAX; | 455 | numThreads = MTCODER_THREADS_MAX; |
434 | numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); | 456 | numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); |
@@ -492,11 +514,22 @@ SRes MtCoder_Code(CMtCoder *p) | |||
492 | 514 | ||
493 | p->numStartedThreadsLimit = numThreads; | 515 | p->numStartedThreadsLimit = numThreads; |
494 | p->numStartedThreads = 0; | 516 | p->numStartedThreads = 0; |
517 | ThreadNextGroup_Init(&p->nextGroup, p->numThreadGroups, 0); // startGroup | ||
495 | 518 | ||
496 | // for (i = 0; i < numThreads; i++) | 519 | // for (i = 0; i < numThreads; i++) |
497 | { | 520 | { |
521 | // here we create new thread for first block. | ||
522 | // And each new thread will create another new thread after block reading | ||
523 | // until numStartedThreadsLimit is reached. | ||
498 | CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; | 524 | CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; |
499 | RINOK(MtCoderThread_CreateAndStart(nextThread)) | 525 | { |
526 | const SRes res2 = MtCoderThread_CreateAndStart(nextThread | ||
527 | #ifdef _WIN32 | ||
528 | , p | ||
529 | #endif | ||
530 | ); | ||
531 | RINOK(res2) | ||
532 | } | ||
500 | } | 533 | } |
501 | 534 | ||
502 | RINOK_THREAD(Event_Set(&p->readEvent)) | 535 | RINOK_THREAD(Event_Set(&p->readEvent)) |
@@ -513,9 +546,9 @@ SRes MtCoder_Code(CMtCoder *p) | |||
513 | RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) | 546 | RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) |
514 | 547 | ||
515 | { | 548 | { |
516 | const CMtCoderBlock *block = &p->blocks[bi]; | 549 | const CMtCoderBlock * const block = &p->blocks[bi]; |
517 | unsigned bufIndex = block->bufIndex; | 550 | const unsigned bufIndex = block->bufIndex; |
518 | BoolInt finished = block->finished; | 551 | const BoolInt finished = block->finished; |
519 | if (res == SZ_OK && block->res != SZ_OK) | 552 | if (res == SZ_OK && block->res != SZ_OK) |
520 | res = block->res; | 553 | res = block->res; |
521 | 554 | ||
@@ -545,7 +578,7 @@ SRes MtCoder_Code(CMtCoder *p) | |||
545 | } | 578 | } |
546 | #else | 579 | #else |
547 | { | 580 | { |
548 | WRes wres = Event_Wait(&p->finishedEvent); | 581 | const WRes wres = Event_Wait(&p->finishedEvent); |
549 | res = MY_SRes_HRESULT_FROM_WRes(wres); | 582 | res = MY_SRes_HRESULT_FROM_WRes(wres); |
550 | } | 583 | } |
551 | #endif | 584 | #endif |
diff --git a/C/MtCoder.h b/C/MtCoder.h index 1231d3c..8166cca 100644 --- a/C/MtCoder.h +++ b/C/MtCoder.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* MtCoder.h -- Multi-thread Coder | 1 | /* MtCoder.h -- Multi-thread Coder |
2 | 2023-04-13 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_MT_CODER_H | 4 | #ifndef ZIP7_INC_MT_CODER_H |
5 | #define ZIP7_INC_MT_CODER_H | 5 | #define ZIP7_INC_MT_CODER_H |
@@ -16,7 +16,7 @@ EXTERN_C_BEGIN | |||
16 | 16 | ||
17 | #ifndef Z7_ST | 17 | #ifndef Z7_ST |
18 | #define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) | 18 | #define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) |
19 | #define MTCODER_THREADS_MAX 64 | 19 | #define MTCODER_THREADS_MAX 256 |
20 | #define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3) | 20 | #define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3) |
21 | #else | 21 | #else |
22 | #define MTCODER_THREADS_MAX 1 | 22 | #define MTCODER_THREADS_MAX 1 |
@@ -77,6 +77,7 @@ typedef struct CMtCoder_ | |||
77 | 77 | ||
78 | size_t blockSize; /* size of input block */ | 78 | size_t blockSize; /* size of input block */ |
79 | unsigned numThreadsMax; | 79 | unsigned numThreadsMax; |
80 | unsigned numThreadGroups; | ||
80 | UInt64 expectedDataSize; | 81 | UInt64 expectedDataSize; |
81 | 82 | ||
82 | ISeqInStreamPtr inStream; | 83 | ISeqInStreamPtr inStream; |
@@ -125,6 +126,8 @@ typedef struct CMtCoder_ | |||
125 | CMtProgress mtProgress; | 126 | CMtProgress mtProgress; |
126 | CMtCoderBlock blocks[MTCODER_BLOCKS_MAX]; | 127 | CMtCoderBlock blocks[MTCODER_BLOCKS_MAX]; |
127 | CMtCoderThread threads[MTCODER_THREADS_MAX]; | 128 | CMtCoderThread threads[MTCODER_THREADS_MAX]; |
129 | |||
130 | CThreadNextGroup nextGroup; | ||
128 | } CMtCoder; | 131 | } CMtCoder; |
129 | 132 | ||
130 | 133 | ||
@@ -1,18 +1,14 @@ | |||
1 | /* Sha1.c -- SHA-1 Hash | 1 | /* Sha1.c -- SHA-1 Hash |
2 | 2024-03-01 : Igor Pavlov : Public domain | 2 | : Igor Pavlov : Public domain |
3 | This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ | 3 | This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ |
4 | 4 | ||
5 | #include "Precomp.h" | 5 | #include "Precomp.h" |
6 | 6 | ||
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #include "CpuArch.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "Sha1.h" | 9 | #include "Sha1.h" |
12 | 10 | #include "RotateDefs.h" | |
13 | #if defined(_MSC_VER) && (_MSC_VER < 1900) | 11 | #include "CpuArch.h" |
14 | // #define USE_MY_MM | ||
15 | #endif | ||
16 | 12 | ||
17 | #ifdef MY_CPU_X86_OR_AMD64 | 13 | #ifdef MY_CPU_X86_OR_AMD64 |
18 | #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ | 14 | #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ |
@@ -56,7 +52,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num | |||
56 | static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS = Sha1_UpdateBlocks; | 52 | static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS = Sha1_UpdateBlocks; |
57 | static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS_HW; | 53 | static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS_HW; |
58 | 54 | ||
59 | #define SHA1_UPDATE_BLOCKS(p) p->func_UpdateBlocks | 55 | #define SHA1_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks |
60 | #else | 56 | #else |
61 | #define SHA1_UPDATE_BLOCKS(p) Sha1_UpdateBlocks | 57 | #define SHA1_UPDATE_BLOCKS(p) Sha1_UpdateBlocks |
62 | #endif | 58 | #endif |
@@ -85,7 +81,7 @@ BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo) | |||
85 | return False; | 81 | return False; |
86 | #endif | 82 | #endif |
87 | 83 | ||
88 | p->func_UpdateBlocks = func; | 84 | p->v.vars.func_UpdateBlocks = func; |
89 | return True; | 85 | return True; |
90 | } | 86 | } |
91 | 87 | ||
@@ -225,7 +221,7 @@ BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo) | |||
225 | 221 | ||
226 | void Sha1_InitState(CSha1 *p) | 222 | void Sha1_InitState(CSha1 *p) |
227 | { | 223 | { |
228 | p->count = 0; | 224 | p->v.vars.count = 0; |
229 | p->state[0] = 0x67452301; | 225 | p->state[0] = 0x67452301; |
230 | p->state[1] = 0xEFCDAB89; | 226 | p->state[1] = 0xEFCDAB89; |
231 | p->state[2] = 0x98BADCFE; | 227 | p->state[2] = 0x98BADCFE; |
@@ -235,7 +231,7 @@ void Sha1_InitState(CSha1 *p) | |||
235 | 231 | ||
236 | void Sha1_Init(CSha1 *p) | 232 | void Sha1_Init(CSha1 *p) |
237 | { | 233 | { |
238 | p->func_UpdateBlocks = | 234 | p->v.vars.func_UpdateBlocks = |
239 | #ifdef Z7_COMPILER_SHA1_SUPPORTED | 235 | #ifdef Z7_COMPILER_SHA1_SUPPORTED |
240 | g_SHA1_FUNC_UPDATE_BLOCKS; | 236 | g_SHA1_FUNC_UPDATE_BLOCKS; |
241 | #else | 237 | #else |
@@ -250,7 +246,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num | |||
250 | { | 246 | { |
251 | UInt32 a, b, c, d, e; | 247 | UInt32 a, b, c, d, e; |
252 | UInt32 W[kNumW]; | 248 | UInt32 W[kNumW]; |
253 | // if (numBlocks != 0x1264378347) return; | 249 | |
254 | if (numBlocks == 0) | 250 | if (numBlocks == 0) |
255 | return; | 251 | return; |
256 | 252 | ||
@@ -283,7 +279,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num | |||
283 | state[3] = d; | 279 | state[3] = d; |
284 | state[4] = e; | 280 | state[4] = e; |
285 | 281 | ||
286 | data += 64; | 282 | data += SHA1_BLOCK_SIZE; |
287 | } | 283 | } |
288 | while (--numBlocks); | 284 | while (--numBlocks); |
289 | } | 285 | } |
@@ -295,20 +291,15 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size) | |||
295 | { | 291 | { |
296 | if (size == 0) | 292 | if (size == 0) |
297 | return; | 293 | return; |
298 | |||
299 | { | 294 | { |
300 | unsigned pos = (unsigned)p->count & 0x3F; | 295 | const unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1); |
301 | unsigned num; | 296 | const unsigned num = SHA1_BLOCK_SIZE - pos; |
302 | 297 | p->v.vars.count += size; | |
303 | p->count += size; | ||
304 | |||
305 | num = 64 - pos; | ||
306 | if (num > size) | 298 | if (num > size) |
307 | { | 299 | { |
308 | memcpy(p->buffer + pos, data, size); | 300 | memcpy(p->buffer + pos, data, size); |
309 | return; | 301 | return; |
310 | } | 302 | } |
311 | |||
312 | if (pos != 0) | 303 | if (pos != 0) |
313 | { | 304 | { |
314 | size -= num; | 305 | size -= num; |
@@ -318,9 +309,10 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size) | |||
318 | } | 309 | } |
319 | } | 310 | } |
320 | { | 311 | { |
321 | size_t numBlocks = size >> 6; | 312 | const size_t numBlocks = size >> 6; |
313 | // if (numBlocks) | ||
322 | SHA1_UPDATE_BLOCKS(p)(p->state, data, numBlocks); | 314 | SHA1_UPDATE_BLOCKS(p)(p->state, data, numBlocks); |
323 | size &= 0x3F; | 315 | size &= SHA1_BLOCK_SIZE - 1; |
324 | if (size == 0) | 316 | if (size == 0) |
325 | return; | 317 | return; |
326 | data += (numBlocks << 6); | 318 | data += (numBlocks << 6); |
@@ -331,42 +323,21 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size) | |||
331 | 323 | ||
332 | void Sha1_Final(CSha1 *p, Byte *digest) | 324 | void Sha1_Final(CSha1 *p, Byte *digest) |
333 | { | 325 | { |
334 | unsigned pos = (unsigned)p->count & 0x3F; | 326 | unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1); |
335 | |||
336 | |||
337 | p->buffer[pos++] = 0x80; | 327 | p->buffer[pos++] = 0x80; |
338 | 328 | if (pos > (SHA1_BLOCK_SIZE - 4 * 2)) | |
339 | if (pos > (64 - 8)) | ||
340 | { | 329 | { |
341 | while (pos != 64) { p->buffer[pos++] = 0; } | 330 | while (pos != SHA1_BLOCK_SIZE) { p->buffer[pos++] = 0; } |
342 | // memset(&p->buf.buffer[pos], 0, 64 - pos); | 331 | // memset(&p->buf.buffer[pos], 0, SHA1_BLOCK_SIZE - pos); |
343 | Sha1_UpdateBlock(p); | 332 | Sha1_UpdateBlock(p); |
344 | pos = 0; | 333 | pos = 0; |
345 | } | 334 | } |
346 | 335 | memset(&p->buffer[pos], 0, (SHA1_BLOCK_SIZE - 4 * 2) - pos); | |
347 | /* | ||
348 | if (pos & 3) | ||
349 | { | ||
350 | p->buffer[pos] = 0; | ||
351 | p->buffer[pos + 1] = 0; | ||
352 | p->buffer[pos + 2] = 0; | ||
353 | pos += 3; | ||
354 | pos &= ~3; | ||
355 | } | ||
356 | { | ||
357 | for (; pos < 64 - 8; pos += 4) | ||
358 | *(UInt32 *)(&p->buffer[pos]) = 0; | ||
359 | } | ||
360 | */ | ||
361 | |||
362 | memset(&p->buffer[pos], 0, (64 - 8) - pos); | ||
363 | |||
364 | { | 336 | { |
365 | const UInt64 numBits = (p->count << 3); | 337 | const UInt64 numBits = p->v.vars.count << 3; |
366 | SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)) | 338 | SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32)) |
367 | SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)) | 339 | SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 1, (UInt32)(numBits)) |
368 | } | 340 | } |
369 | |||
370 | Sha1_UpdateBlock(p); | 341 | Sha1_UpdateBlock(p); |
371 | 342 | ||
372 | SetBe32(digest, p->state[0]) | 343 | SetBe32(digest, p->state[0]) |
@@ -375,16 +346,13 @@ void Sha1_Final(CSha1 *p, Byte *digest) | |||
375 | SetBe32(digest + 12, p->state[3]) | 346 | SetBe32(digest + 12, p->state[3]) |
376 | SetBe32(digest + 16, p->state[4]) | 347 | SetBe32(digest + 16, p->state[4]) |
377 | 348 | ||
378 | |||
379 | |||
380 | |||
381 | Sha1_InitState(p); | 349 | Sha1_InitState(p); |
382 | } | 350 | } |
383 | 351 | ||
384 | 352 | ||
385 | void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size) | 353 | void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size) |
386 | { | 354 | { |
387 | const UInt64 numBits = (p->count + size) << 3; | 355 | const UInt64 numBits = (p->v.vars.count + size) << 3; |
388 | SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 2], (UInt32)(numBits >> 32)) | 356 | SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 2], (UInt32)(numBits >> 32)) |
389 | SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 1], (UInt32)(numBits)) | 357 | SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 1], (UInt32)(numBits)) |
390 | // SetBe32((UInt32 *)(block + size), 0x80000000); | 358 | // SetBe32((UInt32 *)(block + size), 0x80000000); |
@@ -420,57 +388,32 @@ void Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest) | |||
420 | 388 | ||
421 | void Sha1Prepare(void) | 389 | void Sha1Prepare(void) |
422 | { | 390 | { |
423 | #ifdef Z7_COMPILER_SHA1_SUPPORTED | 391 | #ifdef Z7_COMPILER_SHA1_SUPPORTED |
424 | SHA1_FUNC_UPDATE_BLOCKS f, f_hw; | 392 | SHA1_FUNC_UPDATE_BLOCKS f, f_hw; |
425 | f = Sha1_UpdateBlocks; | 393 | f = Sha1_UpdateBlocks; |
426 | f_hw = NULL; | 394 | f_hw = NULL; |
427 | #ifdef MY_CPU_X86_OR_AMD64 | 395 | #ifdef MY_CPU_X86_OR_AMD64 |
428 | #ifndef USE_MY_MM | ||
429 | if (CPU_IsSupported_SHA() | 396 | if (CPU_IsSupported_SHA() |
430 | && CPU_IsSupported_SSSE3() | 397 | && CPU_IsSupported_SSSE3() |
431 | // && CPU_IsSupported_SSE41() | ||
432 | ) | 398 | ) |
433 | #endif | 399 | #else |
434 | #else | ||
435 | if (CPU_IsSupported_SHA1()) | 400 | if (CPU_IsSupported_SHA1()) |
436 | #endif | 401 | #endif |
437 | { | 402 | { |
438 | // printf("\n========== HW SHA1 ======== \n"); | 403 | // printf("\n========== HW SHA1 ======== \n"); |
439 | #if 0 && defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER) | 404 | #if 1 && defined(MY_CPU_ARM_OR_ARM64) && defined(Z7_MSC_VER_ORIGINAL) && (_MSC_FULL_VER < 192930037) |
440 | /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037). | 405 | /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037). |
441 | It generated incorrect SHA-1 code. | 406 | It generated incorrect SHA-1 code. */ |
442 | 21.03 : we test sha1-hardware code at runtime initialization */ | 407 | #pragma message("== SHA1 code can work incorrectly with this compiler") |
443 | 408 | #error Stop_Compiling_MSC_Compiler_BUG_SHA1 | |
444 | #pragma message("== SHA1 code: MSC compiler : failure-check code was inserted") | 409 | #endif |
445 | |||
446 | UInt32 state[5] = { 0, 1, 2, 3, 4 } ; | ||
447 | Byte data[64]; | ||
448 | unsigned i; | ||
449 | for (i = 0; i < sizeof(data); i += 2) | ||
450 | { | ||
451 | data[i ] = (Byte)(i); | ||
452 | data[i + 1] = (Byte)(i + 1); | ||
453 | } | ||
454 | |||
455 | Sha1_UpdateBlocks_HW(state, data, sizeof(data) / 64); | ||
456 | |||
457 | if ( state[0] != 0x9acd7297 | ||
458 | || state[1] != 0x4624d898 | ||
459 | || state[2] != 0x0bf079f0 | ||
460 | || state[3] != 0x031e61b3 | ||
461 | || state[4] != 0x8323fe20) | ||
462 | { | ||
463 | // printf("\n========== SHA-1 hardware version failure ======== \n"); | ||
464 | } | ||
465 | else | ||
466 | #endif | ||
467 | { | 410 | { |
468 | f = f_hw = Sha1_UpdateBlocks_HW; | 411 | f = f_hw = Sha1_UpdateBlocks_HW; |
469 | } | 412 | } |
470 | } | 413 | } |
471 | g_SHA1_FUNC_UPDATE_BLOCKS = f; | 414 | g_SHA1_FUNC_UPDATE_BLOCKS = f; |
472 | g_SHA1_FUNC_UPDATE_BLOCKS_HW = f_hw; | 415 | g_SHA1_FUNC_UPDATE_BLOCKS_HW = f_hw; |
473 | #endif | 416 | #endif |
474 | } | 417 | } |
475 | 418 | ||
476 | #undef kNumW | 419 | #undef kNumW |
@@ -1,5 +1,5 @@ | |||
1 | /* Sha1.h -- SHA-1 Hash | 1 | /* Sha1.h -- SHA-1 Hash |
2 | 2023-04-02 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_SHA1_H | 4 | #ifndef ZIP7_INC_SHA1_H |
5 | #define ZIP7_INC_SHA1_H | 5 | #define ZIP7_INC_SHA1_H |
@@ -14,6 +14,9 @@ EXTERN_C_BEGIN | |||
14 | #define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4) | 14 | #define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4) |
15 | #define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4) | 15 | #define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4) |
16 | 16 | ||
17 | |||
18 | |||
19 | |||
17 | typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte *data, size_t numBlocks); | 20 | typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte *data, size_t numBlocks); |
18 | 21 | ||
19 | /* | 22 | /* |
@@ -32,9 +35,16 @@ typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte | |||
32 | 35 | ||
33 | typedef struct | 36 | typedef struct |
34 | { | 37 | { |
35 | SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks; | 38 | union |
36 | UInt64 count; | 39 | { |
37 | UInt64 _pad_2[2]; | 40 | struct |
41 | { | ||
42 | SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks; | ||
43 | UInt64 count; | ||
44 | } vars; | ||
45 | UInt64 _pad_64bit[4]; | ||
46 | void *_pad_align_ptr[2]; | ||
47 | } v; | ||
38 | UInt32 state[SHA1_NUM_DIGEST_WORDS]; | 48 | UInt32 state[SHA1_NUM_DIGEST_WORDS]; |
39 | UInt32 _pad_3[3]; | 49 | UInt32 _pad_3[3]; |
40 | Byte buffer[SHA1_BLOCK_SIZE]; | 50 | Byte buffer[SHA1_BLOCK_SIZE]; |
diff --git a/C/Sha1Opt.c b/C/Sha1Opt.c index 4e835f1..8738b94 100644 --- a/C/Sha1Opt.c +++ b/C/Sha1Opt.c | |||
@@ -1,18 +1,11 @@ | |||
1 | /* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions | 1 | /* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | #include "Compiler.h" | 5 | #include "Compiler.h" |
6 | #include "CpuArch.h" | 6 | #include "CpuArch.h" |
7 | 7 | ||
8 | #if defined(_MSC_VER) | ||
9 | #if (_MSC_VER < 1900) && (_MSC_VER >= 1200) | ||
10 | // #define USE_MY_MM | ||
11 | #endif | ||
12 | #endif | ||
13 | |||
14 | // #define Z7_USE_HW_SHA_STUB // for debug | 8 | // #define Z7_USE_HW_SHA_STUB // for debug |
15 | |||
16 | #ifdef MY_CPU_X86_OR_AMD64 | 9 | #ifdef MY_CPU_X86_OR_AMD64 |
17 | #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check | 10 | #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check |
18 | #define USE_HW_SHA | 11 | #define USE_HW_SHA |
@@ -20,19 +13,14 @@ | |||
20 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ | 13 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ |
21 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) | 14 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) |
22 | #define USE_HW_SHA | 15 | #define USE_HW_SHA |
23 | #if !defined(_INTEL_COMPILER) | 16 | #if !defined(__INTEL_COMPILER) |
24 | // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) | 17 | // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) |
25 | #if !defined(__SHA__) || !defined(__SSSE3__) | 18 | #if !defined(__SHA__) || !defined(__SSSE3__) |
26 | #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) | 19 | #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) |
27 | #endif | 20 | #endif |
28 | #endif | 21 | #endif |
29 | #elif defined(_MSC_VER) | 22 | #elif defined(_MSC_VER) |
30 | #ifdef USE_MY_MM | 23 | #if (_MSC_VER >= 1900) |
31 | #define USE_VER_MIN 1300 | ||
32 | #else | ||
33 | #define USE_VER_MIN 1900 | ||
34 | #endif | ||
35 | #if (_MSC_VER >= USE_VER_MIN) | ||
36 | #define USE_HW_SHA | 24 | #define USE_HW_SHA |
37 | #else | 25 | #else |
38 | #define Z7_USE_HW_SHA_STUB | 26 | #define Z7_USE_HW_SHA_STUB |
@@ -47,23 +35,20 @@ | |||
47 | 35 | ||
48 | // #pragma message("Sha1 HW") | 36 | // #pragma message("Sha1 HW") |
49 | 37 | ||
38 | |||
39 | |||
40 | |||
50 | // sse/sse2/ssse3: | 41 | // sse/sse2/ssse3: |
51 | #include <tmmintrin.h> | 42 | #include <tmmintrin.h> |
52 | // sha*: | 43 | // sha*: |
53 | #include <immintrin.h> | 44 | #include <immintrin.h> |
54 | 45 | ||
55 | #if defined (__clang__) && defined(_MSC_VER) | 46 | #if defined (__clang__) && defined(_MSC_VER) |
56 | // #if !defined(__SSSE3__) | ||
57 | // #endif | ||
58 | #if !defined(__SHA__) | 47 | #if !defined(__SHA__) |
59 | #include <shaintrin.h> | 48 | #include <shaintrin.h> |
60 | #endif | 49 | #endif |
61 | #else | 50 | #else |
62 | 51 | ||
63 | #ifdef USE_MY_MM | ||
64 | #include "My_mm.h" | ||
65 | #endif | ||
66 | |||
67 | #endif | 52 | #endif |
68 | 53 | ||
69 | /* | 54 | /* |
@@ -84,7 +69,6 @@ SHA: | |||
84 | _mm_sha1* | 69 | _mm_sha1* |
85 | */ | 70 | */ |
86 | 71 | ||
87 | |||
88 | #define XOR_SI128(dest, src) dest = _mm_xor_si128(dest, src); | 72 | #define XOR_SI128(dest, src) dest = _mm_xor_si128(dest, src); |
89 | #define SHUFFLE_EPI8(dest, mask) dest = _mm_shuffle_epi8(dest, mask); | 73 | #define SHUFFLE_EPI8(dest, mask) dest = _mm_shuffle_epi8(dest, mask); |
90 | #define SHUFFLE_EPI32(dest, mask) dest = _mm_shuffle_epi32(dest, mask); | 74 | #define SHUFFLE_EPI32(dest, mask) dest = _mm_shuffle_epi32(dest, mask); |
@@ -99,11 +83,12 @@ SHA: | |||
99 | #define SHA1_MSG1(dest, src) dest = _mm_sha1msg1_epu32(dest, src); | 83 | #define SHA1_MSG1(dest, src) dest = _mm_sha1msg1_epu32(dest, src); |
100 | #define SHA1_MSG2(dest, src) dest = _mm_sha1msg2_epu32(dest, src); | 84 | #define SHA1_MSG2(dest, src) dest = _mm_sha1msg2_epu32(dest, src); |
101 | 85 | ||
102 | |||
103 | #define LOAD_SHUFFLE(m, k) \ | 86 | #define LOAD_SHUFFLE(m, k) \ |
104 | m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ | 87 | m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ |
105 | SHUFFLE_EPI8(m, mask) \ | 88 | SHUFFLE_EPI8(m, mask) \ |
106 | 89 | ||
90 | #define NNN(m0, m1, m2, m3) | ||
91 | |||
107 | #define SM1(m0, m1, m2, m3) \ | 92 | #define SM1(m0, m1, m2, m3) \ |
108 | SHA1_MSG1(m0, m1) \ | 93 | SHA1_MSG1(m0, m1) \ |
109 | 94 | ||
@@ -116,35 +101,19 @@ SHA: | |||
116 | SM1(m0, m1, m2, m3) \ | 101 | SM1(m0, m1, m2, m3) \ |
117 | SHA1_MSG2(m3, m2) \ | 102 | SHA1_MSG2(m3, m2) \ |
118 | 103 | ||
119 | #define NNN(m0, m1, m2, m3) | 104 | #define R4(k, m0, m1, m2, m3, e0, e1, OP) \ |
120 | |||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | |||
128 | |||
129 | |||
130 | |||
131 | |||
132 | |||
133 | |||
134 | |||
135 | |||
136 | |||
137 | #define R4(k, e0, e1, m0, m1, m2, m3, OP) \ | ||
138 | e1 = abcd; \ | 105 | e1 = abcd; \ |
139 | SHA1_RND4(abcd, e0, (k) / 5) \ | 106 | SHA1_RND4(abcd, e0, (k) / 5) \ |
140 | SHA1_NEXTE(e1, m1) \ | 107 | SHA1_NEXTE(e1, m1) \ |
141 | OP(m0, m1, m2, m3) \ | 108 | OP(m0, m1, m2, m3) \ |
142 | 109 | ||
110 | |||
111 | |||
143 | #define R16(k, mx, OP0, OP1, OP2, OP3) \ | 112 | #define R16(k, mx, OP0, OP1, OP2, OP3) \ |
144 | R4 ( (k)*4+0, e0,e1, m0,m1,m2,m3, OP0 ) \ | 113 | R4 ( (k)*4+0, m0,m1,m2,m3, e0,e1, OP0 ) \ |
145 | R4 ( (k)*4+1, e1,e0, m1,m2,m3,m0, OP1 ) \ | 114 | R4 ( (k)*4+1, m1,m2,m3,m0, e1,e0, OP1 ) \ |
146 | R4 ( (k)*4+2, e0,e1, m2,m3,m0,m1, OP2 ) \ | 115 | R4 ( (k)*4+2, m2,m3,m0,m1, e0,e1, OP2 ) \ |
147 | R4 ( (k)*4+3, e1,e0, m3,mx,m1,m2, OP3 ) \ | 116 | R4 ( (k)*4+3, m3,mx,m1,m2, e1,e0, OP3 ) \ |
148 | 117 | ||
149 | #define PREPARE_STATE \ | 118 | #define PREPARE_STATE \ |
150 | SHUFFLE_EPI32 (abcd, 0x1B) \ | 119 | SHUFFLE_EPI32 (abcd, 0x1B) \ |
@@ -162,8 +131,9 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t | |||
162 | { | 131 | { |
163 | const __m128i mask = _mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); | 132 | const __m128i mask = _mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); |
164 | 133 | ||
165 | __m128i abcd, e0; | ||
166 | 134 | ||
135 | __m128i abcd, e0; | ||
136 | |||
167 | if (numBlocks == 0) | 137 | if (numBlocks == 0) |
168 | return; | 138 | return; |
169 | 139 | ||
@@ -204,7 +174,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t | |||
204 | PREPARE_STATE | 174 | PREPARE_STATE |
205 | 175 | ||
206 | _mm_storeu_si128((__m128i *) (void *) state, abcd); | 176 | _mm_storeu_si128((__m128i *) (void *) state, abcd); |
207 | *(state+4) = (UInt32)_mm_cvtsi128_si32(e0); | 177 | *(state + 4) = (UInt32)_mm_cvtsi128_si32(e0); |
208 | } | 178 | } |
209 | 179 | ||
210 | #endif // USE_HW_SHA | 180 | #endif // USE_HW_SHA |
@@ -262,22 +232,10 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t | |||
262 | #define _ARM_USE_NEW_NEON_INTRINSICS | 232 | #define _ARM_USE_NEW_NEON_INTRINSICS |
263 | #endif | 233 | #endif |
264 | 234 | ||
265 | |||
266 | |||
267 | |||
268 | |||
269 | #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) | 235 | #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) |
270 | #include <arm64_neon.h> | 236 | #include <arm64_neon.h> |
271 | #else | 237 | #else |
272 | 238 | ||
273 | |||
274 | |||
275 | |||
276 | |||
277 | |||
278 | |||
279 | |||
280 | |||
281 | #if defined(__clang__) && __clang_major__ < 16 | 239 | #if defined(__clang__) && __clang_major__ < 16 |
282 | #if !defined(__ARM_FEATURE_SHA2) && \ | 240 | #if !defined(__ARM_FEATURE_SHA2) && \ |
283 | !defined(__ARM_FEATURE_CRYPTO) | 241 | !defined(__ARM_FEATURE_CRYPTO) |
@@ -329,26 +287,37 @@ typedef uint32x4_t v128; | |||
329 | #endif | 287 | #endif |
330 | 288 | ||
331 | #ifdef MY_CPU_BE | 289 | #ifdef MY_CPU_BE |
332 | #define MY_rev32_for_LE(x) | 290 | #define MY_rev32_for_LE(x) x |
333 | #else | 291 | #else |
334 | #define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x))) | 292 | #define MY_rev32_for_LE(x) vrev32q_u8(x) |
335 | #endif | 293 | #endif |
336 | 294 | ||
337 | #define LOAD_128(_p) (*(const v128 *)(const void *)(_p)) | 295 | #define LOAD_128_32(_p) vld1q_u32(_p) |
338 | #define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v) | 296 | #define LOAD_128_8(_p) vld1q_u8 (_p) |
297 | #define STORE_128_32(_p, _v) vst1q_u32(_p, _v) | ||
339 | 298 | ||
340 | #define LOAD_SHUFFLE(m, k) \ | 299 | #define LOAD_SHUFFLE(m, k) \ |
341 | m = LOAD_128((data + (k) * 16)); \ | 300 | m = vreinterpretq_u32_u8( \ |
342 | MY_rev32_for_LE(m); \ | 301 | MY_rev32_for_LE( \ |
343 | 302 | LOAD_128_8(data + (k) * 16))); \ | |
344 | #define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3) | 303 | |
345 | #define SU1(dest, src) dest = vsha1su1q_u32(dest, src) | 304 | #define N0(dest, src2, src3) |
305 | #define N1(dest, src) | ||
306 | #define U0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3); | ||
307 | #define U1(dest, src) dest = vsha1su1q_u32(dest, src); | ||
346 | #define C(e) abcd = vsha1cq_u32(abcd, e, t) | 308 | #define C(e) abcd = vsha1cq_u32(abcd, e, t) |
347 | #define P(e) abcd = vsha1pq_u32(abcd, e, t) | 309 | #define P(e) abcd = vsha1pq_u32(abcd, e, t) |
348 | #define M(e) abcd = vsha1mq_u32(abcd, e, t) | 310 | #define M(e) abcd = vsha1mq_u32(abcd, e, t) |
349 | #define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0)) | 311 | #define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0)) |
350 | #define T(m, c) t = vaddq_u32(m, c) | 312 | #define T(m, c) t = vaddq_u32(m, c) |
351 | 313 | ||
314 | #define R16(d0,d1,d2,d3, f0,z0, f1,z1, f2,z2, f3,z3, w0,w1,w2,w3) \ | ||
315 | T(m0, d0); f0(m3, m0, m1) z0(m2, m1) H(e1); w0(e0); \ | ||
316 | T(m1, d1); f1(m0, m1, m2) z1(m3, m2) H(e0); w1(e1); \ | ||
317 | T(m2, d2); f2(m1, m2, m3) z2(m0, m3) H(e1); w2(e0); \ | ||
318 | T(m3, d3); f3(m2, m3, m0) z3(m1, m0) H(e0); w3(e1); \ | ||
319 | |||
320 | |||
352 | void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); | 321 | void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); |
353 | #ifdef ATTRIB_SHA | 322 | #ifdef ATTRIB_SHA |
354 | ATTRIB_SHA | 323 | ATTRIB_SHA |
@@ -367,7 +336,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t | |||
367 | c2 = vdupq_n_u32(0x8f1bbcdc); | 336 | c2 = vdupq_n_u32(0x8f1bbcdc); |
368 | c3 = vdupq_n_u32(0xca62c1d6); | 337 | c3 = vdupq_n_u32(0xca62c1d6); |
369 | 338 | ||
370 | abcd = LOAD_128(&state[0]); | 339 | abcd = LOAD_128_32(&state[0]); |
371 | e0 = state[4]; | 340 | e0 = state[4]; |
372 | 341 | ||
373 | do | 342 | do |
@@ -385,26 +354,11 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t | |||
385 | LOAD_SHUFFLE (m2, 2) | 354 | LOAD_SHUFFLE (m2, 2) |
386 | LOAD_SHUFFLE (m3, 3) | 355 | LOAD_SHUFFLE (m3, 3) |
387 | 356 | ||
388 | T(m0, c0); H(e1); C(e0); | 357 | R16 ( c0,c0,c0,c0, N0,N1, U0,N1, U0,U1, U0,U1, C,C,C,C ) |
389 | T(m1, c0); SU0(m0, m1, m2); H(e0); C(e1); | 358 | R16 ( c0,c1,c1,c1, U0,U1, U0,U1, U0,U1, U0,U1, C,P,P,P ) |
390 | T(m2, c0); SU0(m1, m2, m3); SU1(m0, m3); H(e1); C(e0); | 359 | R16 ( c1,c1,c2,c2, U0,U1, U0,U1, U0,U1, U0,U1, P,P,M,M ) |
391 | T(m3, c0); SU0(m2, m3, m0); SU1(m1, m0); H(e0); C(e1); | 360 | R16 ( c2,c2,c2,c3, U0,U1, U0,U1, U0,U1, U0,U1, M,M,M,P ) |
392 | T(m0, c0); SU0(m3, m0, m1); SU1(m2, m1); H(e1); C(e0); | 361 | R16 ( c3,c3,c3,c3, U0,U1, N0,U1, N0,N1, N0,N1, P,P,P,P ) |
393 | T(m1, c1); SU0(m0, m1, m2); SU1(m3, m2); H(e0); P(e1); | ||
394 | T(m2, c1); SU0(m1, m2, m3); SU1(m0, m3); H(e1); P(e0); | ||
395 | T(m3, c1); SU0(m2, m3, m0); SU1(m1, m0); H(e0); P(e1); | ||
396 | T(m0, c1); SU0(m3, m0, m1); SU1(m2, m1); H(e1); P(e0); | ||
397 | T(m1, c1); SU0(m0, m1, m2); SU1(m3, m2); H(e0); P(e1); | ||
398 | T(m2, c2); SU0(m1, m2, m3); SU1(m0, m3); H(e1); M(e0); | ||
399 | T(m3, c2); SU0(m2, m3, m0); SU1(m1, m0); H(e0); M(e1); | ||
400 | T(m0, c2); SU0(m3, m0, m1); SU1(m2, m1); H(e1); M(e0); | ||
401 | T(m1, c2); SU0(m0, m1, m2); SU1(m3, m2); H(e0); M(e1); | ||
402 | T(m2, c2); SU0(m1, m2, m3); SU1(m0, m3); H(e1); M(e0); | ||
403 | T(m3, c3); SU0(m2, m3, m0); SU1(m1, m0); H(e0); P(e1); | ||
404 | T(m0, c3); SU0(m3, m0, m1); SU1(m2, m1); H(e1); P(e0); | ||
405 | T(m1, c3); SU1(m3, m2); H(e0); P(e1); | ||
406 | T(m2, c3); H(e1); P(e0); | ||
407 | T(m3, c3); H(e0); P(e1); | ||
408 | 362 | ||
409 | abcd = vaddq_u32(abcd, abcd_save); | 363 | abcd = vaddq_u32(abcd, abcd_save); |
410 | e0 += e0_save; | 364 | e0 += e0_save; |
@@ -413,7 +367,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t | |||
413 | } | 367 | } |
414 | while (--numBlocks); | 368 | while (--numBlocks); |
415 | 369 | ||
416 | STORE_128(&state[0], abcd); | 370 | STORE_128_32(&state[0], abcd); |
417 | state[4] = e0; | 371 | state[4] = e0; |
418 | } | 372 | } |
419 | 373 | ||
@@ -421,13 +375,9 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t | |||
421 | 375 | ||
422 | #endif // MY_CPU_ARM_OR_ARM64 | 376 | #endif // MY_CPU_ARM_OR_ARM64 |
423 | 377 | ||
424 | |||
425 | #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB) | 378 | #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB) |
426 | // #error Stop_Compiling_UNSUPPORTED_SHA | 379 | // #error Stop_Compiling_UNSUPPORTED_SHA |
427 | // #include <stdlib.h> | 380 | // #include <stdlib.h> |
428 | |||
429 | |||
430 | |||
431 | // #include "Sha1.h" | 381 | // #include "Sha1.h" |
432 | // #if defined(_MSC_VER) | 382 | // #if defined(_MSC_VER) |
433 | #pragma message("Sha1 HW-SW stub was used") | 383 | #pragma message("Sha1 HW-SW stub was used") |
@@ -447,8 +397,10 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t | |||
447 | } | 397 | } |
448 | #endif | 398 | #endif |
449 | 399 | ||
450 | #undef SU0 | 400 | #undef U0 |
451 | #undef SU1 | 401 | #undef U1 |
402 | #undef N0 | ||
403 | #undef N1 | ||
452 | #undef C | 404 | #undef C |
453 | #undef P | 405 | #undef P |
454 | #undef M | 406 | #undef M |
@@ -1,18 +1,14 @@ | |||
1 | /* Sha256.c -- SHA-256 Hash | 1 | /* Sha256.c -- SHA-256 Hash |
2 | 2024-03-01 : Igor Pavlov : Public domain | 2 | : Igor Pavlov : Public domain |
3 | This code is based on public domain code from Wei Dai's Crypto++ library. */ | 3 | This code is based on public domain code from Wei Dai's Crypto++ library. */ |
4 | 4 | ||
5 | #include "Precomp.h" | 5 | #include "Precomp.h" |
6 | 6 | ||
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #include "CpuArch.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "Sha256.h" | 9 | #include "Sha256.h" |
12 | 10 | #include "RotateDefs.h" | |
13 | #if defined(_MSC_VER) && (_MSC_VER < 1900) | 11 | #include "CpuArch.h" |
14 | // #define USE_MY_MM | ||
15 | #endif | ||
16 | 12 | ||
17 | #ifdef MY_CPU_X86_OR_AMD64 | 13 | #ifdef MY_CPU_X86_OR_AMD64 |
18 | #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ | 14 | #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \ |
@@ -56,7 +52,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n | |||
56 | static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks; | 52 | static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks; |
57 | static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW; | 53 | static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW; |
58 | 54 | ||
59 | #define SHA256_UPDATE_BLOCKS(p) p->func_UpdateBlocks | 55 | #define SHA256_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks |
60 | #else | 56 | #else |
61 | #define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks | 57 | #define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks |
62 | #endif | 58 | #endif |
@@ -85,7 +81,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo) | |||
85 | return False; | 81 | return False; |
86 | #endif | 82 | #endif |
87 | 83 | ||
88 | p->func_UpdateBlocks = func; | 84 | p->v.vars.func_UpdateBlocks = func; |
89 | return True; | 85 | return True; |
90 | } | 86 | } |
91 | 87 | ||
@@ -111,7 +107,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo) | |||
111 | 107 | ||
112 | void Sha256_InitState(CSha256 *p) | 108 | void Sha256_InitState(CSha256 *p) |
113 | { | 109 | { |
114 | p->count = 0; | 110 | p->v.vars.count = 0; |
115 | p->state[0] = 0x6a09e667; | 111 | p->state[0] = 0x6a09e667; |
116 | p->state[1] = 0xbb67ae85; | 112 | p->state[1] = 0xbb67ae85; |
117 | p->state[2] = 0x3c6ef372; | 113 | p->state[2] = 0x3c6ef372; |
@@ -122,9 +118,16 @@ void Sha256_InitState(CSha256 *p) | |||
122 | p->state[7] = 0x5be0cd19; | 118 | p->state[7] = 0x5be0cd19; |
123 | } | 119 | } |
124 | 120 | ||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | |||
125 | void Sha256_Init(CSha256 *p) | 128 | void Sha256_Init(CSha256 *p) |
126 | { | 129 | { |
127 | p->func_UpdateBlocks = | 130 | p->v.vars.func_UpdateBlocks = |
128 | #ifdef Z7_COMPILER_SHA256_SUPPORTED | 131 | #ifdef Z7_COMPILER_SHA256_SUPPORTED |
129 | g_SHA256_FUNC_UPDATE_BLOCKS; | 132 | g_SHA256_FUNC_UPDATE_BLOCKS; |
130 | #else | 133 | #else |
@@ -133,10 +136,10 @@ void Sha256_Init(CSha256 *p) | |||
133 | Sha256_InitState(p); | 136 | Sha256_InitState(p); |
134 | } | 137 | } |
135 | 138 | ||
136 | #define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) | 139 | #define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x,22)) |
137 | #define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) | 140 | #define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x,25)) |
138 | #define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) | 141 | #define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) |
139 | #define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) | 142 | #define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >>10)) |
140 | 143 | ||
141 | #define Ch(x,y,z) (z^(x&(y^z))) | 144 | #define Ch(x,y,z) (z^(x&(y^z))) |
142 | #define Maj(x,y,z) ((x&y)|(z&(x|y))) | 145 | #define Maj(x,y,z) ((x&y)|(z&(x|y))) |
@@ -224,12 +227,10 @@ void Sha256_Init(CSha256 *p) | |||
224 | 227 | ||
225 | #endif | 228 | #endif |
226 | 229 | ||
227 | // static | ||
228 | extern MY_ALIGN(64) | ||
229 | const UInt32 SHA256_K_ARRAY[64]; | ||
230 | 230 | ||
231 | MY_ALIGN(64) | 231 | extern |
232 | const UInt32 SHA256_K_ARRAY[64] = { | 232 | MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64]; |
233 | MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64] = { | ||
233 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, | 234 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, |
234 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | 235 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
235 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, | 236 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
@@ -248,27 +249,29 @@ const UInt32 SHA256_K_ARRAY[64] = { | |||
248 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | 249 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
249 | }; | 250 | }; |
250 | 251 | ||
251 | #define K SHA256_K_ARRAY | ||
252 | 252 | ||
253 | 253 | ||
254 | |||
255 | |||
256 | #define K SHA256_K_ARRAY | ||
257 | |||
254 | Z7_NO_INLINE | 258 | Z7_NO_INLINE |
255 | void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks) | 259 | void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks) |
256 | { | 260 | { |
257 | UInt32 W | 261 | UInt32 W |
258 | #ifdef Z7_SHA256_BIG_W | 262 | #ifdef Z7_SHA256_BIG_W |
259 | [64]; | 263 | [64]; |
260 | #else | 264 | #else |
261 | [16]; | 265 | [16]; |
262 | #endif | 266 | #endif |
263 | |||
264 | unsigned j; | 267 | unsigned j; |
265 | |||
266 | UInt32 a,b,c,d,e,f,g,h; | 268 | UInt32 a,b,c,d,e,f,g,h; |
267 | 269 | #if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) | |
268 | #if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) | ||
269 | UInt32 tmp; | 270 | UInt32 tmp; |
270 | #endif | 271 | #endif |
271 | 272 | ||
273 | if (numBlocks == 0) return; | ||
274 | |||
272 | a = state[0]; | 275 | a = state[0]; |
273 | b = state[1]; | 276 | b = state[1]; |
274 | c = state[2]; | 277 | c = state[2]; |
@@ -278,7 +281,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n | |||
278 | g = state[6]; | 281 | g = state[6]; |
279 | h = state[7]; | 282 | h = state[7]; |
280 | 283 | ||
281 | while (numBlocks) | 284 | do |
282 | { | 285 | { |
283 | 286 | ||
284 | for (j = 0; j < 16; j += STEP_PRE) | 287 | for (j = 0; j < 16; j += STEP_PRE) |
@@ -352,19 +355,11 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n | |||
352 | g += state[6]; state[6] = g; | 355 | g += state[6]; state[6] = g; |
353 | h += state[7]; state[7] = h; | 356 | h += state[7]; state[7] = h; |
354 | 357 | ||
355 | data += 64; | 358 | data += SHA256_BLOCK_SIZE; |
356 | numBlocks--; | ||
357 | } | 359 | } |
358 | 360 | while (--numBlocks); | |
359 | /* Wipe variables */ | ||
360 | /* memset(W, 0, sizeof(W)); */ | ||
361 | } | 361 | } |
362 | 362 | ||
363 | #undef S0 | ||
364 | #undef S1 | ||
365 | #undef s0 | ||
366 | #undef s1 | ||
367 | #undef K | ||
368 | 363 | ||
369 | #define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) | 364 | #define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) |
370 | 365 | ||
@@ -372,20 +367,15 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size) | |||
372 | { | 367 | { |
373 | if (size == 0) | 368 | if (size == 0) |
374 | return; | 369 | return; |
375 | |||
376 | { | 370 | { |
377 | unsigned pos = (unsigned)p->count & 0x3F; | 371 | const unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1); |
378 | unsigned num; | 372 | const unsigned num = SHA256_BLOCK_SIZE - pos; |
379 | 373 | p->v.vars.count += size; | |
380 | p->count += size; | ||
381 | |||
382 | num = 64 - pos; | ||
383 | if (num > size) | 374 | if (num > size) |
384 | { | 375 | { |
385 | memcpy(p->buffer + pos, data, size); | 376 | memcpy(p->buffer + pos, data, size); |
386 | return; | 377 | return; |
387 | } | 378 | } |
388 | |||
389 | if (pos != 0) | 379 | if (pos != 0) |
390 | { | 380 | { |
391 | size -= num; | 381 | size -= num; |
@@ -395,9 +385,10 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size) | |||
395 | } | 385 | } |
396 | } | 386 | } |
397 | { | 387 | { |
398 | size_t numBlocks = size >> 6; | 388 | const size_t numBlocks = size >> 6; |
389 | // if (numBlocks) | ||
399 | SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks); | 390 | SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks); |
400 | size &= 0x3F; | 391 | size &= SHA256_BLOCK_SIZE - 1; |
401 | if (size == 0) | 392 | if (size == 0) |
402 | return; | 393 | return; |
403 | data += (numBlocks << 6); | 394 | data += (numBlocks << 6); |
@@ -408,82 +399,69 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size) | |||
408 | 399 | ||
409 | void Sha256_Final(CSha256 *p, Byte *digest) | 400 | void Sha256_Final(CSha256 *p, Byte *digest) |
410 | { | 401 | { |
411 | unsigned pos = (unsigned)p->count & 0x3F; | 402 | unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1); |
412 | unsigned i; | ||
413 | |||
414 | p->buffer[pos++] = 0x80; | 403 | p->buffer[pos++] = 0x80; |
415 | 404 | if (pos > (SHA256_BLOCK_SIZE - 4 * 2)) | |
416 | if (pos > (64 - 8)) | ||
417 | { | 405 | { |
418 | while (pos != 64) { p->buffer[pos++] = 0; } | 406 | while (pos != SHA256_BLOCK_SIZE) { p->buffer[pos++] = 0; } |
419 | // memset(&p->buf.buffer[pos], 0, 64 - pos); | 407 | // memset(&p->buf.buffer[pos], 0, SHA256_BLOCK_SIZE - pos); |
420 | Sha256_UpdateBlock(p); | 408 | Sha256_UpdateBlock(p); |
421 | pos = 0; | 409 | pos = 0; |
422 | } | 410 | } |
423 | 411 | memset(&p->buffer[pos], 0, (SHA256_BLOCK_SIZE - 4 * 2) - pos); | |
424 | /* | ||
425 | if (pos & 3) | ||
426 | { | 412 | { |
427 | p->buffer[pos] = 0; | 413 | const UInt64 numBits = p->v.vars.count << 3; |
428 | p->buffer[pos + 1] = 0; | 414 | SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32)) |
429 | p->buffer[pos + 2] = 0; | 415 | SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 1, (UInt32)(numBits)) |
430 | pos += 3; | ||
431 | pos &= ~3; | ||
432 | } | 416 | } |
417 | Sha256_UpdateBlock(p); | ||
418 | #if 1 && defined(MY_CPU_BE) | ||
419 | memcpy(digest, p->state, SHA256_DIGEST_SIZE); | ||
420 | #else | ||
433 | { | 421 | { |
434 | for (; pos < 64 - 8; pos += 4) | 422 | unsigned i; |
435 | *(UInt32 *)(&p->buffer[pos]) = 0; | 423 | for (i = 0; i < 8; i += 2) |
424 | { | ||
425 | const UInt32 v0 = p->state[i]; | ||
426 | const UInt32 v1 = p->state[(size_t)i + 1]; | ||
427 | SetBe32(digest , v0) | ||
428 | SetBe32(digest + 4, v1) | ||
429 | digest += 4 * 2; | ||
430 | } | ||
436 | } | 431 | } |
437 | */ | ||
438 | 432 | ||
439 | memset(&p->buffer[pos], 0, (64 - 8) - pos); | ||
440 | 433 | ||
441 | { | ||
442 | UInt64 numBits = (p->count << 3); | ||
443 | SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)) | ||
444 | SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)) | ||
445 | } | ||
446 | |||
447 | Sha256_UpdateBlock(p); | ||
448 | 434 | ||
449 | for (i = 0; i < 8; i += 2) | 435 | |
450 | { | 436 | #endif |
451 | UInt32 v0 = p->state[i]; | ||
452 | UInt32 v1 = p->state[(size_t)i + 1]; | ||
453 | SetBe32(digest , v0) | ||
454 | SetBe32(digest + 4, v1) | ||
455 | digest += 8; | ||
456 | } | ||
457 | |||
458 | Sha256_InitState(p); | 437 | Sha256_InitState(p); |
459 | } | 438 | } |
460 | 439 | ||
461 | 440 | ||
462 | void Sha256Prepare(void) | 441 | void Sha256Prepare(void) |
463 | { | 442 | { |
464 | #ifdef Z7_COMPILER_SHA256_SUPPORTED | 443 | #ifdef Z7_COMPILER_SHA256_SUPPORTED |
465 | SHA256_FUNC_UPDATE_BLOCKS f, f_hw; | 444 | SHA256_FUNC_UPDATE_BLOCKS f, f_hw; |
466 | f = Sha256_UpdateBlocks; | 445 | f = Sha256_UpdateBlocks; |
467 | f_hw = NULL; | 446 | f_hw = NULL; |
468 | #ifdef MY_CPU_X86_OR_AMD64 | 447 | #ifdef MY_CPU_X86_OR_AMD64 |
469 | #ifndef USE_MY_MM | ||
470 | if (CPU_IsSupported_SHA() | 448 | if (CPU_IsSupported_SHA() |
471 | && CPU_IsSupported_SSSE3() | 449 | && CPU_IsSupported_SSSE3() |
472 | // && CPU_IsSupported_SSE41() | ||
473 | ) | 450 | ) |
474 | #endif | 451 | #else |
475 | #else | ||
476 | if (CPU_IsSupported_SHA2()) | 452 | if (CPU_IsSupported_SHA2()) |
477 | #endif | 453 | #endif |
478 | { | 454 | { |
479 | // printf("\n========== HW SHA256 ======== \n"); | 455 | // printf("\n========== HW SHA256 ======== \n"); |
480 | f = f_hw = Sha256_UpdateBlocks_HW; | 456 | f = f_hw = Sha256_UpdateBlocks_HW; |
481 | } | 457 | } |
482 | g_SHA256_FUNC_UPDATE_BLOCKS = f; | 458 | g_SHA256_FUNC_UPDATE_BLOCKS = f; |
483 | g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw; | 459 | g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw; |
484 | #endif | 460 | #endif |
485 | } | 461 | } |
486 | 462 | ||
463 | #undef U64C | ||
464 | #undef K | ||
487 | #undef S0 | 465 | #undef S0 |
488 | #undef S1 | 466 | #undef S1 |
489 | #undef s0 | 467 | #undef s0 |
@@ -1,5 +1,5 @@ | |||
1 | /* Sha256.h -- SHA-256 Hash | 1 | /* Sha256.h -- SHA-256 Hash |
2 | 2023-04-02 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_SHA256_H | 4 | #ifndef ZIP7_INC_SHA256_H |
5 | #define ZIP7_INC_SHA256_H | 5 | #define ZIP7_INC_SHA256_H |
@@ -14,6 +14,9 @@ EXTERN_C_BEGIN | |||
14 | #define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4) | 14 | #define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4) |
15 | #define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4) | 15 | #define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4) |
16 | 16 | ||
17 | |||
18 | |||
19 | |||
17 | typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks); | 20 | typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks); |
18 | 21 | ||
19 | /* | 22 | /* |
@@ -32,9 +35,16 @@ typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byt | |||
32 | 35 | ||
33 | typedef struct | 36 | typedef struct |
34 | { | 37 | { |
35 | SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks; | 38 | union |
36 | UInt64 count; | 39 | { |
37 | UInt64 _pad_2[2]; | 40 | struct |
41 | { | ||
42 | SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks; | ||
43 | UInt64 count; | ||
44 | } vars; | ||
45 | UInt64 _pad_64bit[4]; | ||
46 | void *_pad_align_ptr[2]; | ||
47 | } v; | ||
38 | UInt32 state[SHA256_NUM_DIGEST_WORDS]; | 48 | UInt32 state[SHA256_NUM_DIGEST_WORDS]; |
39 | 49 | ||
40 | Byte buffer[SHA256_BLOCK_SIZE]; | 50 | Byte buffer[SHA256_BLOCK_SIZE]; |
diff --git a/C/Sha256Opt.c b/C/Sha256Opt.c index eb38166..1c6b50f 100644 --- a/C/Sha256Opt.c +++ b/C/Sha256Opt.c | |||
@@ -1,18 +1,11 @@ | |||
1 | /* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions | 1 | /* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | #include "Compiler.h" | 5 | #include "Compiler.h" |
6 | #include "CpuArch.h" | 6 | #include "CpuArch.h" |
7 | 7 | ||
8 | #if defined(_MSC_VER) | ||
9 | #if (_MSC_VER < 1900) && (_MSC_VER >= 1200) | ||
10 | // #define USE_MY_MM | ||
11 | #endif | ||
12 | #endif | ||
13 | |||
14 | // #define Z7_USE_HW_SHA_STUB // for debug | 8 | // #define Z7_USE_HW_SHA_STUB // for debug |
15 | |||
16 | #ifdef MY_CPU_X86_OR_AMD64 | 9 | #ifdef MY_CPU_X86_OR_AMD64 |
17 | #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check | 10 | #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check |
18 | #define USE_HW_SHA | 11 | #define USE_HW_SHA |
@@ -20,19 +13,14 @@ | |||
20 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ | 13 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \ |
21 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) | 14 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) |
22 | #define USE_HW_SHA | 15 | #define USE_HW_SHA |
23 | #if !defined(_INTEL_COMPILER) | 16 | #if !defined(__INTEL_COMPILER) |
24 | // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) | 17 | // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) |
25 | #if !defined(__SHA__) || !defined(__SSSE3__) | 18 | #if !defined(__SHA__) || !defined(__SSSE3__) |
26 | #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) | 19 | #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) |
27 | #endif | 20 | #endif |
28 | #endif | 21 | #endif |
29 | #elif defined(_MSC_VER) | 22 | #elif defined(_MSC_VER) |
30 | #ifdef USE_MY_MM | 23 | #if (_MSC_VER >= 1900) |
31 | #define USE_VER_MIN 1300 | ||
32 | #else | ||
33 | #define USE_VER_MIN 1900 | ||
34 | #endif | ||
35 | #if (_MSC_VER >= USE_VER_MIN) | ||
36 | #define USE_HW_SHA | 24 | #define USE_HW_SHA |
37 | #else | 25 | #else |
38 | #define Z7_USE_HW_SHA_STUB | 26 | #define Z7_USE_HW_SHA_STUB |
@@ -47,23 +35,20 @@ | |||
47 | 35 | ||
48 | // #pragma message("Sha256 HW") | 36 | // #pragma message("Sha256 HW") |
49 | 37 | ||
38 | |||
39 | |||
40 | |||
50 | // sse/sse2/ssse3: | 41 | // sse/sse2/ssse3: |
51 | #include <tmmintrin.h> | 42 | #include <tmmintrin.h> |
52 | // sha*: | 43 | // sha*: |
53 | #include <immintrin.h> | 44 | #include <immintrin.h> |
54 | 45 | ||
55 | #if defined (__clang__) && defined(_MSC_VER) | 46 | #if defined (__clang__) && defined(_MSC_VER) |
56 | // #if !defined(__SSSE3__) | ||
57 | // #endif | ||
58 | #if !defined(__SHA__) | 47 | #if !defined(__SHA__) |
59 | #include <shaintrin.h> | 48 | #include <shaintrin.h> |
60 | #endif | 49 | #endif |
61 | #else | 50 | #else |
62 | 51 | ||
63 | #ifdef USE_MY_MM | ||
64 | #include "My_mm.h" | ||
65 | #endif | ||
66 | |||
67 | #endif | 52 | #endif |
68 | 53 | ||
69 | /* | 54 | /* |
@@ -91,60 +76,44 @@ SHA: | |||
91 | extern | 76 | extern |
92 | MY_ALIGN(64) | 77 | MY_ALIGN(64) |
93 | const UInt32 SHA256_K_ARRAY[64]; | 78 | const UInt32 SHA256_K_ARRAY[64]; |
94 | |||
95 | #define K SHA256_K_ARRAY | 79 | #define K SHA256_K_ARRAY |
96 | 80 | ||
97 | 81 | ||
98 | #define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src); | 82 | #define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src); |
99 | #define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src); | 83 | #define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src); |
100 | #define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src); | 84 | #define SHA256_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src); |
101 | |||
102 | 85 | ||
103 | #define LOAD_SHUFFLE(m, k) \ | 86 | #define LOAD_SHUFFLE(m, k) \ |
104 | m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ | 87 | m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ |
105 | m = _mm_shuffle_epi8(m, mask); \ | 88 | m = _mm_shuffle_epi8(m, mask); \ |
106 | 89 | ||
107 | #define SM1(g0, g1, g2, g3) \ | 90 | #define NNN(m0, m1, m2, m3) |
108 | SHA256_MSG1(g3, g0); \ | ||
109 | 91 | ||
110 | #define SM2(g0, g1, g2, g3) \ | 92 | #define SM1(m1, m2, m3, m0) \ |
111 | tmp = _mm_alignr_epi8(g1, g0, 4); \ | 93 | SHA256_MSG1(m0, m1); \ |
112 | ADD_EPI32(g2, tmp) \ | ||
113 | SHA25G_MSG2(g2, g1); \ | ||
114 | |||
115 | // #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k) | ||
116 | // #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1) | ||
117 | |||
118 | |||
119 | #define NNN(g0, g1, g2, g3) | ||
120 | 94 | ||
95 | #define SM2(m2, m3, m0, m1) \ | ||
96 | ADD_EPI32(m0, _mm_alignr_epi8(m3, m2, 4)) \ | ||
97 | SHA256_MSG2(m0, m3); \ | ||
121 | 98 | ||
122 | #define RND2(t0, t1) \ | 99 | #define RND2(t0, t1) \ |
123 | t0 = _mm_sha256rnds2_epu32(t0, t1, msg); | 100 | t0 = _mm_sha256rnds2_epu32(t0, t1, msg); |
124 | 101 | ||
125 | #define RND2_0(m, k) \ | ||
126 | msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \ | ||
127 | RND2(state0, state1); \ | ||
128 | msg = _mm_shuffle_epi32(msg, 0x0E); \ | ||
129 | 102 | ||
130 | 103 | ||
131 | #define RND2_1 \ | 104 | #define R4(k, m0, m1, m2, m3, OP0, OP1) \ |
105 | msg = _mm_add_epi32(m0, *(const __m128i *) (const void *) &K[(k) * 4]); \ | ||
106 | RND2(state0, state1); \ | ||
107 | msg = _mm_shuffle_epi32(msg, 0x0E); \ | ||
108 | OP0(m0, m1, m2, m3) \ | ||
132 | RND2(state1, state0); \ | 109 | RND2(state1, state0); \ |
133 | 110 | OP1(m0, m1, m2, m3) \ | |
134 | |||
135 | // We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2 | ||
136 | |||
137 | #define R4(k, g0, g1, g2, g3, OP0, OP1) \ | ||
138 | RND2_0(g0, k) \ | ||
139 | OP0(g0, g1, g2, g3) \ | ||
140 | RND2_1 \ | ||
141 | OP1(g0, g1, g2, g3) \ | ||
142 | 111 | ||
143 | #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ | 112 | #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ |
144 | R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \ | 113 | R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \ |
145 | R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \ | 114 | R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \ |
146 | R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \ | 115 | R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \ |
147 | R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \ | 116 | R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \ |
148 | 117 | ||
149 | #define PREPARE_STATE \ | 118 | #define PREPARE_STATE \ |
150 | tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \ | 119 | tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \ |
@@ -161,8 +130,9 @@ ATTRIB_SHA | |||
161 | void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) | 130 | void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) |
162 | { | 131 | { |
163 | const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203); | 132 | const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203); |
164 | __m128i tmp; | 133 | |
165 | __m128i state0, state1; | 134 | |
135 | __m128i tmp, state0, state1; | ||
166 | 136 | ||
167 | if (numBlocks == 0) | 137 | if (numBlocks == 0) |
168 | return; | 138 | return; |
@@ -262,22 +232,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_ | |||
262 | #define _ARM_USE_NEW_NEON_INTRINSICS | 232 | #define _ARM_USE_NEW_NEON_INTRINSICS |
263 | #endif | 233 | #endif |
264 | 234 | ||
265 | |||
266 | |||
267 | |||
268 | |||
269 | #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) | 235 | #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64) |
270 | #include <arm64_neon.h> | 236 | #include <arm64_neon.h> |
271 | #else | 237 | #else |
272 | 238 | ||
273 | |||
274 | |||
275 | |||
276 | |||
277 | |||
278 | |||
279 | |||
280 | |||
281 | #if defined(__clang__) && __clang_major__ < 16 | 239 | #if defined(__clang__) && __clang_major__ < 16 |
282 | #if !defined(__ARM_FEATURE_SHA2) && \ | 240 | #if !defined(__ARM_FEATURE_SHA2) && \ |
283 | !defined(__ARM_FEATURE_CRYPTO) | 241 | !defined(__ARM_FEATURE_CRYPTO) |
@@ -324,41 +282,70 @@ typedef uint32x4_t v128; | |||
324 | // typedef __n128 v128; // MSVC | 282 | // typedef __n128 v128; // MSVC |
325 | 283 | ||
326 | #ifdef MY_CPU_BE | 284 | #ifdef MY_CPU_BE |
327 | #define MY_rev32_for_LE(x) | 285 | #define MY_rev32_for_LE(x) x |
328 | #else | 286 | #else |
329 | #define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x))) | 287 | #define MY_rev32_for_LE(x) vrev32q_u8(x) |
330 | #endif | 288 | #endif |
331 | 289 | ||
332 | #define LOAD_128(_p) (*(const v128 *)(const void *)(_p)) | 290 | #if 1 // 0 for debug |
333 | #define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v) | 291 | // for arm32: it works slower by some reason than direct code |
292 | /* | ||
293 | for arm32 it generates: | ||
294 | MSVC-2022, GCC-9: | ||
295 | vld1.32 {d18,d19}, [r10] | ||
296 | vst1.32 {d4,d5}, [r3] | ||
297 | vld1.8 {d20-d21}, [r4] | ||
298 | there is no align hint (like [r10:128]). So instruction allows unaligned access | ||
299 | */ | ||
300 | #define LOAD_128_32(_p) vld1q_u32(_p) | ||
301 | #define LOAD_128_8(_p) vld1q_u8 (_p) | ||
302 | #define STORE_128_32(_p, _v) vst1q_u32(_p, _v) | ||
303 | #else | ||
304 | /* | ||
305 | for arm32: | ||
306 | MSVC-2022: | ||
307 | vldm r10,{d18,d19} | ||
308 | vstm r3,{d4,d5} | ||
309 | does it require strict alignment? | ||
310 | GCC-9: | ||
311 | vld1.64 {d30-d31}, [r0:64] | ||
312 | vldr d28, [r0, #16] | ||
313 | vldr d29, [r0, #24] | ||
314 | vst1.64 {d30-d31}, [r0:64] | ||
315 | vstr d28, [r0, #16] | ||
316 | vstr d29, [r0, #24] | ||
317 | there is hint [r0:64], so does it requires 64-bit alignment. | ||
318 | */ | ||
319 | #define LOAD_128_32(_p) (*(const v128 *)(const void *)(_p)) | ||
320 | #define LOAD_128_8(_p) vreinterpretq_u8_u32(*(const v128 *)(const void *)(_p)) | ||
321 | #define STORE_128_32(_p, _v) *(v128 *)(void *)(_p) = (_v) | ||
322 | #endif | ||
334 | 323 | ||
335 | #define LOAD_SHUFFLE(m, k) \ | 324 | #define LOAD_SHUFFLE(m, k) \ |
336 | m = LOAD_128((data + (k) * 16)); \ | 325 | m = vreinterpretq_u32_u8( \ |
337 | MY_rev32_for_LE(m); \ | 326 | MY_rev32_for_LE( \ |
327 | LOAD_128_8(data + (k) * 16))); \ | ||
338 | 328 | ||
339 | // K array must be aligned for 16-bytes at least. | 329 | // K array must be aligned for 16-bytes at least. |
340 | extern | 330 | extern |
341 | MY_ALIGN(64) | 331 | MY_ALIGN(64) |
342 | const UInt32 SHA256_K_ARRAY[64]; | 332 | const UInt32 SHA256_K_ARRAY[64]; |
343 | |||
344 | #define K SHA256_K_ARRAY | 333 | #define K SHA256_K_ARRAY |
345 | 334 | ||
346 | |||
347 | #define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src); | 335 | #define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src); |
348 | #define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3); | 336 | #define SHA256_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3); |
349 | 337 | ||
350 | #define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0) | 338 | #define SM1(m0, m1, m2, m3) SHA256_SU0(m3, m0) |
351 | #define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1) | 339 | #define SM2(m0, m1, m2, m3) SHA256_SU1(m2, m0, m1) |
352 | #define NNN(g0, g1, g2, g3) | 340 | #define NNN(m0, m1, m2, m3) |
353 | 341 | ||
354 | 342 | #define R4(k, m0, m1, m2, m3, OP0, OP1) \ | |
355 | #define R4(k, g0, g1, g2, g3, OP0, OP1) \ | 343 | msg = vaddq_u32(m0, *(const v128 *) (const void *) &K[(k) * 4]); \ |
356 | msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \ | ||
357 | tmp = state0; \ | 344 | tmp = state0; \ |
358 | state0 = vsha256hq_u32( state0, state1, msg ); \ | 345 | state0 = vsha256hq_u32( state0, state1, msg ); \ |
359 | state1 = vsha256h2q_u32( state1, tmp, msg ); \ | 346 | state1 = vsha256h2q_u32( state1, tmp, msg ); \ |
360 | OP0(g0, g1, g2, g3); \ | 347 | OP0(m0, m1, m2, m3); \ |
361 | OP1(g0, g1, g2, g3); \ | 348 | OP1(m0, m1, m2, m3); \ |
362 | 349 | ||
363 | 350 | ||
364 | #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ | 351 | #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ |
@@ -379,8 +366,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_ | |||
379 | if (numBlocks == 0) | 366 | if (numBlocks == 0) |
380 | return; | 367 | return; |
381 | 368 | ||
382 | state0 = LOAD_128(&state[0]); | 369 | state0 = LOAD_128_32(&state[0]); |
383 | state1 = LOAD_128(&state[4]); | 370 | state1 = LOAD_128_32(&state[4]); |
384 | 371 | ||
385 | do | 372 | do |
386 | { | 373 | { |
@@ -408,8 +395,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_ | |||
408 | } | 395 | } |
409 | while (--numBlocks); | 396 | while (--numBlocks); |
410 | 397 | ||
411 | STORE_128(&state[0], state0); | 398 | STORE_128_32(&state[0], state0); |
412 | STORE_128(&state[4], state1); | 399 | STORE_128_32(&state[4], state1); |
413 | } | 400 | } |
414 | 401 | ||
415 | #endif // USE_HW_SHA | 402 | #endif // USE_HW_SHA |
@@ -443,13 +430,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_ | |||
443 | #endif | 430 | #endif |
444 | 431 | ||
445 | 432 | ||
446 | |||
447 | #undef K | 433 | #undef K |
448 | #undef RND2 | 434 | #undef RND2 |
449 | #undef RND2_0 | ||
450 | #undef RND2_1 | ||
451 | |||
452 | #undef MY_rev32_for_LE | 435 | #undef MY_rev32_for_LE |
436 | |||
453 | #undef NNN | 437 | #undef NNN |
454 | #undef LOAD_128 | 438 | #undef LOAD_128 |
455 | #undef STORE_128 | 439 | #undef STORE_128 |
@@ -457,7 +441,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_ | |||
457 | #undef SM1 | 441 | #undef SM1 |
458 | #undef SM2 | 442 | #undef SM2 |
459 | 443 | ||
460 | #undef NNN | 444 | |
461 | #undef R4 | 445 | #undef R4 |
462 | #undef R16 | 446 | #undef R16 |
463 | #undef PREPARE_STATE | 447 | #undef PREPARE_STATE |
diff --git a/C/Sha3.c b/C/Sha3.c new file mode 100644 index 0000000..be972d6 --- /dev/null +++ b/C/Sha3.c | |||
@@ -0,0 +1,359 @@ | |||
1 | /* Sha3.c -- SHA-3 Hash | ||
2 | : Igor Pavlov : Public domain | ||
3 | This code is based on public domain code from Wei Dai's Crypto++ library. */ | ||
4 | |||
5 | #include "Precomp.h" | ||
6 | |||
7 | #include <string.h> | ||
8 | |||
9 | #include "Sha3.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "CpuArch.h" | ||
12 | |||
13 | #define U64C(x) UINT64_CONST(x) | ||
14 | |||
15 | static | ||
16 | MY_ALIGN(64) | ||
17 | const UInt64 SHA3_K_ARRAY[24] = | ||
18 | { | ||
19 | U64C(0x0000000000000001), U64C(0x0000000000008082), | ||
20 | U64C(0x800000000000808a), U64C(0x8000000080008000), | ||
21 | U64C(0x000000000000808b), U64C(0x0000000080000001), | ||
22 | U64C(0x8000000080008081), U64C(0x8000000000008009), | ||
23 | U64C(0x000000000000008a), U64C(0x0000000000000088), | ||
24 | U64C(0x0000000080008009), U64C(0x000000008000000a), | ||
25 | U64C(0x000000008000808b), U64C(0x800000000000008b), | ||
26 | U64C(0x8000000000008089), U64C(0x8000000000008003), | ||
27 | U64C(0x8000000000008002), U64C(0x8000000000000080), | ||
28 | U64C(0x000000000000800a), U64C(0x800000008000000a), | ||
29 | U64C(0x8000000080008081), U64C(0x8000000000008080), | ||
30 | U64C(0x0000000080000001), U64C(0x8000000080008008) | ||
31 | }; | ||
32 | |||
33 | void Sha3_Init(CSha3 *p) | ||
34 | { | ||
35 | p->count = 0; | ||
36 | memset(p->state, 0, sizeof(p->state)); | ||
37 | } | ||
38 | |||
39 | #define GET_state(i, a) UInt64 a = state[i]; | ||
40 | #define SET_state(i, a) state[i] = a; | ||
41 | |||
42 | #define LS_5(M, i, a0,a1,a2,a3,a4) \ | ||
43 | M ((i) * 5 , a0) \ | ||
44 | M ((i) * 5 + 1, a1) \ | ||
45 | M ((i) * 5 + 2, a2) \ | ||
46 | M ((i) * 5 + 3, a3) \ | ||
47 | M ((i) * 5 + 4, a4) \ | ||
48 | |||
49 | #define LS_25(M) \ | ||
50 | LS_5 (M, 0, a50, a51, a52, a53, a54) \ | ||
51 | LS_5 (M, 1, a60, a61, a62, a63, a64) \ | ||
52 | LS_5 (M, 2, a70, a71, a72, a73, a74) \ | ||
53 | LS_5 (M, 3, a80, a81, a82, a83, a84) \ | ||
54 | LS_5 (M, 4, a90, a91, a92, a93, a94) \ | ||
55 | |||
56 | |||
57 | #define XOR_1(i, a0) \ | ||
58 | a0 ^= GetUi64(data + (i) * 8); \ | ||
59 | |||
60 | #define XOR_4(i, a0,a1,a2,a3) \ | ||
61 | XOR_1 ((i) , a0); \ | ||
62 | XOR_1 ((i) + 1, a1); \ | ||
63 | XOR_1 ((i) + 2, a2); \ | ||
64 | XOR_1 ((i) + 3, a3); \ | ||
65 | |||
66 | #define D(d,b1,b2) \ | ||
67 | d = b1 ^ Z7_ROTL64(b2, 1); | ||
68 | |||
69 | #define D5 \ | ||
70 | D (d0, c4, c1) \ | ||
71 | D (d1, c0, c2) \ | ||
72 | D (d2, c1, c3) \ | ||
73 | D (d3, c2, c4) \ | ||
74 | D (d4, c3, c0) \ | ||
75 | |||
76 | #define C0(c,a,d) \ | ||
77 | c = a ^ d; \ | ||
78 | |||
79 | #define C(c,a,d,k) \ | ||
80 | c = a ^ d; \ | ||
81 | c = Z7_ROTL64(c, k); \ | ||
82 | |||
83 | #define E4(e1,e2,e3,e4) \ | ||
84 | e1 = c1 ^ (~c2 & c3); \ | ||
85 | e2 = c2 ^ (~c3 & c4); \ | ||
86 | e3 = c3 ^ (~c4 & c0); \ | ||
87 | e4 = c4 ^ (~c0 & c1); \ | ||
88 | |||
89 | #define CK( v0,w0, \ | ||
90 | v1,w1,k1, \ | ||
91 | v2,w2,k2, \ | ||
92 | v3,w3,k3, \ | ||
93 | v4,w4,k4, e0,e1,e2,e3,e4, keccak_c) \ | ||
94 | C0(c0,v0,w0) \ | ||
95 | C (c1,v1,w1,k1) \ | ||
96 | C (c2,v2,w2,k2) \ | ||
97 | C (c3,v3,w3,k3) \ | ||
98 | C (c4,v4,w4,k4) \ | ||
99 | e0 = c0 ^ (~c1 & c2) ^ keccak_c; \ | ||
100 | E4(e1,e2,e3,e4) \ | ||
101 | |||
102 | #define CE( v0,w0,k0, \ | ||
103 | v1,w1,k1, \ | ||
104 | v2,w2,k2, \ | ||
105 | v3,w3,k3, \ | ||
106 | v4,w4,k4, e0,e1,e2,e3,e4) \ | ||
107 | C (c0,v0,w0,k0) \ | ||
108 | C (c1,v1,w1,k1) \ | ||
109 | C (c2,v2,w2,k2) \ | ||
110 | C (c3,v3,w3,k3) \ | ||
111 | C (c4,v4,w4,k4) \ | ||
112 | e0 = c0 ^ (~c1 & c2); \ | ||
113 | E4(e1,e2,e3,e4) \ | ||
114 | |||
115 | // numBlocks != 0 | ||
116 | static | ||
117 | Z7_NO_INLINE | ||
118 | void Z7_FASTCALL Sha3_UpdateBlocks(UInt64 state[SHA3_NUM_STATE_WORDS], | ||
119 | const Byte *data, size_t numBlocks, size_t blockSize) | ||
120 | { | ||
121 | LS_25 (GET_state) | ||
122 | |||
123 | do | ||
124 | { | ||
125 | unsigned round; | ||
126 | XOR_4 ( 0, a50, a51, a52, a53) | ||
127 | XOR_4 ( 4, a54, a60, a61, a62) | ||
128 | XOR_1 ( 8, a63) | ||
129 | if (blockSize > 8 * 9) { XOR_4 ( 9, a64, a70, a71, a72) // sha3-384 | ||
130 | if (blockSize > 8 * 13) { XOR_4 (13, a73, a74, a80, a81) // sha3-256 | ||
131 | if (blockSize > 8 * 17) { XOR_1 (17, a82) // sha3-224 | ||
132 | if (blockSize > 8 * 18) { XOR_1 (18, a83) // shake128 | ||
133 | XOR_1 (19, a84) | ||
134 | XOR_1 (20, a90) }}}} | ||
135 | data += blockSize; | ||
136 | |||
137 | for (round = 0; round < 24; round += 2) | ||
138 | { | ||
139 | UInt64 c0, c1, c2, c3, c4; | ||
140 | UInt64 d0, d1, d2, d3, d4; | ||
141 | UInt64 e50, e51, e52, e53, e54; | ||
142 | UInt64 e60, e61, e62, e63, e64; | ||
143 | UInt64 e70, e71, e72, e73, e74; | ||
144 | UInt64 e80, e81, e82, e83, e84; | ||
145 | UInt64 e90, e91, e92, e93, e94; | ||
146 | |||
147 | c0 = a50^a60^a70^a80^a90; | ||
148 | c1 = a51^a61^a71^a81^a91; | ||
149 | c2 = a52^a62^a72^a82^a92; | ||
150 | c3 = a53^a63^a73^a83^a93; | ||
151 | c4 = a54^a64^a74^a84^a94; | ||
152 | D5 | ||
153 | CK( a50, d0, | ||
154 | a61, d1, 44, | ||
155 | a72, d2, 43, | ||
156 | a83, d3, 21, | ||
157 | a94, d4, 14, e50, e51, e52, e53, e54, SHA3_K_ARRAY[round]) | ||
158 | CE( a53, d3, 28, | ||
159 | a64, d4, 20, | ||
160 | a70, d0, 3, | ||
161 | a81, d1, 45, | ||
162 | a92, d2, 61, e60, e61, e62, e63, e64) | ||
163 | CE( a51, d1, 1, | ||
164 | a62, d2, 6, | ||
165 | a73, d3, 25, | ||
166 | a84, d4, 8, | ||
167 | a90, d0, 18, e70, e71, e72, e73, e74) | ||
168 | CE( a54, d4, 27, | ||
169 | a60, d0, 36, | ||
170 | a71, d1, 10, | ||
171 | a82, d2, 15, | ||
172 | a93, d3, 56, e80, e81, e82, e83, e84) | ||
173 | CE( a52, d2, 62, | ||
174 | a63, d3, 55, | ||
175 | a74, d4, 39, | ||
176 | a80, d0, 41, | ||
177 | a91, d1, 2, e90, e91, e92, e93, e94) | ||
178 | |||
179 | // ---------- ROUND + 1 ---------- | ||
180 | |||
181 | c0 = e50^e60^e70^e80^e90; | ||
182 | c1 = e51^e61^e71^e81^e91; | ||
183 | c2 = e52^e62^e72^e82^e92; | ||
184 | c3 = e53^e63^e73^e83^e93; | ||
185 | c4 = e54^e64^e74^e84^e94; | ||
186 | D5 | ||
187 | CK( e50, d0, | ||
188 | e61, d1, 44, | ||
189 | e72, d2, 43, | ||
190 | e83, d3, 21, | ||
191 | e94, d4, 14, a50, a51, a52, a53, a54, SHA3_K_ARRAY[(size_t)round + 1]) | ||
192 | CE( e53, d3, 28, | ||
193 | e64, d4, 20, | ||
194 | e70, d0, 3, | ||
195 | e81, d1, 45, | ||
196 | e92, d2, 61, a60, a61, a62, a63, a64) | ||
197 | CE( e51, d1, 1, | ||
198 | e62, d2, 6, | ||
199 | e73, d3, 25, | ||
200 | e84, d4, 8, | ||
201 | e90, d0, 18, a70, a71, a72, a73, a74) | ||
202 | CE (e54, d4, 27, | ||
203 | e60, d0, 36, | ||
204 | e71, d1, 10, | ||
205 | e82, d2, 15, | ||
206 | e93, d3, 56, a80, a81, a82, a83, a84) | ||
207 | CE (e52, d2, 62, | ||
208 | e63, d3, 55, | ||
209 | e74, d4, 39, | ||
210 | e80, d0, 41, | ||
211 | e91, d1, 2, a90, a91, a92, a93, a94) | ||
212 | } | ||
213 | } | ||
214 | while (--numBlocks); | ||
215 | |||
216 | LS_25 (SET_state) | ||
217 | } | ||
218 | |||
219 | |||
220 | #define Sha3_UpdateBlock(p) \ | ||
221 | Sha3_UpdateBlocks(p->state, p->buffer, 1, p->blockSize) | ||
222 | |||
223 | void Sha3_Update(CSha3 *p, const Byte *data, size_t size) | ||
224 | { | ||
225 | /* | ||
226 | for (;;) | ||
227 | { | ||
228 | if (size == 0) | ||
229 | return; | ||
230 | unsigned cur = p->blockSize - p->count; | ||
231 | if (cur > size) | ||
232 | cur = (unsigned)size; | ||
233 | size -= cur; | ||
234 | unsigned pos = p->count; | ||
235 | p->count = pos + cur; | ||
236 | while (pos & 7) | ||
237 | { | ||
238 | if (cur == 0) | ||
239 | return; | ||
240 | Byte *pb = &(((Byte *)p->state)[pos]); | ||
241 | *pb = (Byte)(*pb ^ *data++); | ||
242 | cur--; | ||
243 | pos++; | ||
244 | } | ||
245 | if (cur >= 8) | ||
246 | { | ||
247 | do | ||
248 | { | ||
249 | *(UInt64 *)(void *)&(((Byte *)p->state)[pos]) ^= GetUi64(data); | ||
250 | data += 8; | ||
251 | pos += 8; | ||
252 | cur -= 8; | ||
253 | } | ||
254 | while (cur >= 8); | ||
255 | } | ||
256 | if (pos != p->blockSize) | ||
257 | { | ||
258 | if (cur) | ||
259 | { | ||
260 | Byte *pb = &(((Byte *)p->state)[pos]); | ||
261 | do | ||
262 | { | ||
263 | *pb = (Byte)(*pb ^ *data++); | ||
264 | pb++; | ||
265 | } | ||
266 | while (--cur); | ||
267 | } | ||
268 | return; | ||
269 | } | ||
270 | Sha3_UpdateBlock(p->state); | ||
271 | p->count = 0; | ||
272 | } | ||
273 | */ | ||
274 | if (size == 0) | ||
275 | return; | ||
276 | { | ||
277 | const unsigned pos = p->count; | ||
278 | const unsigned num = p->blockSize - pos; | ||
279 | if (num > size) | ||
280 | { | ||
281 | p->count = pos + (unsigned)size; | ||
282 | memcpy(p->buffer + pos, data, size); | ||
283 | return; | ||
284 | } | ||
285 | if (pos != 0) | ||
286 | { | ||
287 | size -= num; | ||
288 | memcpy(p->buffer + pos, data, num); | ||
289 | data += num; | ||
290 | Sha3_UpdateBlock(p); | ||
291 | } | ||
292 | } | ||
293 | if (size >= p->blockSize) | ||
294 | { | ||
295 | const size_t numBlocks = size / p->blockSize; | ||
296 | const Byte *dataOld = data; | ||
297 | data += numBlocks * p->blockSize; | ||
298 | size = (size_t)(dataOld + size - data); | ||
299 | Sha3_UpdateBlocks(p->state, dataOld, numBlocks, p->blockSize); | ||
300 | } | ||
301 | p->count = (unsigned)size; | ||
302 | if (size) | ||
303 | memcpy(p->buffer, data, size); | ||
304 | } | ||
305 | |||
306 | |||
307 | // we support only (digestSize % 4 == 0) cases | ||
308 | void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake) | ||
309 | { | ||
310 | memset(p->buffer + p->count, 0, p->blockSize - p->count); | ||
311 | // we write bits markers from low to higher in current byte: | ||
312 | // - if sha-3 : 2 bits : 0,1 | ||
313 | // - if shake : 4 bits : 1111 | ||
314 | // then we write bit 1 to same byte. | ||
315 | // And we write bit 1 to highest bit of last byte of block. | ||
316 | p->buffer[p->count] = (Byte)(shake ? 0x1f : 0x06); | ||
317 | // we need xor operation (^= 0x80) here because we must write 0x80 bit | ||
318 | // to same byte as (0x1f : 0x06), if (p->count == p->blockSize - 1) !!! | ||
319 | p->buffer[p->blockSize - 1] ^= 0x80; | ||
320 | /* | ||
321 | ((Byte *)p->state)[p->count] ^= (Byte)(shake ? 0x1f : 0x06); | ||
322 | ((Byte *)p->state)[p->blockSize - 1] ^= 0x80; | ||
323 | */ | ||
324 | Sha3_UpdateBlock(p); | ||
325 | #if 1 && defined(MY_CPU_LE) | ||
326 | memcpy(digest, p->state, digestSize); | ||
327 | #else | ||
328 | { | ||
329 | const unsigned numWords = digestSize >> 3; | ||
330 | unsigned i; | ||
331 | for (i = 0; i < numWords; i++) | ||
332 | { | ||
333 | const UInt64 v = p->state[i]; | ||
334 | SetUi64(digest, v) | ||
335 | digest += 8; | ||
336 | } | ||
337 | if (digestSize & 4) // for SHA3-224 | ||
338 | { | ||
339 | const UInt32 v = (UInt32)p->state[numWords]; | ||
340 | SetUi32(digest, v) | ||
341 | } | ||
342 | } | ||
343 | #endif | ||
344 | Sha3_Init(p); | ||
345 | } | ||
346 | |||
347 | #undef GET_state | ||
348 | #undef SET_state | ||
349 | #undef LS_5 | ||
350 | #undef LS_25 | ||
351 | #undef XOR_1 | ||
352 | #undef XOR_4 | ||
353 | #undef D | ||
354 | #undef D5 | ||
355 | #undef C0 | ||
356 | #undef C | ||
357 | #undef E4 | ||
358 | #undef CK | ||
359 | #undef CE | ||
diff --git a/C/Sha3.h b/C/Sha3.h new file mode 100644 index 0000000..c5909c9 --- /dev/null +++ b/C/Sha3.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* Sha3.h -- SHA-3 Hash | ||
2 | : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #ifndef ZIP7_INC_MD5_H | ||
5 | #define ZIP7_INC_MD5_H | ||
6 | |||
7 | #include "7zTypes.h" | ||
8 | |||
9 | EXTERN_C_BEGIN | ||
10 | |||
11 | #define SHA3_NUM_STATE_WORDS 25 | ||
12 | |||
13 | #define SHA3_BLOCK_SIZE_FROM_DIGEST_SIZE(digestSize) \ | ||
14 | (SHA3_NUM_STATE_WORDS * 8 - (digestSize) * 2) | ||
15 | |||
16 | typedef struct | ||
17 | { | ||
18 | UInt32 count; // < blockSize | ||
19 | UInt32 blockSize; // <= SHA3_NUM_STATE_WORDS * 8 | ||
20 | UInt64 _pad1[3]; | ||
21 | // we want 32-bytes alignment here | ||
22 | UInt64 state[SHA3_NUM_STATE_WORDS]; | ||
23 | UInt64 _pad2[3]; | ||
24 | // we want 64-bytes alignment here | ||
25 | Byte buffer[SHA3_NUM_STATE_WORDS * 8]; // last bytes will be unused with predefined blockSize values | ||
26 | } CSha3; | ||
27 | |||
28 | #define Sha3_SET_blockSize(p, blockSize) { (p)->blockSize = (blockSize); } | ||
29 | |||
30 | void Sha3_Init(CSha3 *p); | ||
31 | void Sha3_Update(CSha3 *p, const Byte *data, size_t size); | ||
32 | void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake); | ||
33 | |||
34 | EXTERN_C_END | ||
35 | |||
36 | #endif | ||
diff --git a/C/Sha512.c b/C/Sha512.c new file mode 100644 index 0000000..f0787fd --- /dev/null +++ b/C/Sha512.c | |||
@@ -0,0 +1,711 @@ | |||
1 | /* Sha512.c -- SHA-512 Hash | ||
2 | : Igor Pavlov : Public domain | ||
3 | This code is based on public domain code from Wei Dai's Crypto++ library. */ | ||
4 | |||
5 | #include "Precomp.h" | ||
6 | |||
7 | #include <string.h> | ||
8 | |||
9 | #include "Sha512.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "CpuArch.h" | ||
12 | |||
13 | #ifdef MY_CPU_X86_OR_AMD64 | ||
14 | #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 170001) \ | ||
15 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 170001) \ | ||
16 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 140000) \ | ||
17 | || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 2400) && (__INTEL_COMPILER <= 9900) \ | ||
18 | || defined(_MSC_VER) && (_MSC_VER >= 1940) | ||
19 | #define Z7_COMPILER_SHA512_SUPPORTED | ||
20 | #endif | ||
21 | #elif defined(MY_CPU_ARM64) && defined(MY_CPU_LE) | ||
22 | #if defined(__ARM_FEATURE_SHA512) | ||
23 | #define Z7_COMPILER_SHA512_SUPPORTED | ||
24 | #else | ||
25 | #if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 130000) \ | ||
26 | || defined(__GNUC__) && (__GNUC__ >= 9) \ | ||
27 | ) \ | ||
28 | || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1940) // fix it | ||
29 | #define Z7_COMPILER_SHA512_SUPPORTED | ||
30 | #endif | ||
31 | #endif | ||
32 | #endif | ||
33 | |||
34 | |||
35 | |||
36 | |||
37 | |||
38 | |||
39 | |||
40 | |||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | |||
47 | void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
48 | |||
49 | #ifdef Z7_COMPILER_SHA512_SUPPORTED | ||
50 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
51 | |||
52 | static SHA512_FUNC_UPDATE_BLOCKS g_SHA512_FUNC_UPDATE_BLOCKS = Sha512_UpdateBlocks; | ||
53 | static SHA512_FUNC_UPDATE_BLOCKS g_SHA512_FUNC_UPDATE_BLOCKS_HW; | ||
54 | |||
55 | #define SHA512_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks | ||
56 | #else | ||
57 | #define SHA512_UPDATE_BLOCKS(p) Sha512_UpdateBlocks | ||
58 | #endif | ||
59 | |||
60 | |||
61 | BoolInt Sha512_SetFunction(CSha512 *p, unsigned algo) | ||
62 | { | ||
63 | SHA512_FUNC_UPDATE_BLOCKS func = Sha512_UpdateBlocks; | ||
64 | |||
65 | #ifdef Z7_COMPILER_SHA512_SUPPORTED | ||
66 | if (algo != SHA512_ALGO_SW) | ||
67 | { | ||
68 | if (algo == SHA512_ALGO_DEFAULT) | ||
69 | func = g_SHA512_FUNC_UPDATE_BLOCKS; | ||
70 | else | ||
71 | { | ||
72 | if (algo != SHA512_ALGO_HW) | ||
73 | return False; | ||
74 | func = g_SHA512_FUNC_UPDATE_BLOCKS_HW; | ||
75 | if (!func) | ||
76 | return False; | ||
77 | } | ||
78 | } | ||
79 | #else | ||
80 | if (algo > 1) | ||
81 | return False; | ||
82 | #endif | ||
83 | |||
84 | p->v.vars.func_UpdateBlocks = func; | ||
85 | return True; | ||
86 | } | ||
87 | |||
88 | |||
89 | /* define it for speed optimization */ | ||
90 | |||
91 | #if 0 // 1 for size optimization | ||
92 | #define STEP_PRE 1 | ||
93 | #define STEP_MAIN 1 | ||
94 | #else | ||
95 | #define STEP_PRE 2 | ||
96 | #define STEP_MAIN 4 | ||
97 | // #define Z7_SHA512_UNROLL | ||
98 | #endif | ||
99 | |||
100 | #undef Z7_SHA512_BIG_W | ||
101 | #if STEP_MAIN != 16 | ||
102 | #define Z7_SHA512_BIG_W | ||
103 | #endif | ||
104 | |||
105 | |||
106 | #define U64C(x) UINT64_CONST(x) | ||
107 | |||
108 | static MY_ALIGN(64) const UInt64 SHA512_INIT_ARRAYS[4][8] = { | ||
109 | { U64C(0x8c3d37c819544da2), U64C(0x73e1996689dcd4d6), U64C(0x1dfab7ae32ff9c82), U64C(0x679dd514582f9fcf), | ||
110 | U64C(0x0f6d2b697bd44da8), U64C(0x77e36f7304c48942), U64C(0x3f9d85a86a1d36c8), U64C(0x1112e6ad91d692a1) | ||
111 | }, | ||
112 | { U64C(0x22312194fc2bf72c), U64C(0x9f555fa3c84c64c2), U64C(0x2393b86b6f53b151), U64C(0x963877195940eabd), | ||
113 | U64C(0x96283ee2a88effe3), U64C(0xbe5e1e2553863992), U64C(0x2b0199fc2c85b8aa), U64C(0x0eb72ddc81c52ca2) | ||
114 | }, | ||
115 | { U64C(0xcbbb9d5dc1059ed8), U64C(0x629a292a367cd507), U64C(0x9159015a3070dd17), U64C(0x152fecd8f70e5939), | ||
116 | U64C(0x67332667ffc00b31), U64C(0x8eb44a8768581511), U64C(0xdb0c2e0d64f98fa7), U64C(0x47b5481dbefa4fa4) | ||
117 | }, | ||
118 | { U64C(0x6a09e667f3bcc908), U64C(0xbb67ae8584caa73b), U64C(0x3c6ef372fe94f82b), U64C(0xa54ff53a5f1d36f1), | ||
119 | U64C(0x510e527fade682d1), U64C(0x9b05688c2b3e6c1f), U64C(0x1f83d9abfb41bd6b), U64C(0x5be0cd19137e2179) | ||
120 | }}; | ||
121 | |||
122 | void Sha512_InitState(CSha512 *p, unsigned digestSize) | ||
123 | { | ||
124 | p->v.vars.count = 0; | ||
125 | memcpy(p->state, SHA512_INIT_ARRAYS[(size_t)(digestSize >> 4) - 1], sizeof(p->state)); | ||
126 | } | ||
127 | |||
128 | void Sha512_Init(CSha512 *p, unsigned digestSize) | ||
129 | { | ||
130 | p->v.vars.func_UpdateBlocks = | ||
131 | #ifdef Z7_COMPILER_SHA512_SUPPORTED | ||
132 | g_SHA512_FUNC_UPDATE_BLOCKS; | ||
133 | #else | ||
134 | NULL; | ||
135 | #endif | ||
136 | Sha512_InitState(p, digestSize); | ||
137 | } | ||
138 | |||
139 | #define S0(x) (Z7_ROTR64(x,28) ^ Z7_ROTR64(x,34) ^ Z7_ROTR64(x,39)) | ||
140 | #define S1(x) (Z7_ROTR64(x,14) ^ Z7_ROTR64(x,18) ^ Z7_ROTR64(x,41)) | ||
141 | #define s0(x) (Z7_ROTR64(x, 1) ^ Z7_ROTR64(x, 8) ^ (x >> 7)) | ||
142 | #define s1(x) (Z7_ROTR64(x,19) ^ Z7_ROTR64(x,61) ^ (x >> 6)) | ||
143 | |||
144 | #define Ch(x,y,z) (z^(x&(y^z))) | ||
145 | #define Maj(x,y,z) ((x&y)|(z&(x|y))) | ||
146 | |||
147 | |||
148 | #define W_PRE(i) (W[(i) + (size_t)(j)] = GetBe64(data + ((size_t)(j) + i) * 8)) | ||
149 | |||
150 | #define blk2_main(j, i) s1(w(j, (i)-2)) + w(j, (i)-7) + s0(w(j, (i)-15)) | ||
151 | |||
152 | #ifdef Z7_SHA512_BIG_W | ||
153 | // we use +i instead of +(i) to change the order to solve CLANG compiler warning for signed/unsigned. | ||
154 | #define w(j, i) W[(size_t)(j) + i] | ||
155 | #define blk2(j, i) (w(j, i) = w(j, (i)-16) + blk2_main(j, i)) | ||
156 | #else | ||
157 | #if STEP_MAIN == 16 | ||
158 | #define w(j, i) W[(i) & 15] | ||
159 | #else | ||
160 | #define w(j, i) W[((size_t)(j) + (i)) & 15] | ||
161 | #endif | ||
162 | #define blk2(j, i) (w(j, i) += blk2_main(j, i)) | ||
163 | #endif | ||
164 | |||
165 | #define W_MAIN(i) blk2(j, i) | ||
166 | |||
167 | |||
168 | #define T1(wx, i) \ | ||
169 | tmp = h + S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ | ||
170 | h = g; \ | ||
171 | g = f; \ | ||
172 | f = e; \ | ||
173 | e = d + tmp; \ | ||
174 | tmp += S0(a) + Maj(a, b, c); \ | ||
175 | d = c; \ | ||
176 | c = b; \ | ||
177 | b = a; \ | ||
178 | a = tmp; \ | ||
179 | |||
180 | #define R1_PRE(i) T1( W_PRE, i) | ||
181 | #define R1_MAIN(i) T1( W_MAIN, i) | ||
182 | |||
183 | #if (!defined(Z7_SHA512_UNROLL) || STEP_MAIN < 8) && (STEP_MAIN >= 4) | ||
184 | #define R2_MAIN(i) \ | ||
185 | R1_MAIN(i) \ | ||
186 | R1_MAIN(i + 1) \ | ||
187 | |||
188 | #endif | ||
189 | |||
190 | |||
191 | |||
192 | #if defined(Z7_SHA512_UNROLL) && STEP_MAIN >= 8 | ||
193 | |||
194 | #define T4( a,b,c,d,e,f,g,h, wx, i) \ | ||
195 | h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ | ||
196 | tmp = h; \ | ||
197 | h += d; \ | ||
198 | d = tmp + S0(a) + Maj(a, b, c); \ | ||
199 | |||
200 | #define R4( wx, i) \ | ||
201 | T4 ( a,b,c,d,e,f,g,h, wx, (i )); \ | ||
202 | T4 ( d,a,b,c,h,e,f,g, wx, (i+1)); \ | ||
203 | T4 ( c,d,a,b,g,h,e,f, wx, (i+2)); \ | ||
204 | T4 ( b,c,d,a,f,g,h,e, wx, (i+3)); \ | ||
205 | |||
206 | #define R4_PRE(i) R4( W_PRE, i) | ||
207 | #define R4_MAIN(i) R4( W_MAIN, i) | ||
208 | |||
209 | |||
210 | #define T8( a,b,c,d,e,f,g,h, wx, i) \ | ||
211 | h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ | ||
212 | d += h; \ | ||
213 | h += S0(a) + Maj(a, b, c); \ | ||
214 | |||
215 | #define R8( wx, i) \ | ||
216 | T8 ( a,b,c,d,e,f,g,h, wx, i ); \ | ||
217 | T8 ( h,a,b,c,d,e,f,g, wx, i+1); \ | ||
218 | T8 ( g,h,a,b,c,d,e,f, wx, i+2); \ | ||
219 | T8 ( f,g,h,a,b,c,d,e, wx, i+3); \ | ||
220 | T8 ( e,f,g,h,a,b,c,d, wx, i+4); \ | ||
221 | T8 ( d,e,f,g,h,a,b,c, wx, i+5); \ | ||
222 | T8 ( c,d,e,f,g,h,a,b, wx, i+6); \ | ||
223 | T8 ( b,c,d,e,f,g,h,a, wx, i+7); \ | ||
224 | |||
225 | #define R8_PRE(i) R8( W_PRE, i) | ||
226 | #define R8_MAIN(i) R8( W_MAIN, i) | ||
227 | |||
228 | #endif | ||
229 | |||
230 | |||
231 | extern | ||
232 | MY_ALIGN(64) const UInt64 SHA512_K_ARRAY[80]; | ||
233 | MY_ALIGN(64) const UInt64 SHA512_K_ARRAY[80] = { | ||
234 | U64C(0x428a2f98d728ae22), U64C(0x7137449123ef65cd), U64C(0xb5c0fbcfec4d3b2f), U64C(0xe9b5dba58189dbbc), | ||
235 | U64C(0x3956c25bf348b538), U64C(0x59f111f1b605d019), U64C(0x923f82a4af194f9b), U64C(0xab1c5ed5da6d8118), | ||
236 | U64C(0xd807aa98a3030242), U64C(0x12835b0145706fbe), U64C(0x243185be4ee4b28c), U64C(0x550c7dc3d5ffb4e2), | ||
237 | U64C(0x72be5d74f27b896f), U64C(0x80deb1fe3b1696b1), U64C(0x9bdc06a725c71235), U64C(0xc19bf174cf692694), | ||
238 | U64C(0xe49b69c19ef14ad2), U64C(0xefbe4786384f25e3), U64C(0x0fc19dc68b8cd5b5), U64C(0x240ca1cc77ac9c65), | ||
239 | U64C(0x2de92c6f592b0275), U64C(0x4a7484aa6ea6e483), U64C(0x5cb0a9dcbd41fbd4), U64C(0x76f988da831153b5), | ||
240 | U64C(0x983e5152ee66dfab), U64C(0xa831c66d2db43210), U64C(0xb00327c898fb213f), U64C(0xbf597fc7beef0ee4), | ||
241 | U64C(0xc6e00bf33da88fc2), U64C(0xd5a79147930aa725), U64C(0x06ca6351e003826f), U64C(0x142929670a0e6e70), | ||
242 | U64C(0x27b70a8546d22ffc), U64C(0x2e1b21385c26c926), U64C(0x4d2c6dfc5ac42aed), U64C(0x53380d139d95b3df), | ||
243 | U64C(0x650a73548baf63de), U64C(0x766a0abb3c77b2a8), U64C(0x81c2c92e47edaee6), U64C(0x92722c851482353b), | ||
244 | U64C(0xa2bfe8a14cf10364), U64C(0xa81a664bbc423001), U64C(0xc24b8b70d0f89791), U64C(0xc76c51a30654be30), | ||
245 | U64C(0xd192e819d6ef5218), U64C(0xd69906245565a910), U64C(0xf40e35855771202a), U64C(0x106aa07032bbd1b8), | ||
246 | U64C(0x19a4c116b8d2d0c8), U64C(0x1e376c085141ab53), U64C(0x2748774cdf8eeb99), U64C(0x34b0bcb5e19b48a8), | ||
247 | U64C(0x391c0cb3c5c95a63), U64C(0x4ed8aa4ae3418acb), U64C(0x5b9cca4f7763e373), U64C(0x682e6ff3d6b2b8a3), | ||
248 | U64C(0x748f82ee5defb2fc), U64C(0x78a5636f43172f60), U64C(0x84c87814a1f0ab72), U64C(0x8cc702081a6439ec), | ||
249 | U64C(0x90befffa23631e28), U64C(0xa4506cebde82bde9), U64C(0xbef9a3f7b2c67915), U64C(0xc67178f2e372532b), | ||
250 | U64C(0xca273eceea26619c), U64C(0xd186b8c721c0c207), U64C(0xeada7dd6cde0eb1e), U64C(0xf57d4f7fee6ed178), | ||
251 | U64C(0x06f067aa72176fba), U64C(0x0a637dc5a2c898a6), U64C(0x113f9804bef90dae), U64C(0x1b710b35131c471b), | ||
252 | U64C(0x28db77f523047d84), U64C(0x32caab7b40c72493), U64C(0x3c9ebe0a15c9bebc), U64C(0x431d67c49c100d4c), | ||
253 | U64C(0x4cc5d4becb3e42b6), U64C(0x597f299cfc657e2a), U64C(0x5fcb6fab3ad6faec), U64C(0x6c44198c4a475817) | ||
254 | }; | ||
255 | |||
256 | #define K SHA512_K_ARRAY | ||
257 | |||
258 | Z7_NO_INLINE | ||
259 | void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks) | ||
260 | { | ||
261 | UInt64 W | ||
262 | #ifdef Z7_SHA512_BIG_W | ||
263 | [80]; | ||
264 | #else | ||
265 | [16]; | ||
266 | #endif | ||
267 | unsigned j; | ||
268 | UInt64 a,b,c,d,e,f,g,h; | ||
269 | #if !defined(Z7_SHA512_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) | ||
270 | UInt64 tmp; | ||
271 | #endif | ||
272 | |||
273 | if (numBlocks == 0) return; | ||
274 | |||
275 | a = state[0]; | ||
276 | b = state[1]; | ||
277 | c = state[2]; | ||
278 | d = state[3]; | ||
279 | e = state[4]; | ||
280 | f = state[5]; | ||
281 | g = state[6]; | ||
282 | h = state[7]; | ||
283 | |||
284 | do | ||
285 | { | ||
286 | |||
287 | for (j = 0; j < 16; j += STEP_PRE) | ||
288 | { | ||
289 | #if STEP_PRE > 4 | ||
290 | |||
291 | #if STEP_PRE < 8 | ||
292 | R4_PRE(0); | ||
293 | #else | ||
294 | R8_PRE(0); | ||
295 | #if STEP_PRE == 16 | ||
296 | R8_PRE(8); | ||
297 | #endif | ||
298 | #endif | ||
299 | |||
300 | #else | ||
301 | |||
302 | R1_PRE(0) | ||
303 | #if STEP_PRE >= 2 | ||
304 | R1_PRE(1) | ||
305 | #if STEP_PRE >= 4 | ||
306 | R1_PRE(2) | ||
307 | R1_PRE(3) | ||
308 | #endif | ||
309 | #endif | ||
310 | |||
311 | #endif | ||
312 | } | ||
313 | |||
314 | for (j = 16; j < 80; j += STEP_MAIN) | ||
315 | { | ||
316 | #if defined(Z7_SHA512_UNROLL) && STEP_MAIN >= 8 | ||
317 | |||
318 | #if STEP_MAIN < 8 | ||
319 | R4_MAIN(0) | ||
320 | #else | ||
321 | R8_MAIN(0) | ||
322 | #if STEP_MAIN == 16 | ||
323 | R8_MAIN(8) | ||
324 | #endif | ||
325 | #endif | ||
326 | |||
327 | #else | ||
328 | |||
329 | R1_MAIN(0) | ||
330 | #if STEP_MAIN >= 2 | ||
331 | R1_MAIN(1) | ||
332 | #if STEP_MAIN >= 4 | ||
333 | R2_MAIN(2) | ||
334 | #if STEP_MAIN >= 8 | ||
335 | R2_MAIN(4) | ||
336 | R2_MAIN(6) | ||
337 | #if STEP_MAIN >= 16 | ||
338 | R2_MAIN(8) | ||
339 | R2_MAIN(10) | ||
340 | R2_MAIN(12) | ||
341 | R2_MAIN(14) | ||
342 | #endif | ||
343 | #endif | ||
344 | #endif | ||
345 | #endif | ||
346 | #endif | ||
347 | } | ||
348 | |||
349 | a += state[0]; state[0] = a; | ||
350 | b += state[1]; state[1] = b; | ||
351 | c += state[2]; state[2] = c; | ||
352 | d += state[3]; state[3] = d; | ||
353 | e += state[4]; state[4] = e; | ||
354 | f += state[5]; state[5] = f; | ||
355 | g += state[6]; state[6] = g; | ||
356 | h += state[7]; state[7] = h; | ||
357 | |||
358 | data += SHA512_BLOCK_SIZE; | ||
359 | } | ||
360 | while (--numBlocks); | ||
361 | } | ||
362 | |||
363 | |||
364 | #define Sha512_UpdateBlock(p) SHA512_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) | ||
365 | |||
366 | void Sha512_Update(CSha512 *p, const Byte *data, size_t size) | ||
367 | { | ||
368 | if (size == 0) | ||
369 | return; | ||
370 | { | ||
371 | const unsigned pos = (unsigned)p->v.vars.count & (SHA512_BLOCK_SIZE - 1); | ||
372 | const unsigned num = SHA512_BLOCK_SIZE - pos; | ||
373 | p->v.vars.count += size; | ||
374 | if (num > size) | ||
375 | { | ||
376 | memcpy(p->buffer + pos, data, size); | ||
377 | return; | ||
378 | } | ||
379 | if (pos != 0) | ||
380 | { | ||
381 | size -= num; | ||
382 | memcpy(p->buffer + pos, data, num); | ||
383 | data += num; | ||
384 | Sha512_UpdateBlock(p); | ||
385 | } | ||
386 | } | ||
387 | { | ||
388 | const size_t numBlocks = size >> 7; | ||
389 | // if (numBlocks) | ||
390 | SHA512_UPDATE_BLOCKS(p)(p->state, data, numBlocks); | ||
391 | size &= SHA512_BLOCK_SIZE - 1; | ||
392 | if (size == 0) | ||
393 | return; | ||
394 | data += (numBlocks << 7); | ||
395 | memcpy(p->buffer, data, size); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | |||
400 | void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize) | ||
401 | { | ||
402 | unsigned pos = (unsigned)p->v.vars.count & (SHA512_BLOCK_SIZE - 1); | ||
403 | p->buffer[pos++] = 0x80; | ||
404 | if (pos > (SHA512_BLOCK_SIZE - 8 * 2)) | ||
405 | { | ||
406 | while (pos != SHA512_BLOCK_SIZE) { p->buffer[pos++] = 0; } | ||
407 | // memset(&p->buf.buffer[pos], 0, SHA512_BLOCK_SIZE - pos); | ||
408 | Sha512_UpdateBlock(p); | ||
409 | pos = 0; | ||
410 | } | ||
411 | memset(&p->buffer[pos], 0, (SHA512_BLOCK_SIZE - 8 * 2) - pos); | ||
412 | { | ||
413 | const UInt64 numBits = p->v.vars.count << 3; | ||
414 | SetBe64(p->buffer + SHA512_BLOCK_SIZE - 8 * 2, 0) // = (p->v.vars.count >> (64 - 3)); (high 64-bits) | ||
415 | SetBe64(p->buffer + SHA512_BLOCK_SIZE - 8 * 1, numBits) | ||
416 | } | ||
417 | Sha512_UpdateBlock(p); | ||
418 | #if 1 && defined(MY_CPU_BE) | ||
419 | memcpy(digest, p->state, digestSize); | ||
420 | #else | ||
421 | { | ||
422 | const unsigned numWords = digestSize >> 3; | ||
423 | unsigned i; | ||
424 | for (i = 0; i < numWords; i++) | ||
425 | { | ||
426 | const UInt64 v = p->state[i]; | ||
427 | SetBe64(digest, v) | ||
428 | digest += 8; | ||
429 | } | ||
430 | if (digestSize & 4) // digestSize == SHA512_224_DIGEST_SIZE | ||
431 | { | ||
432 | const UInt32 v = (UInt32)((p->state[numWords]) >> 32); | ||
433 | SetBe32(digest, v) | ||
434 | } | ||
435 | } | ||
436 | #endif | ||
437 | Sha512_InitState(p, digestSize); | ||
438 | } | ||
439 | |||
440 | |||
441 | |||
442 | // #define Z7_SHA512_PROBE_DEBUG // for debug | ||
443 | |||
444 | #if defined(Z7_SHA512_PROBE_DEBUG) || defined(Z7_COMPILER_SHA512_SUPPORTED) | ||
445 | |||
446 | #if defined(Z7_SHA512_PROBE_DEBUG) \ | ||
447 | || defined(_WIN32) && defined(MY_CPU_ARM64) | ||
448 | #ifndef Z7_SHA512_USE_PROBE | ||
449 | #define Z7_SHA512_USE_PROBE | ||
450 | #endif | ||
451 | #endif | ||
452 | |||
453 | #ifdef Z7_SHA512_USE_PROBE | ||
454 | |||
455 | #ifdef Z7_SHA512_PROBE_DEBUG | ||
456 | #include <stdio.h> | ||
457 | #define PRF(x) x | ||
458 | #else | ||
459 | #define PRF(x) | ||
460 | #endif | ||
461 | |||
462 | #if 0 || !defined(_MSC_VER) // 1 || : for debug LONGJMP mode | ||
463 | // MINGW doesn't support __try. So we use signal() / longjmp(). | ||
464 | // Note: signal() / longjmp() probably is not thread-safe. | ||
465 | // So we must call Sha512Prepare() from main thread at program start. | ||
466 | #ifndef Z7_SHA512_USE_LONGJMP | ||
467 | #define Z7_SHA512_USE_LONGJMP | ||
468 | #endif | ||
469 | #endif | ||
470 | |||
471 | #ifdef Z7_SHA512_USE_LONGJMP | ||
472 | #include <signal.h> | ||
473 | #include <setjmp.h> | ||
474 | static jmp_buf g_Sha512_jmp_buf; | ||
475 | // static int g_Sha512_Unsupported; | ||
476 | |||
477 | #if defined(__GNUC__) && (__GNUC__ >= 8) \ | ||
478 | || defined(__clang__) && (__clang_major__ >= 3) | ||
479 | __attribute__((noreturn)) | ||
480 | #endif | ||
481 | static void Z7_CDECL Sha512_signal_Handler(int v) | ||
482 | { | ||
483 | PRF(printf("======== Sha512_signal_Handler = %x\n", (unsigned)v);) | ||
484 | // g_Sha512_Unsupported = 1; | ||
485 | longjmp(g_Sha512_jmp_buf, 1); | ||
486 | } | ||
487 | #endif // Z7_SHA512_USE_LONGJMP | ||
488 | |||
489 | |||
490 | #if defined(_WIN32) | ||
491 | #include "7zWindows.h" | ||
492 | #endif | ||
493 | |||
494 | #if defined(MY_CPU_ARM64) | ||
495 | // #define Z7_SHA512_USE_SIMPLIFIED_PROBE // for debug | ||
496 | #endif | ||
497 | |||
498 | #ifdef Z7_SHA512_USE_SIMPLIFIED_PROBE | ||
499 | #include <arm_neon.h> | ||
500 | #if defined(__clang__) | ||
501 | __attribute__((__target__("sha3"))) | ||
502 | #elif !defined(_MSC_VER) | ||
503 | __attribute__((__target__("arch=armv8.2-a+sha3"))) | ||
504 | #endif | ||
505 | #endif | ||
506 | static BoolInt CPU_IsSupported_SHA512_Probe(void) | ||
507 | { | ||
508 | PRF(printf("\n== CPU_IsSupported_SHA512_Probe\n");) | ||
509 | #if defined(_WIN32) && defined(MY_CPU_ARM64) | ||
510 | // we have no SHA512 flag for IsProcessorFeaturePresent() still. | ||
511 | if (!CPU_IsSupported_CRYPTO()) | ||
512 | return False; | ||
513 | PRF(printf("==== Registry check\n");) | ||
514 | { | ||
515 | // we can't read ID_AA64ISAR0_EL1 register from application. | ||
516 | // but ID_AA64ISAR0_EL1 register is mapped to "CP 4030" registry value. | ||
517 | HKEY key = NULL; | ||
518 | LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, | ||
519 | TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), | ||
520 | 0, KEY_READ, &key); | ||
521 | if (res != ERROR_SUCCESS) | ||
522 | return False; | ||
523 | { | ||
524 | DWORD type = 0; | ||
525 | DWORD count = sizeof(UInt64); | ||
526 | UInt64 val = 0; | ||
527 | res = RegQueryValueEx(key, TEXT("CP 4030"), NULL, | ||
528 | &type, (LPBYTE)&val, &count); | ||
529 | RegCloseKey(key); | ||
530 | if (res != ERROR_SUCCESS | ||
531 | || type != REG_QWORD | ||
532 | || count != sizeof(UInt64) | ||
533 | || ((unsigned)(val >> 12) & 0xf) != 2) | ||
534 | return False; | ||
535 | // we parse SHA2 field of ID_AA64ISAR0_EL1 register: | ||
536 | // 0 : No SHA2 instructions implemented | ||
537 | // 1 : SHA256 implemented | ||
538 | // 2 : SHA256 and SHA512 implemented | ||
539 | } | ||
540 | } | ||
541 | #endif // defined(_WIN32) && defined(MY_CPU_ARM64) | ||
542 | |||
543 | |||
544 | #if 1 // 0 for debug to disable SHA512 PROBE code | ||
545 | |||
546 | /* | ||
547 | ----- SHA512 PROBE ----- | ||
548 | |||
549 | We suppose that "CP 4030" registry reading is enough. | ||
550 | But we use additional SHA512 PROBE code, because | ||
551 | we can catch exception here, and we don't catch exceptions, | ||
552 | if we call Sha512 functions from main code. | ||
553 | |||
554 | NOTE: arm64 PROBE code doesn't work, if we call it via Wine in linux-arm64. | ||
555 | The program just stops. | ||
556 | Also x64 version of PROBE code doesn't work, if we run it via Intel SDE emulator | ||
557 | without SHA512 support (-skl switch), | ||
558 | The program stops, and we have message from SDE: | ||
559 | TID 0 SDE-ERROR: Executed instruction not valid for specified chip (SKYLAKE): vsha512msg1 | ||
560 | But we still want to catch that exception instead of process stopping. | ||
561 | Does this PROBE code work in native Windows-arm64 (with/without sha512 hw instructions)? | ||
562 | Are there any ways to fix the problems with arm64-wine and x64-SDE cases? | ||
563 | */ | ||
564 | |||
565 | PRF(printf("==== CPU_IsSupported_SHA512 PROBE\n");) | ||
566 | { | ||
567 | BoolInt isSupported = False; | ||
568 | #ifdef Z7_SHA512_USE_LONGJMP | ||
569 | void (Z7_CDECL *signal_prev)(int); | ||
570 | /* | ||
571 | if (g_Sha512_Unsupported) | ||
572 | { | ||
573 | PRF(printf("==== g_Sha512_Unsupported\n");) | ||
574 | return False; | ||
575 | } | ||
576 | */ | ||
577 | printf("====== signal(SIGILL)\n"); | ||
578 | signal_prev = signal(SIGILL, Sha512_signal_Handler); | ||
579 | if (signal_prev == SIG_ERR) | ||
580 | { | ||
581 | PRF(printf("====== signal fail\n");) | ||
582 | return False; | ||
583 | } | ||
584 | // PRF(printf("==== signal_prev = %p\n", (void *)signal_prev);) | ||
585 | // docs: Before the specified function is executed, | ||
586 | // the value of func is set to SIG_DFL. | ||
587 | // So we can exit if (setjmp(g_Sha512_jmp_buf) != 0). | ||
588 | PRF(printf("====== setjmp\n");) | ||
589 | if (!setjmp(g_Sha512_jmp_buf)) | ||
590 | #else // Z7_SHA512_USE_LONGJMP | ||
591 | |||
592 | #ifdef _MSC_VER | ||
593 | #ifdef __clang_major__ | ||
594 | #pragma GCC diagnostic ignored "-Wlanguage-extension-token" | ||
595 | #endif | ||
596 | __try | ||
597 | #endif | ||
598 | #endif // Z7_SHA512_USE_LONGJMP | ||
599 | |||
600 | { | ||
601 | #if defined(Z7_COMPILER_SHA512_SUPPORTED) | ||
602 | #ifdef Z7_SHA512_USE_SIMPLIFIED_PROBE | ||
603 | // simplified sha512 check for arm64: | ||
604 | const uint64x2_t a = vdupq_n_u64(1); | ||
605 | const uint64x2_t b = vsha512hq_u64(a, a, a); | ||
606 | PRF(printf("======== vsha512hq_u64 probe\n");) | ||
607 | if ((UInt32)vgetq_lane_u64(b, 0) == 0x11800002) | ||
608 | #else | ||
609 | MY_ALIGN(16) | ||
610 | UInt64 temp[SHA512_NUM_DIGEST_WORDS + SHA512_NUM_BLOCK_WORDS]; | ||
611 | memset(temp, 0x5a, sizeof(temp)); | ||
612 | PRF(printf("======== Sha512_UpdateBlocks_HW\n");) | ||
613 | Sha512_UpdateBlocks_HW(temp, | ||
614 | (const Byte *)(const void *)(temp + SHA512_NUM_DIGEST_WORDS), 1); | ||
615 | // PRF(printf("======== t = %x\n", (UInt32)temp[0]);) | ||
616 | if ((UInt32)temp[0] == 0xa33cfdf7) | ||
617 | #endif | ||
618 | { | ||
619 | PRF(printf("======== PROBE SHA512: SHA512 is supported\n");) | ||
620 | isSupported = True; | ||
621 | } | ||
622 | #else // Z7_COMPILER_SHA512_SUPPORTED | ||
623 | // for debug : we generate bad instrction or raise exception. | ||
624 | // __except() doesn't catch raise() calls. | ||
625 | #ifdef Z7_SHA512_USE_LONGJMP | ||
626 | PRF(printf("====== raise(SIGILL)\n");) | ||
627 | raise(SIGILL); | ||
628 | #else | ||
629 | #if defined(_MSC_VER) && defined(MY_CPU_X86) | ||
630 | __asm ud2 | ||
631 | #endif | ||
632 | #endif // Z7_SHA512_USE_LONGJMP | ||
633 | #endif // Z7_COMPILER_SHA512_SUPPORTED | ||
634 | } | ||
635 | |||
636 | #ifdef Z7_SHA512_USE_LONGJMP | ||
637 | PRF(printf("====== restore signal SIGILL\n");) | ||
638 | signal(SIGILL, signal_prev); | ||
639 | #elif _MSC_VER | ||
640 | __except (EXCEPTION_EXECUTE_HANDLER) | ||
641 | { | ||
642 | PRF(printf("==== CPU_IsSupported_SHA512 __except(EXCEPTION_EXECUTE_HANDLER)\n");) | ||
643 | } | ||
644 | #endif | ||
645 | PRF(printf("== return (sha512 supported) = %d\n", isSupported);) | ||
646 | return isSupported; | ||
647 | } | ||
648 | #else | ||
649 | // without SHA512 PROBE code | ||
650 | return True; | ||
651 | #endif | ||
652 | } | ||
653 | |||
654 | #endif // Z7_SHA512_USE_PROBE | ||
655 | #endif // defined(Z7_SHA512_PROBE_DEBUG) || defined(Z7_COMPILER_SHA512_SUPPORTED) | ||
656 | |||
657 | |||
658 | void Sha512Prepare(void) | ||
659 | { | ||
660 | #ifdef Z7_COMPILER_SHA512_SUPPORTED | ||
661 | SHA512_FUNC_UPDATE_BLOCKS f, f_hw; | ||
662 | f = Sha512_UpdateBlocks; | ||
663 | f_hw = NULL; | ||
664 | #ifdef Z7_SHA512_USE_PROBE | ||
665 | if (CPU_IsSupported_SHA512_Probe()) | ||
666 | #elif defined(MY_CPU_X86_OR_AMD64) | ||
667 | if (CPU_IsSupported_SHA512() && CPU_IsSupported_AVX2()) | ||
668 | #else | ||
669 | if (CPU_IsSupported_SHA512()) | ||
670 | #endif | ||
671 | { | ||
672 | // printf("\n========== HW SHA512 ======== \n"); | ||
673 | f = f_hw = Sha512_UpdateBlocks_HW; | ||
674 | } | ||
675 | g_SHA512_FUNC_UPDATE_BLOCKS = f; | ||
676 | g_SHA512_FUNC_UPDATE_BLOCKS_HW = f_hw; | ||
677 | #elif defined(Z7_SHA512_PROBE_DEBUG) | ||
678 | CPU_IsSupported_SHA512_Probe(); // for debug | ||
679 | #endif | ||
680 | } | ||
681 | |||
682 | |||
683 | #undef K | ||
684 | #undef S0 | ||
685 | #undef S1 | ||
686 | #undef s0 | ||
687 | #undef s1 | ||
688 | #undef Ch | ||
689 | #undef Maj | ||
690 | #undef W_MAIN | ||
691 | #undef W_PRE | ||
692 | #undef w | ||
693 | #undef blk2_main | ||
694 | #undef blk2 | ||
695 | #undef T1 | ||
696 | #undef T4 | ||
697 | #undef T8 | ||
698 | #undef R1_PRE | ||
699 | #undef R1_MAIN | ||
700 | #undef R2_MAIN | ||
701 | #undef R4 | ||
702 | #undef R4_PRE | ||
703 | #undef R4_MAIN | ||
704 | #undef R8 | ||
705 | #undef R8_PRE | ||
706 | #undef R8_MAIN | ||
707 | #undef STEP_PRE | ||
708 | #undef STEP_MAIN | ||
709 | #undef Z7_SHA512_BIG_W | ||
710 | #undef Z7_SHA512_UNROLL | ||
711 | #undef Z7_COMPILER_SHA512_SUPPORTED | ||
diff --git a/C/Sha512.h b/C/Sha512.h new file mode 100644 index 0000000..1f3a4d1 --- /dev/null +++ b/C/Sha512.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* Sha512.h -- SHA-512 Hash | ||
2 | : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #ifndef ZIP7_INC_SHA512_H | ||
5 | #define ZIP7_INC_SHA512_H | ||
6 | |||
7 | #include "7zTypes.h" | ||
8 | |||
9 | EXTERN_C_BEGIN | ||
10 | |||
11 | #define SHA512_NUM_BLOCK_WORDS 16 | ||
12 | #define SHA512_NUM_DIGEST_WORDS 8 | ||
13 | |||
14 | #define SHA512_BLOCK_SIZE (SHA512_NUM_BLOCK_WORDS * 8) | ||
15 | #define SHA512_DIGEST_SIZE (SHA512_NUM_DIGEST_WORDS * 8) | ||
16 | #define SHA512_224_DIGEST_SIZE (224 / 8) | ||
17 | #define SHA512_256_DIGEST_SIZE (256 / 8) | ||
18 | #define SHA512_384_DIGEST_SIZE (384 / 8) | ||
19 | |||
20 | typedef void (Z7_FASTCALL *SHA512_FUNC_UPDATE_BLOCKS)(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
21 | |||
22 | /* | ||
23 | if (the system supports different SHA512 code implementations) | ||
24 | { | ||
25 | (CSha512::func_UpdateBlocks) will be used | ||
26 | (CSha512::func_UpdateBlocks) can be set by | ||
27 | Sha512_Init() - to default (fastest) | ||
28 | Sha512_SetFunction() - to any algo | ||
29 | } | ||
30 | else | ||
31 | { | ||
32 | (CSha512::func_UpdateBlocks) is ignored. | ||
33 | } | ||
34 | */ | ||
35 | |||
36 | typedef struct | ||
37 | { | ||
38 | union | ||
39 | { | ||
40 | struct | ||
41 | { | ||
42 | SHA512_FUNC_UPDATE_BLOCKS func_UpdateBlocks; | ||
43 | UInt64 count; | ||
44 | } vars; | ||
45 | UInt64 _pad_64bit[8]; | ||
46 | void *_pad_align_ptr[2]; | ||
47 | } v; | ||
48 | UInt64 state[SHA512_NUM_DIGEST_WORDS]; | ||
49 | |||
50 | Byte buffer[SHA512_BLOCK_SIZE]; | ||
51 | } CSha512; | ||
52 | |||
53 | |||
54 | #define SHA512_ALGO_DEFAULT 0 | ||
55 | #define SHA512_ALGO_SW 1 | ||
56 | #define SHA512_ALGO_HW 2 | ||
57 | |||
58 | /* | ||
59 | Sha512_SetFunction() | ||
60 | return: | ||
61 | 0 - (algo) value is not supported, and func_UpdateBlocks was not changed | ||
62 | 1 - func_UpdateBlocks was set according (algo) value. | ||
63 | */ | ||
64 | |||
65 | BoolInt Sha512_SetFunction(CSha512 *p, unsigned algo); | ||
66 | // we support only these (digestSize) values: 224/8, 256/8, 384/8, 512/8 | ||
67 | void Sha512_InitState(CSha512 *p, unsigned digestSize); | ||
68 | void Sha512_Init(CSha512 *p, unsigned digestSize); | ||
69 | void Sha512_Update(CSha512 *p, const Byte *data, size_t size); | ||
70 | void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize); | ||
71 | |||
72 | |||
73 | |||
74 | |||
75 | // void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
76 | |||
77 | /* | ||
78 | call Sha512Prepare() once at program start. | ||
79 | It prepares all supported implementations, and detects the fastest implementation. | ||
80 | */ | ||
81 | |||
82 | void Sha512Prepare(void); | ||
83 | |||
84 | EXTERN_C_END | ||
85 | |||
86 | #endif | ||
diff --git a/C/Sha512Opt.c b/C/Sha512Opt.c new file mode 100644 index 0000000..3a13868 --- /dev/null +++ b/C/Sha512Opt.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* Sha512Opt.c -- SHA-512 optimized code for SHA-512 hardware instructions | ||
2 | : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #include "Precomp.h" | ||
5 | #include "Compiler.h" | ||
6 | #include "CpuArch.h" | ||
7 | |||
8 | // #define Z7_USE_HW_SHA_STUB // for debug | ||
9 | #ifdef MY_CPU_X86_OR_AMD64 | ||
10 | #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 2400) && (__INTEL_COMPILER <= 9900) // fix it | ||
11 | #define USE_HW_SHA | ||
12 | #elif defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 170001) \ | ||
13 | || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 170001) \ | ||
14 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 140000) | ||
15 | #define USE_HW_SHA | ||
16 | #if !defined(__INTEL_COMPILER) | ||
17 | // icc defines __GNUC__, but icc doesn't support __attribute__(__target__) | ||
18 | #if !defined(__SHA512__) || !defined(__AVX2__) | ||
19 | #define ATTRIB_SHA512 __attribute__((__target__("sha512,avx2"))) | ||
20 | #endif | ||
21 | #endif | ||
22 | #elif defined(Z7_MSC_VER_ORIGINAL) | ||
23 | #if (_MSC_VER >= 1940) | ||
24 | #define USE_HW_SHA | ||
25 | #else | ||
26 | // #define Z7_USE_HW_SHA_STUB | ||
27 | #endif | ||
28 | #endif | ||
29 | // #endif // MY_CPU_X86_OR_AMD64 | ||
30 | #ifndef USE_HW_SHA | ||
31 | // #define Z7_USE_HW_SHA_STUB // for debug | ||
32 | #endif | ||
33 | |||
34 | #ifdef USE_HW_SHA | ||
35 | |||
36 | // #pragma message("Sha512 HW") | ||
37 | |||
38 | #include <immintrin.h> | ||
39 | |||
40 | #if defined (__clang__) && defined(_MSC_VER) | ||
41 | #if !defined(__AVX__) | ||
42 | #include <avxintrin.h> | ||
43 | #endif | ||
44 | #if !defined(__AVX2__) | ||
45 | #include <avx2intrin.h> | ||
46 | #endif | ||
47 | #if !defined(__SHA512__) | ||
48 | #include <sha512intrin.h> | ||
49 | #endif | ||
50 | #else | ||
51 | |||
52 | #endif | ||
53 | |||
54 | /* | ||
55 | SHA512 uses: | ||
56 | AVX: | ||
57 | _mm256_loadu_si256 (vmovdqu) | ||
58 | _mm256_storeu_si256 | ||
59 | _mm256_set_epi32 (unused) | ||
60 | AVX2: | ||
61 | _mm256_add_epi64 : vpaddq | ||
62 | _mm256_shuffle_epi8 : vpshufb | ||
63 | _mm256_shuffle_epi32 : pshufd | ||
64 | _mm256_blend_epi32 : vpblendd | ||
65 | _mm256_permute4x64_epi64 : vpermq : 3c | ||
66 | _mm256_permute2x128_si256: vperm2i128 : 3c | ||
67 | _mm256_extracti128_si256 : vextracti128 : 3c | ||
68 | SHA512: | ||
69 | _mm256_sha512* | ||
70 | */ | ||
71 | |||
72 | // K array must be aligned for 32-bytes at least. | ||
73 | // The compiler can look align attribute and selects | ||
74 | // vmovdqu - for code without align attribute | ||
75 | // vmovdqa - for code with align attribute | ||
76 | extern | ||
77 | MY_ALIGN(64) | ||
78 | const UInt64 SHA512_K_ARRAY[80]; | ||
79 | #define K SHA512_K_ARRAY | ||
80 | |||
81 | |||
82 | #define ADD_EPI64(dest, src) dest = _mm256_add_epi64(dest, src); | ||
83 | #define SHA512_MSG1(dest, src) dest = _mm256_sha512msg1_epi64(dest, _mm256_extracti128_si256(src, 0)); | ||
84 | #define SHA512_MSG2(dest, src) dest = _mm256_sha512msg2_epi64(dest, src); | ||
85 | |||
86 | #define LOAD_SHUFFLE(m, k) \ | ||
87 | m = _mm256_loadu_si256((const __m256i *)(const void *)(data + (k) * 32)); \ | ||
88 | m = _mm256_shuffle_epi8(m, mask); \ | ||
89 | |||
90 | #define NNN(m0, m1, m2, m3) | ||
91 | |||
92 | #define SM1(m1, m2, m3, m0) \ | ||
93 | SHA512_MSG1(m0, m1); \ | ||
94 | |||
95 | #define SM2(m2, m3, m0, m1) \ | ||
96 | ADD_EPI64(m0, _mm256_permute4x64_epi64(_mm256_blend_epi32(m2, m3, 3), 0x39)); \ | ||
97 | SHA512_MSG2(m0, m3); \ | ||
98 | |||
99 | #define RND2(t0, t1, lane) \ | ||
100 | t0 = _mm256_sha512rnds2_epi64(t0, t1, _mm256_extracti128_si256(msg, lane)); | ||
101 | |||
102 | |||
103 | |||
104 | #define R4(k, m0, m1, m2, m3, OP0, OP1) \ | ||
105 | msg = _mm256_add_epi64(m0, *(const __m256i *) (const void *) &K[(k) * 4]); \ | ||
106 | RND2(state0, state1, 0); OP0(m0, m1, m2, m3) \ | ||
107 | RND2(state1, state0, 1); OP1(m0, m1, m2, m3) \ | ||
108 | |||
109 | |||
110 | |||
111 | |||
112 | #define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ | ||
113 | R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \ | ||
114 | R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \ | ||
115 | R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \ | ||
116 | R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \ | ||
117 | |||
118 | #define PREPARE_STATE \ | ||
119 | state0 = _mm256_shuffle_epi32(state0, 0x4e); /* cdab */ \ | ||
120 | state1 = _mm256_shuffle_epi32(state1, 0x4e); /* ghef */ \ | ||
121 | tmp = state0; \ | ||
122 | state0 = _mm256_permute2x128_si256(state0, state1, 0x13); /* cdgh */ \ | ||
123 | state1 = _mm256_permute2x128_si256(tmp, state1, 2); /* abef */ \ | ||
124 | |||
125 | |||
126 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
127 | #ifdef ATTRIB_SHA512 | ||
128 | ATTRIB_SHA512 | ||
129 | #endif | ||
130 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks) | ||
131 | { | ||
132 | const __m256i mask = _mm256_set_epi32( | ||
133 | 0x08090a0b,0x0c0d0e0f, 0x00010203,0x04050607, | ||
134 | 0x08090a0b,0x0c0d0e0f, 0x00010203,0x04050607); | ||
135 | __m256i tmp, state0, state1; | ||
136 | |||
137 | if (numBlocks == 0) | ||
138 | return; | ||
139 | |||
140 | state0 = _mm256_loadu_si256((const __m256i *) (const void *) &state[0]); | ||
141 | state1 = _mm256_loadu_si256((const __m256i *) (const void *) &state[4]); | ||
142 | |||
143 | PREPARE_STATE | ||
144 | |||
145 | do | ||
146 | { | ||
147 | __m256i state0_save, state1_save; | ||
148 | __m256i m0, m1, m2, m3; | ||
149 | __m256i msg; | ||
150 | // #define msg tmp | ||
151 | |||
152 | state0_save = state0; | ||
153 | state1_save = state1; | ||
154 | |||
155 | LOAD_SHUFFLE (m0, 0) | ||
156 | LOAD_SHUFFLE (m1, 1) | ||
157 | LOAD_SHUFFLE (m2, 2) | ||
158 | LOAD_SHUFFLE (m3, 3) | ||
159 | |||
160 | |||
161 | |||
162 | R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ) | ||
163 | R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) | ||
164 | R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) | ||
165 | R16 ( 3, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ) | ||
166 | R16 ( 4, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ) | ||
167 | ADD_EPI64(state0, state0_save) | ||
168 | ADD_EPI64(state1, state1_save) | ||
169 | |||
170 | data += 128; | ||
171 | } | ||
172 | while (--numBlocks); | ||
173 | |||
174 | PREPARE_STATE | ||
175 | |||
176 | _mm256_storeu_si256((__m256i *) (void *) &state[0], state0); | ||
177 | _mm256_storeu_si256((__m256i *) (void *) &state[4], state1); | ||
178 | } | ||
179 | |||
180 | #endif // USE_HW_SHA | ||
181 | |||
182 | // gcc 8.5 also supports sha512, but we need also support in assembler that is called by gcc | ||
183 | #elif defined(MY_CPU_ARM64) && defined(MY_CPU_LE) | ||
184 | |||
185 | #if defined(__ARM_FEATURE_SHA512) | ||
186 | #define USE_HW_SHA | ||
187 | #else | ||
188 | #if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 130000) \ | ||
189 | || defined(__GNUC__) && (__GNUC__ >= 9) \ | ||
190 | ) \ | ||
191 | || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1940) // fix it | ||
192 | #define USE_HW_SHA | ||
193 | #endif | ||
194 | #endif | ||
195 | |||
196 | #ifdef USE_HW_SHA | ||
197 | |||
198 | // #pragma message("=== Sha512 HW === ") | ||
199 | |||
200 | |||
201 | #if defined(__clang__) || defined(__GNUC__) | ||
202 | #if !defined(__ARM_FEATURE_SHA512) | ||
203 | // #pragma message("=== we define SHA3 ATTRIB_SHA512 === ") | ||
204 | #if defined(__clang__) | ||
205 | #define ATTRIB_SHA512 __attribute__((__target__("sha3"))) // "armv8.2-a,sha3" | ||
206 | #else | ||
207 | #define ATTRIB_SHA512 __attribute__((__target__("arch=armv8.2-a+sha3"))) | ||
208 | #endif | ||
209 | #endif | ||
210 | #endif | ||
211 | |||
212 | |||
213 | #if defined(Z7_MSC_VER_ORIGINAL) | ||
214 | #include <arm64_neon.h> | ||
215 | #else | ||
216 | |||
217 | #if defined(__clang__) && __clang_major__ < 16 | ||
218 | #if !defined(__ARM_FEATURE_SHA512) | ||
219 | // #pragma message("=== we set __ARM_FEATURE_SHA512 1 === ") | ||
220 | Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER | ||
221 | #define Z7_ARM_FEATURE_SHA512_WAS_SET 1 | ||
222 | #define __ARM_FEATURE_SHA512 1 | ||
223 | Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER | ||
224 | #endif | ||
225 | #endif // clang | ||
226 | |||
227 | #include <arm_neon.h> | ||
228 | |||
229 | #if defined(Z7_ARM_FEATURE_SHA512_WAS_SET) && \ | ||
230 | defined(__ARM_FEATURE_SHA512) | ||
231 | Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER | ||
232 | #undef __ARM_FEATURE_SHA512 | ||
233 | #undef Z7_ARM_FEATURE_SHA512_WAS_SET | ||
234 | Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER | ||
235 | // #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ") | ||
236 | #endif | ||
237 | |||
238 | #endif // Z7_MSC_VER_ORIGINAL | ||
239 | |||
240 | typedef uint64x2_t v128_64; | ||
241 | // typedef __n128 v128_64; // MSVC | ||
242 | |||
243 | #ifdef MY_CPU_BE | ||
244 | #define MY_rev64_for_LE(x) x | ||
245 | #else | ||
246 | #define MY_rev64_for_LE(x) vrev64q_u8(x) | ||
247 | #endif | ||
248 | |||
249 | #define LOAD_128_64(_p) vld1q_u64(_p) | ||
250 | #define LOAD_128_8(_p) vld1q_u8 (_p) | ||
251 | #define STORE_128_64(_p, _v) vst1q_u64(_p, _v) | ||
252 | |||
253 | #define LOAD_SHUFFLE(m, k) \ | ||
254 | m = vreinterpretq_u64_u8( \ | ||
255 | MY_rev64_for_LE( \ | ||
256 | LOAD_128_8(data + (k) * 16))); \ | ||
257 | |||
258 | // K array must be aligned for 16-bytes at least. | ||
259 | extern | ||
260 | MY_ALIGN(64) | ||
261 | const UInt64 SHA512_K_ARRAY[80]; | ||
262 | #define K SHA512_K_ARRAY | ||
263 | |||
264 | #define NN(m0, m1, m4, m5, m7) | ||
265 | #define SM(m0, m1, m4, m5, m7) \ | ||
266 | m0 = vsha512su1q_u64(vsha512su0q_u64(m0, m1), m7, vextq_u64(m4, m5, 1)); | ||
267 | |||
268 | #define R2(k, m0,m1,m2,m3,m4,m5,m6,m7, a0,a1,a2,a3, OP) \ | ||
269 | OP(m0, m1, m4, m5, m7) \ | ||
270 | t = vaddq_u64(m0, vld1q_u64(k)); \ | ||
271 | t = vaddq_u64(vextq_u64(t, t, 1), a3); \ | ||
272 | t = vsha512hq_u64(t, vextq_u64(a2, a3, 1), vextq_u64(a1, a2, 1)); \ | ||
273 | a3 = vsha512h2q_u64(t, a1, a0); \ | ||
274 | a1 = vaddq_u64(a1, t); \ | ||
275 | |||
276 | #define R8(k, m0,m1,m2,m3,m4,m5,m6,m7, OP) \ | ||
277 | R2 ( (k)+0*2, m0,m1,m2,m3,m4,m5,m6,m7, a0,a1,a2,a3, OP ) \ | ||
278 | R2 ( (k)+1*2, m1,m2,m3,m4,m5,m6,m7,m0, a3,a0,a1,a2, OP ) \ | ||
279 | R2 ( (k)+2*2, m2,m3,m4,m5,m6,m7,m0,m1, a2,a3,a0,a1, OP ) \ | ||
280 | R2 ( (k)+3*2, m3,m4,m5,m6,m7,m0,m1,m2, a1,a2,a3,a0, OP ) \ | ||
281 | |||
282 | #define R16(k, OP) \ | ||
283 | R8 ( (k)+0*2, m0,m1,m2,m3,m4,m5,m6,m7, OP ) \ | ||
284 | R8 ( (k)+4*2, m4,m5,m6,m7,m0,m1,m2,m3, OP ) \ | ||
285 | |||
286 | |||
287 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
288 | #ifdef ATTRIB_SHA512 | ||
289 | ATTRIB_SHA512 | ||
290 | #endif | ||
291 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks) | ||
292 | { | ||
293 | v128_64 a0, a1, a2, a3; | ||
294 | |||
295 | if (numBlocks == 0) | ||
296 | return; | ||
297 | a0 = LOAD_128_64(&state[0]); | ||
298 | a1 = LOAD_128_64(&state[2]); | ||
299 | a2 = LOAD_128_64(&state[4]); | ||
300 | a3 = LOAD_128_64(&state[6]); | ||
301 | do | ||
302 | { | ||
303 | v128_64 a0_save, a1_save, a2_save, a3_save; | ||
304 | v128_64 m0, m1, m2, m3, m4, m5, m6, m7; | ||
305 | v128_64 t; | ||
306 | unsigned i; | ||
307 | const UInt64 *k_ptr; | ||
308 | |||
309 | LOAD_SHUFFLE (m0, 0) | ||
310 | LOAD_SHUFFLE (m1, 1) | ||
311 | LOAD_SHUFFLE (m2, 2) | ||
312 | LOAD_SHUFFLE (m3, 3) | ||
313 | LOAD_SHUFFLE (m4, 4) | ||
314 | LOAD_SHUFFLE (m5, 5) | ||
315 | LOAD_SHUFFLE (m6, 6) | ||
316 | LOAD_SHUFFLE (m7, 7) | ||
317 | |||
318 | a0_save = a0; | ||
319 | a1_save = a1; | ||
320 | a2_save = a2; | ||
321 | a3_save = a3; | ||
322 | |||
323 | R16 ( K, NN ) | ||
324 | k_ptr = K + 16; | ||
325 | for (i = 0; i < 4; i++) | ||
326 | { | ||
327 | R16 ( k_ptr, SM ) | ||
328 | k_ptr += 16; | ||
329 | } | ||
330 | |||
331 | a0 = vaddq_u64(a0, a0_save); | ||
332 | a1 = vaddq_u64(a1, a1_save); | ||
333 | a2 = vaddq_u64(a2, a2_save); | ||
334 | a3 = vaddq_u64(a3, a3_save); | ||
335 | |||
336 | data += 128; | ||
337 | } | ||
338 | while (--numBlocks); | ||
339 | |||
340 | STORE_128_64(&state[0], a0); | ||
341 | STORE_128_64(&state[2], a1); | ||
342 | STORE_128_64(&state[4], a2); | ||
343 | STORE_128_64(&state[6], a3); | ||
344 | } | ||
345 | |||
346 | #endif // USE_HW_SHA | ||
347 | |||
348 | #endif // MY_CPU_ARM_OR_ARM64 | ||
349 | |||
350 | |||
351 | #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB) | ||
352 | // #error Stop_Compiling_UNSUPPORTED_SHA | ||
353 | // #include <stdlib.h> | ||
354 | // We can compile this file with another C compiler, | ||
355 | // or we can compile asm version. | ||
356 | // So we can generate real code instead of this stub function. | ||
357 | // #include "Sha512.h" | ||
358 | // #if defined(_MSC_VER) | ||
359 | #pragma message("Sha512 HW-SW stub was used") | ||
360 | // #endif | ||
361 | void Z7_FASTCALL Sha512_UpdateBlocks (UInt64 state[8], const Byte *data, size_t numBlocks); | ||
362 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks); | ||
363 | void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks) | ||
364 | { | ||
365 | Sha512_UpdateBlocks(state, data, numBlocks); | ||
366 | /* | ||
367 | UNUSED_VAR(state); | ||
368 | UNUSED_VAR(data); | ||
369 | UNUSED_VAR(numBlocks); | ||
370 | exit(1); | ||
371 | return; | ||
372 | */ | ||
373 | } | ||
374 | #endif | ||
375 | |||
376 | |||
377 | #undef K | ||
378 | #undef RND2 | ||
379 | #undef MY_rev64_for_LE | ||
380 | #undef NN | ||
381 | #undef NNN | ||
382 | #undef LOAD_128 | ||
383 | #undef STORE_128 | ||
384 | #undef LOAD_SHUFFLE | ||
385 | #undef SM1 | ||
386 | #undef SM2 | ||
387 | #undef SM | ||
388 | #undef R2 | ||
389 | #undef R4 | ||
390 | #undef R16 | ||
391 | #undef PREPARE_STATE | ||
392 | #undef USE_HW_SHA | ||
393 | #undef ATTRIB_SHA512 | ||
394 | #undef USE_VER_MIN | ||
395 | #undef Z7_USE_HW_SHA_STUB | ||
@@ -1,141 +1,268 @@ | |||
1 | /* Sort.c -- Sort functions | 1 | /* Sort.c -- Sort functions |
2 | 2014-04-05 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
6 | #include "Sort.h" | 6 | #include "Sort.h" |
7 | #include "CpuArch.h" | ||
7 | 8 | ||
8 | #define HeapSortDown(p, k, size, temp) \ | 9 | #if ( (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ |
9 | { for (;;) { \ | 10 | || (defined(__clang__) && Z7_has_builtin(__builtin_prefetch)) \ |
10 | size_t s = (k << 1); \ | 11 | ) |
11 | if (s > size) break; \ | 12 | // the code with prefetch is slow for small arrays on x86. |
12 | if (s < size && p[s + 1] > p[s]) s++; \ | 13 | // So we disable prefetch for x86. |
13 | if (temp >= p[s]) break; \ | 14 | #ifndef MY_CPU_X86 |
14 | p[k] = p[s]; k = s; \ | 15 | // #pragma message("Z7_PREFETCH : __builtin_prefetch") |
15 | } p[k] = temp; } | 16 | #define Z7_PREFETCH(a) __builtin_prefetch((a)) |
17 | #endif | ||
16 | 18 | ||
17 | void HeapSort(UInt32 *p, size_t size) | 19 | #elif defined(_WIN32) // || defined(_MSC_VER) && (_MSC_VER >= 1200) |
18 | { | 20 | |
19 | if (size <= 1) | 21 | #include "7zWindows.h" |
20 | return; | 22 | |
21 | p--; | 23 | // NOTE: CLANG/GCC/MSVC can define different values for _MM_HINT_T0 / PF_TEMPORAL_LEVEL_1. |
22 | { | 24 | // For example, clang-cl can generate "prefetcht2" instruction for |
23 | size_t i = size / 2; | 25 | // PreFetchCacheLine(PF_TEMPORAL_LEVEL_1) call. |
24 | do | 26 | // But we want to generate "prefetcht0" instruction. |
25 | { | 27 | // So for CLANG/GCC we must use __builtin_prefetch() in code branch above |
26 | UInt32 temp = p[i]; | 28 | // instead of PreFetchCacheLine() / _mm_prefetch(). |
27 | size_t k = i; | 29 | |
28 | HeapSortDown(p, k, size, temp) | 30 | // New msvc-x86 compiler generates "prefetcht0" instruction for PreFetchCacheLine() call. |
29 | } | 31 | // But old x86 cpus don't support "prefetcht0". |
30 | while (--i != 0); | 32 | // So we will use PreFetchCacheLine(), only if we are sure that |
31 | } | 33 | // generated instruction is supported by all cpus of that isa. |
32 | /* | 34 | #if defined(MY_CPU_AMD64) \ |
33 | do | 35 | || defined(MY_CPU_ARM64) \ |
34 | { | 36 | || defined(MY_CPU_IA64) |
35 | size_t k = 1; | 37 | // we need to use additional braces for (a) in PreFetchCacheLine call, because |
36 | UInt32 temp = p[size]; | 38 | // PreFetchCacheLine macro doesn't use braces: |
37 | p[size--] = p[1]; | 39 | // #define PreFetchCacheLine(l, a) _mm_prefetch((CHAR CONST *) a, l) |
38 | HeapSortDown(p, k, size, temp) | 40 | // #pragma message("Z7_PREFETCH : PreFetchCacheLine") |
39 | } | 41 | #define Z7_PREFETCH(a) PreFetchCacheLine(PF_TEMPORAL_LEVEL_1, (a)) |
40 | while (size > 1); | 42 | #endif |
41 | */ | 43 | |
42 | while (size > 3) | 44 | #endif // _WIN32 |
43 | { | 45 | |
44 | UInt32 temp = p[size]; | 46 | |
45 | size_t k = (p[3] > p[2]) ? 3 : 2; | 47 | #define PREFETCH_NO(p,k,s,size) |
46 | p[size--] = p[1]; | 48 | |
47 | p[1] = p[k]; | 49 | #ifndef Z7_PREFETCH |
48 | HeapSortDown(p, k, size, temp) | 50 | #define SORT_PREFETCH(p,k,s,size) |
49 | } | 51 | #else |
50 | { | 52 | |
51 | UInt32 temp = p[size]; | 53 | // #define PREFETCH_LEVEL 2 // use it if cache line is 32-bytes |
52 | p[size] = p[1]; | 54 | #define PREFETCH_LEVEL 3 // it is fast for most cases (64-bytes cache line prefetch) |
53 | if (size > 2 && p[2] < temp) | 55 | // #define PREFETCH_LEVEL 4 // it can be faster for big array (128-bytes prefetch) |
54 | { | 56 | |
55 | p[1] = p[2]; | 57 | #if PREFETCH_LEVEL == 0 |
56 | p[2] = temp; | 58 | |
57 | } | 59 | #define SORT_PREFETCH(p,k,s,size) |
58 | else | 60 | |
59 | p[1] = temp; | 61 | #else // PREFETCH_LEVEL != 0 |
60 | } | 62 | |
63 | /* | ||
64 | if defined(USE_PREFETCH_FOR_ALIGNED_ARRAY) | ||
65 | we prefetch one value per cache line. | ||
66 | Use it if array is aligned for cache line size (64 bytes) | ||
67 | or if array is small (less than L1 cache size). | ||
68 | |||
69 | if !defined(USE_PREFETCH_FOR_ALIGNED_ARRAY) | ||
70 | we perfetch all cache lines that can be required. | ||
71 | it can be faster for big unaligned arrays. | ||
72 | */ | ||
73 | #define USE_PREFETCH_FOR_ALIGNED_ARRAY | ||
74 | |||
75 | // s == k * 2 | ||
76 | #if 0 && PREFETCH_LEVEL <= 3 && defined(MY_CPU_X86_OR_AMD64) | ||
77 | // x86 supports (lea r1*8+offset) | ||
78 | #define PREFETCH_OFFSET(k,s) ((s) << PREFETCH_LEVEL) | ||
79 | #else | ||
80 | #define PREFETCH_OFFSET(k,s) ((k) << (PREFETCH_LEVEL + 1)) | ||
81 | #endif | ||
82 | |||
83 | #if 1 && PREFETCH_LEVEL <= 3 && defined(USE_PREFETCH_FOR_ALIGNED_ARRAY) | ||
84 | #define PREFETCH_ADD_OFFSET 0 | ||
85 | #else | ||
86 | // last offset that can be reqiured in PREFETCH_LEVEL step: | ||
87 | #define PREFETCH_RANGE ((2 << PREFETCH_LEVEL) - 1) | ||
88 | #define PREFETCH_ADD_OFFSET PREFETCH_RANGE / 2 | ||
89 | #endif | ||
90 | |||
91 | #if PREFETCH_LEVEL <= 3 | ||
92 | |||
93 | #ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY | ||
94 | #define SORT_PREFETCH(p,k,s,size) \ | ||
95 | { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_ADD_OFFSET; \ | ||
96 | if (s2 <= size) { \ | ||
97 | Z7_PREFETCH((p + s2)); \ | ||
98 | }} | ||
99 | #else /* for unaligned array */ | ||
100 | #define SORT_PREFETCH(p,k,s,size) \ | ||
101 | { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \ | ||
102 | if (s2 <= size) { \ | ||
103 | Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \ | ||
104 | Z7_PREFETCH((p + s2)); \ | ||
105 | }} | ||
106 | #endif | ||
107 | |||
108 | #else // PREFETCH_LEVEL > 3 | ||
109 | |||
110 | #ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY | ||
111 | #define SORT_PREFETCH(p,k,s,size) \ | ||
112 | { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE - 16 / 2; \ | ||
113 | if (s2 <= size) { \ | ||
114 | Z7_PREFETCH((p + s2 - 16)); \ | ||
115 | Z7_PREFETCH((p + s2)); \ | ||
116 | }} | ||
117 | #else /* for unaligned array */ | ||
118 | #define SORT_PREFETCH(p,k,s,size) \ | ||
119 | { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \ | ||
120 | if (s2 <= size) { \ | ||
121 | Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \ | ||
122 | Z7_PREFETCH((p + s2 - PREFETCH_RANGE / 2)); \ | ||
123 | Z7_PREFETCH((p + s2)); \ | ||
124 | }} | ||
125 | #endif | ||
126 | |||
127 | #endif // PREFETCH_LEVEL > 3 | ||
128 | #endif // PREFETCH_LEVEL != 0 | ||
129 | #endif // Z7_PREFETCH | ||
130 | |||
131 | |||
132 | #if defined(MY_CPU_ARM64) \ | ||
133 | /* || defined(MY_CPU_AMD64) */ \ | ||
134 | /* || defined(MY_CPU_ARM) && !defined(_MSC_VER) */ | ||
135 | // we want to use cmov, if cmov is very fast: | ||
136 | // - this cmov version is slower for clang-x64. | ||
137 | // - this cmov version is faster for gcc-arm64 for some fast arm64 cpus. | ||
138 | #define Z7_FAST_CMOV_SUPPORTED | ||
139 | #endif | ||
140 | |||
141 | #ifdef Z7_FAST_CMOV_SUPPORTED | ||
142 | // we want to use cmov here, if cmov is fast: new arm64 cpus. | ||
143 | // we want the compiler to use conditional move for this branch | ||
144 | #define GET_MAX_VAL(n0, n1, max_val_slow) if (n0 < n1) n0 = n1; | ||
145 | #else | ||
146 | // use this branch, if cpu doesn't support fast conditional move. | ||
147 | // it uses slow array access reading: | ||
148 | #define GET_MAX_VAL(n0, n1, max_val_slow) n0 = max_val_slow; | ||
149 | #endif | ||
150 | |||
151 | #define HeapSortDown(p, k, size, temp, macro_prefetch) \ | ||
152 | { \ | ||
153 | for (;;) { \ | ||
154 | UInt32 n0, n1; \ | ||
155 | size_t s = k * 2; \ | ||
156 | if (s >= size) { \ | ||
157 | if (s == size) { \ | ||
158 | n0 = p[s]; \ | ||
159 | p[k] = n0; \ | ||
160 | if (temp < n0) k = s; \ | ||
161 | } \ | ||
162 | break; \ | ||
163 | } \ | ||
164 | n0 = p[k * 2]; \ | ||
165 | n1 = p[k * 2 + 1]; \ | ||
166 | s += n0 < n1; \ | ||
167 | GET_MAX_VAL(n0, n1, p[s]) \ | ||
168 | if (temp >= n0) break; \ | ||
169 | macro_prefetch(p, k, s, size) \ | ||
170 | p[k] = n0; \ | ||
171 | k = s; \ | ||
172 | } \ | ||
173 | p[k] = temp; \ | ||
61 | } | 174 | } |
62 | 175 | ||
63 | void HeapSort64(UInt64 *p, size_t size) | 176 | |
177 | /* | ||
178 | stage-1 : O(n) : | ||
179 | we generate intermediate partially sorted binary tree: | ||
180 | p[0] : it's additional item for better alignment of tree structure in memory. | ||
181 | p[1] | ||
182 | p[2] p[3] | ||
183 | p[4] p[5] p[6] p[7] | ||
184 | ... | ||
185 | p[x] >= p[x * 2] | ||
186 | p[x] >= p[x * 2 + 1] | ||
187 | |||
188 | stage-2 : O(n)*log2(N): | ||
189 | we move largest item p[0] from head of tree to the end of array | ||
190 | and insert last item to sorted binary tree. | ||
191 | */ | ||
192 | |||
193 | // (p) must be aligned for cache line size (64-bytes) for best performance | ||
194 | |||
195 | void Z7_FASTCALL HeapSort(UInt32 *p, size_t size) | ||
64 | { | 196 | { |
65 | if (size <= 1) | 197 | if (size < 2) |
66 | return; | 198 | return; |
67 | p--; | 199 | if (size == 2) |
68 | { | ||
69 | size_t i = size / 2; | ||
70 | do | ||
71 | { | ||
72 | UInt64 temp = p[i]; | ||
73 | size_t k = i; | ||
74 | HeapSortDown(p, k, size, temp) | ||
75 | } | ||
76 | while (--i != 0); | ||
77 | } | ||
78 | /* | ||
79 | do | ||
80 | { | 200 | { |
81 | size_t k = 1; | 201 | const UInt32 a0 = p[0]; |
82 | UInt64 temp = p[size]; | 202 | const UInt32 a1 = p[1]; |
83 | p[size--] = p[1]; | 203 | const unsigned k = a1 < a0; |
84 | HeapSortDown(p, k, size, temp) | 204 | p[k] = a0; |
85 | } | 205 | p[k ^ 1] = a1; |
86 | while (size > 1); | 206 | return; |
87 | */ | ||
88 | while (size > 3) | ||
89 | { | ||
90 | UInt64 temp = p[size]; | ||
91 | size_t k = (p[3] > p[2]) ? 3 : 2; | ||
92 | p[size--] = p[1]; | ||
93 | p[1] = p[k]; | ||
94 | HeapSortDown(p, k, size, temp) | ||
95 | } | 207 | } |
96 | { | 208 | { |
97 | UInt64 temp = p[size]; | 209 | // stage-1 : O(n) |
98 | p[size] = p[1]; | 210 | // we transform array to partially sorted binary tree. |
99 | if (size > 2 && p[2] < temp) | 211 | size_t i = --size / 2; |
212 | // (size) now is the index of the last item in tree, | ||
213 | // if (i) | ||
100 | { | 214 | { |
101 | p[1] = p[2]; | 215 | do |
102 | p[2] = temp; | 216 | { |
217 | const UInt32 temp = p[i]; | ||
218 | size_t k = i; | ||
219 | HeapSortDown(p, k, size, temp, PREFETCH_NO) | ||
220 | } | ||
221 | while (--i); | ||
222 | } | ||
223 | { | ||
224 | const UInt32 temp = p[0]; | ||
225 | const UInt32 a1 = p[1]; | ||
226 | if (temp < a1) | ||
227 | { | ||
228 | size_t k = 1; | ||
229 | p[0] = a1; | ||
230 | HeapSortDown(p, k, size, temp, PREFETCH_NO) | ||
231 | } | ||
103 | } | 232 | } |
104 | else | ||
105 | p[1] = temp; | ||
106 | } | 233 | } |
107 | } | ||
108 | 234 | ||
109 | /* | 235 | if (size < 3) |
110 | #define HeapSortRefDown(p, vals, n, size, temp) \ | 236 | { |
111 | { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ | 237 | // size == 2 |
112 | size_t s = (k << 1); \ | 238 | const UInt32 a0 = p[0]; |
113 | if (s > size) break; \ | 239 | p[0] = p[2]; |
114 | if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ | 240 | p[2] = a0; |
115 | if (val >= vals[p[s]]) break; \ | ||
116 | p[k] = p[s]; k = s; \ | ||
117 | } p[k] = temp; } | ||
118 | |||
119 | void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) | ||
120 | { | ||
121 | if (size <= 1) | ||
122 | return; | 241 | return; |
123 | p--; | 242 | } |
243 | if (size != 3) | ||
124 | { | 244 | { |
125 | size_t i = size / 2; | 245 | // stage-2 : O(size) * log2(size): |
246 | // we move largest item p[0] from head to the end of array, | ||
247 | // and insert last item to sorted binary tree. | ||
126 | do | 248 | do |
127 | { | 249 | { |
128 | UInt32 temp = p[i]; | 250 | const UInt32 temp = p[size]; |
129 | HeapSortRefDown(p, vals, i, size, temp); | 251 | size_t k = p[2] < p[3] ? 3 : 2; |
252 | p[size--] = p[0]; | ||
253 | p[0] = p[1]; | ||
254 | p[1] = p[k]; | ||
255 | HeapSortDown(p, k, size, temp, SORT_PREFETCH) // PREFETCH_NO | ||
130 | } | 256 | } |
131 | while (--i != 0); | 257 | while (size != 3); |
132 | } | 258 | } |
133 | do | ||
134 | { | 259 | { |
135 | UInt32 temp = p[size]; | 260 | const UInt32 a2 = p[2]; |
136 | p[size--] = p[1]; | 261 | const UInt32 a3 = p[3]; |
137 | HeapSortRefDown(p, vals, 1, size, temp); | 262 | const size_t k = a2 < a3; |
263 | p[2] = p[1]; | ||
264 | p[3] = p[0]; | ||
265 | p[k] = a3; | ||
266 | p[k ^ 1] = a2; | ||
138 | } | 267 | } |
139 | while (size > 1); | ||
140 | } | 268 | } |
141 | */ | ||
@@ -1,5 +1,5 @@ | |||
1 | /* Sort.h -- Sort functions | 1 | /* Sort.h -- Sort functions |
2 | 2023-03-05 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_SORT_H | 4 | #ifndef ZIP7_INC_SORT_H |
5 | #define ZIP7_INC_SORT_H | 5 | #define ZIP7_INC_SORT_H |
@@ -8,10 +8,7 @@ | |||
8 | 8 | ||
9 | EXTERN_C_BEGIN | 9 | EXTERN_C_BEGIN |
10 | 10 | ||
11 | void HeapSort(UInt32 *p, size_t size); | 11 | void Z7_FASTCALL HeapSort(UInt32 *p, size_t size); |
12 | void HeapSort64(UInt64 *p, size_t size); | ||
13 | |||
14 | /* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ | ||
15 | 12 | ||
16 | EXTERN_C_END | 13 | EXTERN_C_END |
17 | 14 | ||
diff --git a/C/Threads.c b/C/Threads.c index 464efec..177d1d9 100644 --- a/C/Threads.c +++ b/C/Threads.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Threads.c -- multithreading library | 1 | /* Threads.c -- multithreading library |
2 | 2024-03-28 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -59,6 +59,100 @@ WRes Thread_Wait_Close(CThread *p) | |||
59 | return (res != 0 ? res : res2); | 59 | return (res != 0 ? res : res2); |
60 | } | 60 | } |
61 | 61 | ||
62 | typedef struct MY_PROCESSOR_NUMBER { | ||
63 | WORD Group; | ||
64 | BYTE Number; | ||
65 | BYTE Reserved; | ||
66 | } MY_PROCESSOR_NUMBER, *MY_PPROCESSOR_NUMBER; | ||
67 | |||
68 | typedef struct MY_GROUP_AFFINITY { | ||
69 | #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 100000) | ||
70 | // KAFFINITY is not defined in old mingw | ||
71 | ULONG_PTR | ||
72 | #else | ||
73 | KAFFINITY | ||
74 | #endif | ||
75 | Mask; | ||
76 | WORD Group; | ||
77 | WORD Reserved[3]; | ||
78 | } MY_GROUP_AFFINITY, *MY_PGROUP_AFFINITY; | ||
79 | |||
80 | typedef BOOL (WINAPI *Func_SetThreadGroupAffinity)( | ||
81 | HANDLE hThread, | ||
82 | CONST MY_GROUP_AFFINITY *GroupAffinity, | ||
83 | MY_PGROUP_AFFINITY PreviousGroupAffinity); | ||
84 | |||
85 | typedef BOOL (WINAPI *Func_GetThreadGroupAffinity)( | ||
86 | HANDLE hThread, | ||
87 | MY_PGROUP_AFFINITY GroupAffinity); | ||
88 | |||
89 | typedef BOOL (WINAPI *Func_GetProcessGroupAffinity)( | ||
90 | HANDLE hProcess, | ||
91 | PUSHORT GroupCount, | ||
92 | PUSHORT GroupArray); | ||
93 | |||
94 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
95 | |||
96 | #if 0 | ||
97 | #include <stdio.h> | ||
98 | #define PRF(x) x | ||
99 | /* | ||
100 | -- | ||
101 | before call of SetThreadGroupAffinity() | ||
102 | GetProcessGroupAffinity return one group. | ||
103 | after call of SetThreadGroupAffinity(): | ||
104 | GetProcessGroupAffinity return more than group, | ||
105 | if SetThreadGroupAffinity() was to another group. | ||
106 | -- | ||
107 | GetProcessAffinityMask MS DOCs: | ||
108 | { | ||
109 | If the calling process contains threads in multiple groups, | ||
110 | the function returns zero for both affinity masks. | ||
111 | } | ||
112 | but tests in win10 with 2 groups (less than 64 cores total): | ||
113 | GetProcessAffinityMask() still returns non-zero affinity masks | ||
114 | even after SetThreadGroupAffinity() calls. | ||
115 | */ | ||
116 | static void PrintProcess_Info() | ||
117 | { | ||
118 | { | ||
119 | const | ||
120 | Func_GetProcessGroupAffinity fn_GetProcessGroupAffinity = | ||
121 | (Func_GetProcessGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), | ||
122 | "GetProcessGroupAffinity"); | ||
123 | if (fn_GetProcessGroupAffinity) | ||
124 | { | ||
125 | unsigned i; | ||
126 | USHORT GroupCounts[64]; | ||
127 | USHORT GroupCount = Z7_ARRAY_SIZE(GroupCounts); | ||
128 | BOOL boolRes = fn_GetProcessGroupAffinity(GetCurrentProcess(), | ||
129 | &GroupCount, GroupCounts); | ||
130 | printf("\n====== GetProcessGroupAffinity : " | ||
131 | "boolRes=%u GroupCounts = %u :", | ||
132 | boolRes, (unsigned)GroupCount); | ||
133 | for (i = 0; i < GroupCount; i++) | ||
134 | printf(" %u", GroupCounts[i]); | ||
135 | printf("\n"); | ||
136 | } | ||
137 | } | ||
138 | { | ||
139 | DWORD_PTR processAffinityMask, systemAffinityMask; | ||
140 | if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask)) | ||
141 | { | ||
142 | PRF(printf("\n====== GetProcessAffinityMask : " | ||
143 | ": processAffinityMask=%x, systemAffinityMask=%x\n", | ||
144 | (UInt32)processAffinityMask, (UInt32)systemAffinityMask);) | ||
145 | } | ||
146 | else | ||
147 | printf("\n==GetProcessAffinityMask FAIL"); | ||
148 | } | ||
149 | } | ||
150 | #else | ||
151 | #ifndef USE_THREADS_CreateThread | ||
152 | // #define PRF(x) | ||
153 | #endif | ||
154 | #endif | ||
155 | |||
62 | WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) | 156 | WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) |
63 | { | 157 | { |
64 | /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ | 158 | /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ |
@@ -72,7 +166,43 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) | |||
72 | 166 | ||
73 | unsigned threadId; | 167 | unsigned threadId; |
74 | *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); | 168 | *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); |
75 | 169 | ||
170 | #if 0 // 1 : for debug | ||
171 | { | ||
172 | DWORD_PTR prevMask; | ||
173 | DWORD_PTR affinity = 1 << 0; | ||
174 | prevMask = SetThreadAffinityMask(*p, (DWORD_PTR)affinity); | ||
175 | prevMask = prevMask; | ||
176 | } | ||
177 | #endif | ||
178 | #if 0 // 1 : for debug | ||
179 | { | ||
180 | /* win10: new thread will be created in same group that is assigned to parent thread | ||
181 | but affinity mask will contain all allowed threads of that group, | ||
182 | even if affinity mask of parent group is not full | ||
183 | win11: what group it will be created, if we have set | ||
184 | affinity of parent thread with ThreadGroupAffinity? | ||
185 | */ | ||
186 | const | ||
187 | Func_GetThreadGroupAffinity fn = | ||
188 | (Func_GetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), | ||
189 | "GetThreadGroupAffinity"); | ||
190 | if (fn) | ||
191 | { | ||
192 | // BOOL wres2; | ||
193 | MY_GROUP_AFFINITY groupAffinity; | ||
194 | memset(&groupAffinity, 0, sizeof(groupAffinity)); | ||
195 | /* wres2 = */ fn(*p, &groupAffinity); | ||
196 | PRF(printf("\n==Thread_Create cur = %6u GetThreadGroupAffinity(): " | ||
197 | "wres2_BOOL = %u, group=%u mask=%x\n", | ||
198 | GetCurrentThreadId(), | ||
199 | wres2, | ||
200 | groupAffinity.Group, | ||
201 | (UInt32)groupAffinity.Mask);) | ||
202 | } | ||
203 | } | ||
204 | #endif | ||
205 | |||
76 | #endif | 206 | #endif |
77 | 207 | ||
78 | /* maybe we must use errno here, but probably GetLastError() is also OK. */ | 208 | /* maybe we must use errno here, but probably GetLastError() is also OK. */ |
@@ -110,7 +240,84 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param | |||
110 | */ | 240 | */ |
111 | } | 241 | } |
112 | { | 242 | { |
113 | DWORD prevSuspendCount = ResumeThread(h); | 243 | const DWORD prevSuspendCount = ResumeThread(h); |
244 | /* ResumeThread() returns: | ||
245 | 0 : was_not_suspended | ||
246 | 1 : was_resumed | ||
247 | -1 : error | ||
248 | */ | ||
249 | if (prevSuspendCount == (DWORD)-1) | ||
250 | wres = GetError(); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* maybe we must use errno here, but probably GetLastError() is also OK. */ | ||
255 | return wres; | ||
256 | |||
257 | #endif | ||
258 | } | ||
259 | |||
260 | |||
261 | WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask) | ||
262 | { | ||
263 | #ifdef USE_THREADS_CreateThread | ||
264 | |||
265 | UNUSED_VAR(group) | ||
266 | UNUSED_VAR(affinityMask) | ||
267 | return Thread_Create(p, func, param); | ||
268 | |||
269 | #else | ||
270 | |||
271 | /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ | ||
272 | HANDLE h; | ||
273 | WRes wres; | ||
274 | unsigned threadId; | ||
275 | h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); | ||
276 | *p = h; | ||
277 | wres = HandleToWRes(h); | ||
278 | if (h) | ||
279 | { | ||
280 | // PrintProcess_Info(); | ||
281 | { | ||
282 | const | ||
283 | Func_SetThreadGroupAffinity fn = | ||
284 | (Func_SetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), | ||
285 | "SetThreadGroupAffinity"); | ||
286 | if (fn) | ||
287 | { | ||
288 | // WRes wres2; | ||
289 | MY_GROUP_AFFINITY groupAffinity, prev_groupAffinity; | ||
290 | memset(&groupAffinity, 0, sizeof(groupAffinity)); | ||
291 | // groupAffinity.Mask must use only bits that supported by current group | ||
292 | // (groupAffinity.Mask = 0) means all allowed bits | ||
293 | groupAffinity.Mask = affinityMask; | ||
294 | groupAffinity.Group = (WORD)group; | ||
295 | // wres2 = | ||
296 | fn(h, &groupAffinity, &prev_groupAffinity); | ||
297 | /* | ||
298 | if (groupAffinity.Group == prev_groupAffinity.Group) | ||
299 | wres2 = wres2; | ||
300 | else | ||
301 | wres2 = wres2; | ||
302 | if (wres2 == 0) | ||
303 | { | ||
304 | wres2 = GetError(); | ||
305 | PRF(printf("\n==SetThreadGroupAffinity error: %u\n", wres2);) | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | PRF(printf("\n==Thread_Create_With_Group::SetThreadGroupAffinity()" | ||
310 | " threadId = %6u" | ||
311 | " group=%u mask=%x\n", | ||
312 | threadId, | ||
313 | prev_groupAffinity.Group, | ||
314 | (UInt32)prev_groupAffinity.Mask);) | ||
315 | } | ||
316 | */ | ||
317 | } | ||
318 | } | ||
319 | { | ||
320 | const DWORD prevSuspendCount = ResumeThread(h); | ||
114 | /* ResumeThread() returns: | 321 | /* ResumeThread() returns: |
115 | 0 : was_not_suspended | 322 | 0 : was_not_suspended |
116 | 1 : was_resumed | 323 | 1 : was_resumed |
@@ -297,6 +504,13 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) | |||
297 | return Thread_Create_With_CpuSet(p, func, param, NULL); | 504 | return Thread_Create_With_CpuSet(p, func, param, NULL); |
298 | } | 505 | } |
299 | 506 | ||
507 | /* | ||
508 | WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinity) | ||
509 | { | ||
510 | UNUSED_VAR(group) | ||
511 | return Thread_Create_With_Affinity(p, func, param, affinity); | ||
512 | } | ||
513 | */ | ||
300 | 514 | ||
301 | WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) | 515 | WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) |
302 | { | 516 | { |
@@ -577,5 +791,22 @@ WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) | |||
577 | return AutoResetEvent_CreateNotSignaled(p); | 791 | return AutoResetEvent_CreateNotSignaled(p); |
578 | } | 792 | } |
579 | 793 | ||
794 | void ThreadNextGroup_Init(CThreadNextGroup *p, UInt32 numGroups, UInt32 startGroup) | ||
795 | { | ||
796 | // printf("\n====== ThreadNextGroup_Init numGroups = %x: startGroup=%x\n", numGroups, startGroup); | ||
797 | if (numGroups == 0) | ||
798 | numGroups = 1; | ||
799 | p->NumGroups = numGroups; | ||
800 | p->NextGroup = startGroup % numGroups; | ||
801 | } | ||
802 | |||
803 | |||
804 | UInt32 ThreadNextGroup_GetNext(CThreadNextGroup *p) | ||
805 | { | ||
806 | const UInt32 next = p->NextGroup; | ||
807 | p->NextGroup = (next + 1) % p->NumGroups; | ||
808 | return next; | ||
809 | } | ||
810 | |||
580 | #undef PRF | 811 | #undef PRF |
581 | #undef Print | 812 | #undef Print |
diff --git a/C/Threads.h b/C/Threads.h index c1484a2..be12e6e 100644 --- a/C/Threads.h +++ b/C/Threads.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Threads.h -- multithreading library | 1 | /* Threads.h -- multithreading library |
2 | 2024-03-28 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_THREADS_H | 4 | #ifndef ZIP7_INC_THREADS_H |
5 | #define ZIP7_INC_THREADS_H | 5 | #define ZIP7_INC_THREADS_H |
@@ -140,12 +140,22 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param | |||
140 | WRes Thread_Wait_Close(CThread *p); | 140 | WRes Thread_Wait_Close(CThread *p); |
141 | 141 | ||
142 | #ifdef _WIN32 | 142 | #ifdef _WIN32 |
143 | WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask); | ||
143 | #define Thread_Create_With_CpuSet(p, func, param, cs) \ | 144 | #define Thread_Create_With_CpuSet(p, func, param, cs) \ |
144 | Thread_Create_With_Affinity(p, func, param, *cs) | 145 | Thread_Create_With_Affinity(p, func, param, *cs) |
145 | #else | 146 | #else |
146 | WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); | 147 | WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); |
147 | #endif | 148 | #endif |
148 | 149 | ||
150 | typedef struct | ||
151 | { | ||
152 | unsigned NumGroups; | ||
153 | unsigned NextGroup; | ||
154 | } CThreadNextGroup; | ||
155 | |||
156 | void ThreadNextGroup_Init(CThreadNextGroup *p, unsigned numGroups, unsigned startGroup); | ||
157 | unsigned ThreadNextGroup_GetNext(CThreadNextGroup *p); | ||
158 | |||
149 | 159 | ||
150 | #ifdef _WIN32 | 160 | #ifdef _WIN32 |
151 | 161 | ||
diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp index e2e7d42..71de950 100644 --- a/C/Util/Lzma/LzmaUtil.dsp +++ b/C/Util/Lzma/LzmaUtil.dsp | |||
@@ -122,6 +122,10 @@ SOURCE=..\..\Compiler.h | |||
122 | # End Source File | 122 | # End Source File |
123 | # Begin Source File | 123 | # Begin Source File |
124 | 124 | ||
125 | SOURCE=..\..\CpuArch.c | ||
126 | # End Source File | ||
127 | # Begin Source File | ||
128 | |||
125 | SOURCE=..\..\CpuArch.h | 129 | SOURCE=..\..\CpuArch.h |
126 | # End Source File | 130 | # End Source File |
127 | # Begin Source File | 131 | # Begin Source File |
diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp index bacd967..f413137 100644 --- a/C/Util/LzmaLib/LzmaLib.dsp +++ b/C/Util/LzmaLib/LzmaLib.dsp | |||
@@ -43,7 +43,7 @@ RSC=rc.exe | |||
43 | # PROP Ignore_Export_Lib 0 | 43 | # PROP Ignore_Export_Lib 0 |
44 | # PROP Target_Dir "" | 44 | # PROP Target_Dir "" |
45 | # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c | 45 | # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c |
46 | # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c | 46 | # ADD CPP /nologo /Gr /MT /W4 /WX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c |
47 | # SUBTRACT CPP /YX | 47 | # SUBTRACT CPP /YX |
48 | # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | 48 | # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 |
49 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | 49 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 |
@@ -71,7 +71,7 @@ LINK32=link.exe | |||
71 | # PROP Ignore_Export_Lib 0 | 71 | # PROP Ignore_Export_Lib 0 |
72 | # PROP Target_Dir "" | 72 | # PROP Target_Dir "" |
73 | # 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 | 73 | # 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 |
74 | # 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 | 74 | # ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c |
75 | # SUBTRACT CPP /YX | 75 | # SUBTRACT CPP /YX |
76 | # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 | 76 | # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 |
77 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 | 77 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 |
@@ -128,6 +128,10 @@ SOURCE=..\..\Compiler.h | |||
128 | # End Source File | 128 | # End Source File |
129 | # Begin Source File | 129 | # Begin Source File |
130 | 130 | ||
131 | SOURCE=..\..\CpuArch.c | ||
132 | # End Source File | ||
133 | # Begin Source File | ||
134 | |||
131 | SOURCE=..\..\CpuArch.h | 135 | SOURCE=..\..\CpuArch.h |
132 | # End Source File | 136 | # End Source File |
133 | # Begin Source File | 137 | # Begin Source File |
@@ -1,5 +1,5 @@ | |||
1 | /* Xz.h - Xz interface | 1 | /* Xz.h - Xz interface |
2 | 2024-01-26 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_XZ_H | 4 | #ifndef ZIP7_INC_XZ_H |
5 | #define ZIP7_INC_XZ_H | 5 | #define ZIP7_INC_XZ_H |
@@ -121,6 +121,7 @@ typedef struct | |||
121 | UInt64 startOffset; | 121 | UInt64 startOffset; |
122 | } CXzStream; | 122 | } CXzStream; |
123 | 123 | ||
124 | #define Xz_CONSTRUCT(p) { (p)->numBlocks = 0; (p)->blocks = NULL; (p)->flags = 0; } | ||
124 | void Xz_Construct(CXzStream *p); | 125 | void Xz_Construct(CXzStream *p); |
125 | void Xz_Free(CXzStream *p, ISzAllocPtr alloc); | 126 | void Xz_Free(CXzStream *p, ISzAllocPtr alloc); |
126 | 127 | ||
@@ -136,8 +137,13 @@ typedef struct | |||
136 | CXzStream *streams; | 137 | CXzStream *streams; |
137 | } CXzs; | 138 | } CXzs; |
138 | 139 | ||
140 | #define Xzs_CONSTRUCT(p) { (p)->num = 0; (p)->numAllocated = 0; (p)->streams = NULL; } | ||
139 | void Xzs_Construct(CXzs *p); | 141 | void Xzs_Construct(CXzs *p); |
140 | void Xzs_Free(CXzs *p, ISzAllocPtr alloc); | 142 | void Xzs_Free(CXzs *p, ISzAllocPtr alloc); |
143 | /* | ||
144 | Xzs_ReadBackward() must be called for empty CXzs object. | ||
145 | Xzs_ReadBackward() can return non empty object with (p->num != 0) even in case of error. | ||
146 | */ | ||
141 | SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc); | 147 | SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc); |
142 | 148 | ||
143 | UInt64 Xzs_GetNumBlocks(const CXzs *p); | 149 | UInt64 Xzs_GetNumBlocks(const CXzs *p); |
@@ -268,8 +274,8 @@ typedef struct | |||
268 | size_t outBufSize; | 274 | size_t outBufSize; |
269 | size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked | 275 | size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked |
270 | 276 | ||
271 | Byte shaDigest[SHA256_DIGEST_SIZE]; | 277 | UInt32 shaDigest32[SHA256_DIGEST_SIZE / 4]; |
272 | Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; | 278 | Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; // it must be aligned for 4-bytes |
273 | } CXzUnpacker; | 279 | } CXzUnpacker; |
274 | 280 | ||
275 | /* alloc : aligned for cache line allocation is better */ | 281 | /* alloc : aligned for cache line allocation is better */ |
diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c index 0c1fc2f..6eea4a3 100644 --- a/C/XzCrc64Opt.c +++ b/C/XzCrc64Opt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* XzCrc64Opt.c -- CRC64 calculation (optimized functions) | 1 | /* XzCrc64Opt.c -- CRC64 calculation (optimized functions) |
2 | 2023-12-08 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -235,7 +235,7 @@ CRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE) | |||
235 | v = Q32BE(1, w1) ^ Q32BE(0, w0); | 235 | v = Q32BE(1, w1) ^ Q32BE(0, w0); |
236 | v ^= Q32BE(3, d1) ^ Q32BE(2, d0); | 236 | v ^= Q32BE(3, d1) ^ Q32BE(2, d0); |
237 | #endif | 237 | #endif |
238 | #elif | 238 | #else |
239 | #error Stop_Compiling_Bad_CRC64_NUM_TABLES | 239 | #error Stop_Compiling_Bad_CRC64_NUM_TABLES |
240 | #endif | 240 | #endif |
241 | p += Z7_CRC64_NUM_TABLES_USE; | 241 | p += Z7_CRC64_NUM_TABLES_USE; |
@@ -1,5 +1,5 @@ | |||
1 | /* XzDec.c -- Xz Decode | 1 | /* XzDec.c -- Xz Decode |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -59,7 +59,7 @@ unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) | |||
59 | 59 | ||
60 | for (i = 0; i < limit;) | 60 | for (i = 0; i < limit;) |
61 | { | 61 | { |
62 | Byte b = p[i]; | 62 | const unsigned b = p[i]; |
63 | *value |= (UInt64)(b & 0x7F) << (7 * i++); | 63 | *value |= (UInt64)(b & 0x7F) << (7 * i++); |
64 | if ((b & 0x80) == 0) | 64 | if ((b & 0x80) == 0) |
65 | return (b == 0 && i != 1) ? 0 : i; | 65 | return (b == 0 && i != 1) ? 0 : i; |
@@ -796,11 +796,10 @@ SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) | |||
796 | 796 | ||
797 | static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) | 797 | static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) |
798 | { | 798 | { |
799 | return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) | 799 | return indexSize == (((UInt64)GetUi32a(buf + 4) + 1) << 2) |
800 | && GetUi32(buf) == CrcCalc(buf + 4, 6) | 800 | && GetUi32a(buf) == CrcCalc(buf + 4, 6) |
801 | && flags == GetBe16(buf + 8) | 801 | && flags == GetBe16a(buf + 8) |
802 | && buf[10] == XZ_FOOTER_SIG_0 | 802 | && GetUi16a(buf + 10) == (XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8)); |
803 | && buf[11] == XZ_FOOTER_SIG_1; | ||
804 | } | 803 | } |
805 | 804 | ||
806 | #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ | 805 | #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ |
@@ -1166,7 +1165,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | |||
1166 | p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); | 1165 | p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); |
1167 | p->indexPos = p->indexPreSize; | 1166 | p->indexPos = p->indexPreSize; |
1168 | p->indexSize += p->indexPreSize; | 1167 | p->indexSize += p->indexPreSize; |
1169 | Sha256_Final(&p->sha, p->shaDigest); | 1168 | Sha256_Final(&p->sha, (Byte *)(void *)p->shaDigest32); |
1170 | Sha256_Init(&p->sha); | 1169 | Sha256_Init(&p->sha); |
1171 | p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); | 1170 | p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); |
1172 | p->state = XZ_STATE_STREAM_INDEX; | 1171 | p->state = XZ_STATE_STREAM_INDEX; |
@@ -1241,10 +1240,10 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | |||
1241 | break; | 1240 | break; |
1242 | } | 1241 | } |
1243 | { | 1242 | { |
1244 | Byte digest[XZ_CHECK_SIZE_MAX]; | 1243 | UInt32 digest32[XZ_CHECK_SIZE_MAX / 4]; |
1245 | p->state = XZ_STATE_BLOCK_HEADER; | 1244 | p->state = XZ_STATE_BLOCK_HEADER; |
1246 | p->pos = 0; | 1245 | p->pos = 0; |
1247 | if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) | 1246 | if (XzCheck_Final(&p->check, (void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0) |
1248 | return SZ_ERROR_CRC; | 1247 | return SZ_ERROR_CRC; |
1249 | if (p->decodeOnlyOneBlock) | 1248 | if (p->decodeOnlyOneBlock) |
1250 | { | 1249 | { |
@@ -1289,12 +1288,12 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | |||
1289 | } | 1288 | } |
1290 | else | 1289 | else |
1291 | { | 1290 | { |
1292 | Byte digest[SHA256_DIGEST_SIZE]; | 1291 | UInt32 digest32[SHA256_DIGEST_SIZE / 4]; |
1293 | p->state = XZ_STATE_STREAM_INDEX_CRC; | 1292 | p->state = XZ_STATE_STREAM_INDEX_CRC; |
1294 | p->indexSize += 4; | 1293 | p->indexSize += 4; |
1295 | p->pos = 0; | 1294 | p->pos = 0; |
1296 | Sha256_Final(&p->sha, digest); | 1295 | Sha256_Final(&p->sha, (void *)digest32); |
1297 | if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) | 1296 | if (memcmp(digest32, p->shaDigest32, SHA256_DIGEST_SIZE) != 0) |
1298 | return SZ_ERROR_CRC; | 1297 | return SZ_ERROR_CRC; |
1299 | } | 1298 | } |
1300 | } | 1299 | } |
@@ -1313,7 +1312,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | |||
1313 | const Byte *ptr = p->buf; | 1312 | const Byte *ptr = p->buf; |
1314 | p->state = XZ_STATE_STREAM_FOOTER; | 1313 | p->state = XZ_STATE_STREAM_FOOTER; |
1315 | p->pos = 0; | 1314 | p->pos = 0; |
1316 | if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr)) | 1315 | if (CRC_GET_DIGEST(p->crc) != GetUi32a(ptr)) |
1317 | return SZ_ERROR_CRC; | 1316 | return SZ_ERROR_CRC; |
1318 | } | 1317 | } |
1319 | break; | 1318 | break; |
@@ -1343,7 +1342,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | |||
1343 | { | 1342 | { |
1344 | if (*src != 0) | 1343 | if (*src != 0) |
1345 | { | 1344 | { |
1346 | if (((UInt32)p->padSize & 3) != 0) | 1345 | if ((unsigned)p->padSize & 3) |
1347 | return SZ_ERROR_NO_ARCHIVE; | 1346 | return SZ_ERROR_NO_ARCHIVE; |
1348 | p->pos = 0; | 1347 | p->pos = 0; |
1349 | p->state = XZ_STATE_STREAM_HEADER; | 1348 | p->state = XZ_STATE_STREAM_HEADER; |
@@ -1,5 +1,5 @@ | |||
1 | /* XzEnc.c -- Xz Encode | 1 | /* XzEnc.c -- Xz Encode |
2 | 2024-03-01 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
@@ -411,6 +411,7 @@ static SRes SeqInFilter_Read(ISeqInStreamPtr pp, void *data, size_t *size) | |||
411 | } | 411 | } |
412 | } | 412 | } |
413 | 413 | ||
414 | Z7_FORCE_INLINE | ||
414 | static void SeqInFilter_Construct(CSeqInFilter *p) | 415 | static void SeqInFilter_Construct(CSeqInFilter *p) |
415 | { | 416 | { |
416 | p->buf = NULL; | 417 | p->buf = NULL; |
@@ -418,6 +419,7 @@ static void SeqInFilter_Construct(CSeqInFilter *p) | |||
418 | p->vt.Read = SeqInFilter_Read; | 419 | p->vt.Read = SeqInFilter_Read; |
419 | } | 420 | } |
420 | 421 | ||
422 | Z7_FORCE_INLINE | ||
421 | static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) | 423 | static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) |
422 | { | 424 | { |
423 | if (p->StateCoder.p) | 425 | if (p->StateCoder.p) |
@@ -507,6 +509,7 @@ void XzFilterProps_Init(CXzFilterProps *p) | |||
507 | void XzProps_Init(CXzProps *p) | 509 | void XzProps_Init(CXzProps *p) |
508 | { | 510 | { |
509 | p->checkId = XZ_CHECK_CRC32; | 511 | p->checkId = XZ_CHECK_CRC32; |
512 | p->numThreadGroups = 0; | ||
510 | p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO; | 513 | p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO; |
511 | p->numBlockThreads_Reduced = -1; | 514 | p->numBlockThreads_Reduced = -1; |
512 | p->numBlockThreads_Max = -1; | 515 | p->numBlockThreads_Max = -1; |
@@ -689,6 +692,7 @@ typedef struct | |||
689 | } CLzma2WithFilters; | 692 | } CLzma2WithFilters; |
690 | 693 | ||
691 | 694 | ||
695 | Z7_FORCE_INLINE | ||
692 | static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) | 696 | static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) |
693 | { | 697 | { |
694 | p->lzma2 = NULL; | 698 | p->lzma2 = NULL; |
@@ -712,6 +716,7 @@ static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISz | |||
712 | } | 716 | } |
713 | 717 | ||
714 | 718 | ||
719 | Z7_FORCE_INLINE | ||
715 | static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) | 720 | static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) |
716 | { | 721 | { |
717 | #ifdef USE_SUBBLOCK | 722 | #ifdef USE_SUBBLOCK |
@@ -1236,6 +1241,7 @@ SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr in | |||
1236 | } | 1241 | } |
1237 | 1242 | ||
1238 | p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max; | 1243 | p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max; |
1244 | p->mtCoder.numThreadGroups = props->numThreadGroups; | ||
1239 | p->mtCoder.expectedDataSize = p->expectedDataSize; | 1245 | p->mtCoder.expectedDataSize = p->expectedDataSize; |
1240 | 1246 | ||
1241 | RINOK(MtCoder_Code(&p->mtCoder)) | 1247 | RINOK(MtCoder_Code(&p->mtCoder)) |
@@ -1,5 +1,5 @@ | |||
1 | /* XzEnc.h -- Xz Encode | 1 | /* XzEnc.h -- Xz Encode |
2 | 2023-04-13 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #ifndef ZIP7_INC_XZ_ENC_H | 4 | #ifndef ZIP7_INC_XZ_ENC_H |
5 | #define ZIP7_INC_XZ_ENC_H | 5 | #define ZIP7_INC_XZ_ENC_H |
@@ -31,6 +31,7 @@ typedef struct | |||
31 | CLzma2EncProps lzma2Props; | 31 | CLzma2EncProps lzma2Props; |
32 | CXzFilterProps filterProps; | 32 | CXzFilterProps filterProps; |
33 | unsigned checkId; | 33 | unsigned checkId; |
34 | unsigned numThreadGroups; // 0 : no groups | ||
34 | UInt64 blockSize; | 35 | UInt64 blockSize; |
35 | int numBlockThreads_Reduced; | 36 | int numBlockThreads_Reduced; |
36 | int numBlockThreads_Max; | 37 | int numBlockThreads_Max; |
@@ -1,38 +1,39 @@ | |||
1 | /* XzIn.c - Xz input | 1 | /* XzIn.c - Xz input |
2 | 2023-09-07 : Igor Pavlov : Public domain */ | 2 | : Igor Pavlov : Public domain */ |
3 | 3 | ||
4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
5 | 5 | ||
6 | #include <string.h> | 6 | #include <string.h> |
7 | 7 | ||
8 | #include "7zCrc.h" | 8 | #include "7zCrc.h" |
9 | #include "CpuArch.h" | ||
10 | #include "Xz.h" | 9 | #include "Xz.h" |
10 | #include "CpuArch.h" | ||
11 | 11 | ||
12 | /* | 12 | #define XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(p) \ |
13 | #define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0) | 13 | (GetUi16a((const Byte *)(const void *)(p) + 10) == \ |
14 | */ | 14 | (XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8))) |
15 | #define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1) | ||
16 | |||
17 | 15 | ||
18 | SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream) | 16 | SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream) |
19 | { | 17 | { |
20 | Byte sig[XZ_STREAM_HEADER_SIZE]; | 18 | UInt32 data32[XZ_STREAM_HEADER_SIZE / 4]; |
21 | size_t processedSize = XZ_STREAM_HEADER_SIZE; | 19 | size_t processedSize = XZ_STREAM_HEADER_SIZE; |
22 | RINOK(SeqInStream_ReadMax(inStream, sig, &processedSize)) | 20 | RINOK(SeqInStream_ReadMax(inStream, data32, &processedSize)) |
23 | if (processedSize != XZ_STREAM_HEADER_SIZE | 21 | if (processedSize != XZ_STREAM_HEADER_SIZE |
24 | || memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) | 22 | || memcmp(data32, XZ_SIG, XZ_SIG_SIZE) != 0) |
25 | return SZ_ERROR_NO_ARCHIVE; | 23 | return SZ_ERROR_NO_ARCHIVE; |
26 | return Xz_ParseHeader(p, sig); | 24 | return Xz_ParseHeader(p, (const Byte *)(const void *)data32); |
27 | } | 25 | } |
28 | 26 | ||
29 | #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ | 27 | #define READ_VARINT_AND_CHECK(buf, size, res) \ |
30 | { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ | 28 | { const unsigned s = Xz_ReadVarInt(buf, size, res); \ |
31 | if (s == 0) return SZ_ERROR_ARCHIVE; \ | 29 | if (s == 0) return SZ_ERROR_ARCHIVE; \ |
32 | pos += s; } | 30 | size -= s; \ |
31 | buf += s; \ | ||
32 | } | ||
33 | 33 | ||
34 | SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes) | 34 | SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes) |
35 | { | 35 | { |
36 | MY_ALIGN(4) | ||
36 | Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; | 37 | Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; |
37 | unsigned headerSize; | 38 | unsigned headerSize; |
38 | *headerSizeRes = 0; | 39 | *headerSizeRes = 0; |
@@ -57,8 +58,12 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, | |||
57 | return XzBlock_Parse(p, header); | 58 | return XzBlock_Parse(p, header); |
58 | } | 59 | } |
59 | 60 | ||
61 | |||
60 | #define ADD_SIZE_CHECK(size, val) \ | 62 | #define ADD_SIZE_CHECK(size, val) \ |
61 | { const UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } | 63 | { const UInt64 newSize = size + (val); \ |
64 | if (newSize < size) return XZ_SIZE_OVERFLOW; \ | ||
65 | size = newSize; \ | ||
66 | } | ||
62 | 67 | ||
63 | UInt64 Xz_GetUnpackSize(const CXzStream *p) | 68 | UInt64 Xz_GetUnpackSize(const CXzStream *p) |
64 | { | 69 | { |
@@ -82,76 +87,85 @@ UInt64 Xz_GetPackSize(const CXzStream *p) | |||
82 | return size; | 87 | return size; |
83 | } | 88 | } |
84 | 89 | ||
85 | /* | ||
86 | SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStreamPtr inStream) | ||
87 | { | ||
88 | return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); | ||
89 | } | ||
90 | */ | ||
91 | 90 | ||
92 | static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) | 91 | // input; |
92 | // CXzStream (p) is empty object. | ||
93 | // size != 0 | ||
94 | // (size & 3) == 0 | ||
95 | // (buf) is aligned for at least 4 bytes. | ||
96 | // output: | ||
97 | // p->numBlocks is number of allocated items in p->blocks | ||
98 | // p->blocks[*] values must be ignored, if function returns error. | ||
99 | static SRes Xz_ParseIndex(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) | ||
93 | { | 100 | { |
94 | size_t numBlocks, pos = 1; | 101 | size_t numBlocks; |
95 | UInt32 crc; | ||
96 | |||
97 | if (size < 5 || buf[0] != 0) | 102 | if (size < 5 || buf[0] != 0) |
98 | return SZ_ERROR_ARCHIVE; | 103 | return SZ_ERROR_ARCHIVE; |
99 | |||
100 | size -= 4; | 104 | size -= 4; |
101 | crc = CrcCalc(buf, size); | 105 | { |
102 | if (crc != GetUi32(buf + size)) | 106 | const UInt32 crc = CrcCalc(buf, size); |
103 | return SZ_ERROR_ARCHIVE; | 107 | if (crc != GetUi32a(buf + size)) |
104 | 108 | return SZ_ERROR_ARCHIVE; | |
109 | } | ||
110 | buf++; | ||
111 | size--; | ||
105 | { | 112 | { |
106 | UInt64 numBlocks64; | 113 | UInt64 numBlocks64; |
107 | READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64) | 114 | READ_VARINT_AND_CHECK(buf, size, &numBlocks64) |
108 | numBlocks = (size_t)numBlocks64; | 115 | // (numBlocks64) is 63-bit value, so we can calculate (numBlocks64 * 2): |
109 | if (numBlocks != numBlocks64 || numBlocks * 2 > size) | 116 | if (numBlocks64 * 2 > size) |
110 | return SZ_ERROR_ARCHIVE; | 117 | return SZ_ERROR_ARCHIVE; |
118 | if (numBlocks64 >= ((size_t)1 << (sizeof(size_t) * 8 - 1)) / sizeof(CXzBlockSizes)) | ||
119 | return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE | ||
120 | numBlocks = (size_t)numBlocks64; | ||
111 | } | 121 | } |
112 | 122 | // Xz_Free(p, alloc); // it's optional, because (p) is empty already | |
113 | Xz_Free(p, alloc); | 123 | if (numBlocks) |
114 | if (numBlocks != 0) | ||
115 | { | 124 | { |
116 | size_t i; | 125 | CXzBlockSizes *blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); |
117 | p->numBlocks = numBlocks; | 126 | if (!blocks) |
118 | p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); | ||
119 | if (!p->blocks) | ||
120 | return SZ_ERROR_MEM; | 127 | return SZ_ERROR_MEM; |
121 | for (i = 0; i < numBlocks; i++) | 128 | p->blocks = blocks; |
129 | p->numBlocks = numBlocks; | ||
130 | // the caller will call Xz_Free() in case of error | ||
131 | do | ||
122 | { | 132 | { |
123 | CXzBlockSizes *block = &p->blocks[i]; | 133 | READ_VARINT_AND_CHECK(buf, size, &blocks->totalSize) |
124 | READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize) | 134 | READ_VARINT_AND_CHECK(buf, size, &blocks->unpackSize) |
125 | READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize) | 135 | if (blocks->totalSize == 0) |
126 | if (block->totalSize == 0) | ||
127 | return SZ_ERROR_ARCHIVE; | 136 | return SZ_ERROR_ARCHIVE; |
137 | blocks++; | ||
128 | } | 138 | } |
139 | while (--numBlocks); | ||
129 | } | 140 | } |
130 | while ((pos & 3) != 0) | 141 | if (size >= 4) |
131 | if (buf[pos++] != 0) | 142 | return SZ_ERROR_ARCHIVE; |
143 | while (size) | ||
144 | if (buf[--size]) | ||
132 | return SZ_ERROR_ARCHIVE; | 145 | return SZ_ERROR_ARCHIVE; |
133 | return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; | 146 | return SZ_OK; |
134 | } | 147 | } |
135 | 148 | ||
149 | |||
150 | /* | ||
136 | static SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc) | 151 | static SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc) |
137 | { | 152 | { |
138 | SRes res; | 153 | SRes res; |
139 | size_t size; | 154 | size_t size; |
140 | Byte *buf; | 155 | Byte *buf; |
141 | if (indexSize > ((UInt32)1 << 31)) | 156 | if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1))) |
142 | return SZ_ERROR_UNSUPPORTED; | 157 | return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE |
143 | size = (size_t)indexSize; | 158 | size = (size_t)indexSize; |
144 | if (size != indexSize) | ||
145 | return SZ_ERROR_UNSUPPORTED; | ||
146 | buf = (Byte *)ISzAlloc_Alloc(alloc, size); | 159 | buf = (Byte *)ISzAlloc_Alloc(alloc, size); |
147 | if (!buf) | 160 | if (!buf) |
148 | return SZ_ERROR_MEM; | 161 | return SZ_ERROR_MEM; |
149 | res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); | 162 | res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); |
150 | if (res == SZ_OK) | 163 | if (res == SZ_OK) |
151 | res = Xz_ReadIndex2(p, buf, size, alloc); | 164 | res = Xz_ParseIndex(p, buf, size, alloc); |
152 | ISzAlloc_Free(alloc, buf); | 165 | ISzAlloc_Free(alloc, buf); |
153 | return res; | 166 | return res; |
154 | } | 167 | } |
168 | */ | ||
155 | 169 | ||
156 | static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size) | 170 | static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size) |
157 | { | 171 | { |
@@ -160,84 +174,102 @@ static SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, | |||
160 | /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ | 174 | /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ |
161 | } | 175 | } |
162 | 176 | ||
177 | |||
178 | /* | ||
179 | in: | ||
180 | (*startOffset) is position in (stream) where xz_stream must be finished. | ||
181 | out: | ||
182 | if returns SZ_OK, then (*startOffset) is position in stream that shows start of xz_stream. | ||
183 | */ | ||
163 | static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc) | 184 | static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc) |
164 | { | 185 | { |
165 | UInt64 indexSize; | 186 | #define TEMP_BUF_SIZE (1 << 10) |
166 | Byte buf[XZ_STREAM_FOOTER_SIZE]; | 187 | UInt32 buf32[TEMP_BUF_SIZE / 4]; |
167 | UInt64 pos = (UInt64)*startOffset; | 188 | UInt64 pos = (UInt64)*startOffset; |
168 | 189 | ||
169 | if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) | 190 | if ((pos & 3) || pos < XZ_STREAM_FOOTER_SIZE) |
170 | return SZ_ERROR_NO_ARCHIVE; | 191 | return SZ_ERROR_NO_ARCHIVE; |
171 | |||
172 | pos -= XZ_STREAM_FOOTER_SIZE; | 192 | pos -= XZ_STREAM_FOOTER_SIZE; |
173 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) | 193 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE)) |
174 | 194 | ||
175 | if (!XZ_FOOTER_SIG_CHECK(buf + 10)) | 195 | if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32)) |
176 | { | 196 | { |
177 | UInt32 total = 0; | ||
178 | pos += XZ_STREAM_FOOTER_SIZE; | 197 | pos += XZ_STREAM_FOOTER_SIZE; |
179 | |||
180 | for (;;) | 198 | for (;;) |
181 | { | 199 | { |
182 | size_t i; | 200 | // pos != 0 |
183 | #define TEMP_BUF_SIZE (1 << 10) | 201 | // (pos & 3) == 0 |
184 | Byte temp[TEMP_BUF_SIZE]; | 202 | size_t i = pos >= TEMP_BUF_SIZE ? TEMP_BUF_SIZE : (size_t)pos; |
185 | |||
186 | i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; | ||
187 | pos -= i; | 203 | pos -= i; |
188 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)) | 204 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, i)) |
189 | total += (UInt32)i; | 205 | i /= 4; |
190 | for (; i != 0; i--) | 206 | do |
191 | if (temp[i - 1] != 0) | 207 | if (buf32[i - 1] != 0) |
192 | break; | 208 | break; |
193 | if (i != 0) | 209 | while (--i); |
194 | { | 210 | |
195 | if ((i & 3) != 0) | 211 | pos += i * 4; |
196 | return SZ_ERROR_NO_ARCHIVE; | 212 | #define XZ_STREAM_BACKWARD_READING_PAD_MAX (1 << 16) |
197 | pos += i; | 213 | // here we don't support rare case with big padding for xz stream. |
198 | break; | 214 | // so we have padding limit for backward reading. |
199 | } | 215 | if ((UInt64)*startOffset - pos > XZ_STREAM_BACKWARD_READING_PAD_MAX) |
200 | if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) | ||
201 | return SZ_ERROR_NO_ARCHIVE; | 216 | return SZ_ERROR_NO_ARCHIVE; |
217 | if (i) | ||
218 | break; | ||
202 | } | 219 | } |
203 | 220 | // we try to open xz stream after skipping zero padding. | |
221 | // ((UInt64)*startOffset == pos) is possible here! | ||
204 | if (pos < XZ_STREAM_FOOTER_SIZE) | 222 | if (pos < XZ_STREAM_FOOTER_SIZE) |
205 | return SZ_ERROR_NO_ARCHIVE; | 223 | return SZ_ERROR_NO_ARCHIVE; |
206 | pos -= XZ_STREAM_FOOTER_SIZE; | 224 | pos -= XZ_STREAM_FOOTER_SIZE; |
207 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)) | 225 | RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE)) |
208 | if (!XZ_FOOTER_SIG_CHECK(buf + 10)) | 226 | if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32)) |
209 | return SZ_ERROR_NO_ARCHIVE; | 227 | return SZ_ERROR_NO_ARCHIVE; |
210 | } | 228 | } |
211 | 229 | ||
212 | p->flags = (CXzStreamFlags)GetBe16(buf + 8); | 230 | p->flags = (CXzStreamFlags)GetBe16a(buf32 + 2); |
213 | |||
214 | if (!XzFlags_IsSupported(p->flags)) | 231 | if (!XzFlags_IsSupported(p->flags)) |
215 | return SZ_ERROR_UNSUPPORTED; | 232 | return SZ_ERROR_UNSUPPORTED; |
216 | |||
217 | { | 233 | { |
218 | /* to eliminate GCC 6.3 warning: | 234 | /* to eliminate GCC 6.3 warning: |
219 | dereferencing type-punned pointer will break strict-aliasing rules */ | 235 | dereferencing type-punned pointer will break strict-aliasing rules */ |
220 | const Byte *buf_ptr = buf; | 236 | const UInt32 *buf_ptr = buf32; |
221 | if (GetUi32(buf_ptr) != CrcCalc(buf + 4, 6)) | 237 | if (GetUi32a(buf_ptr) != CrcCalc(buf32 + 1, 6)) |
222 | return SZ_ERROR_ARCHIVE; | 238 | return SZ_ERROR_ARCHIVE; |
223 | } | 239 | } |
224 | |||
225 | indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; | ||
226 | |||
227 | if (pos < indexSize) | ||
228 | return SZ_ERROR_ARCHIVE; | ||
229 | |||
230 | pos -= indexSize; | ||
231 | RINOK(LookInStream_SeekTo(stream, pos)) | ||
232 | RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)) | ||
233 | |||
234 | { | 240 | { |
235 | UInt64 totalSize = Xz_GetPackSize(p); | 241 | const UInt64 indexSize = ((UInt64)GetUi32a(buf32 + 1) + 1) << 2; |
236 | if (totalSize == XZ_SIZE_OVERFLOW | 242 | if (pos < indexSize) |
237 | || totalSize >= ((UInt64)1 << 63) | ||
238 | || pos < totalSize + XZ_STREAM_HEADER_SIZE) | ||
239 | return SZ_ERROR_ARCHIVE; | 243 | return SZ_ERROR_ARCHIVE; |
240 | pos -= (totalSize + XZ_STREAM_HEADER_SIZE); | 244 | pos -= indexSize; |
245 | // v25.00: relaxed indexSize check. We allow big index table. | ||
246 | // if (indexSize > ((UInt32)1 << 31)) | ||
247 | if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1))) | ||
248 | return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE | ||
249 | RINOK(LookInStream_SeekTo(stream, pos)) | ||
250 | // RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)) | ||
251 | { | ||
252 | SRes res; | ||
253 | const size_t size = (size_t)indexSize; | ||
254 | // if (size != indexSize) return SZ_ERROR_UNSUPPORTED; | ||
255 | Byte *buf = (Byte *)ISzAlloc_Alloc(alloc, size); | ||
256 | if (!buf) | ||
257 | return SZ_ERROR_MEM; | ||
258 | res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); | ||
259 | if (res == SZ_OK) | ||
260 | res = Xz_ParseIndex(p, buf, size, alloc); | ||
261 | ISzAlloc_Free(alloc, buf); | ||
262 | RINOK(res) | ||
263 | } | ||
264 | } | ||
265 | { | ||
266 | UInt64 total = Xz_GetPackSize(p); | ||
267 | if (total == XZ_SIZE_OVERFLOW || total >= ((UInt64)1 << 63)) | ||
268 | return SZ_ERROR_ARCHIVE; | ||
269 | total += XZ_STREAM_HEADER_SIZE; | ||
270 | if (pos < total) | ||
271 | return SZ_ERROR_ARCHIVE; | ||
272 | pos -= total; | ||
241 | RINOK(LookInStream_SeekTo(stream, pos)) | 273 | RINOK(LookInStream_SeekTo(stream, pos)) |
242 | *startOffset = (Int64)pos; | 274 | *startOffset = (Int64)pos; |
243 | } | 275 | } |
@@ -246,7 +278,6 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startO | |||
246 | CSecToRead secToRead; | 278 | CSecToRead secToRead; |
247 | SecToRead_CreateVTable(&secToRead); | 279 | SecToRead_CreateVTable(&secToRead); |
248 | secToRead.realStream = stream; | 280 | secToRead.realStream = stream; |
249 | |||
250 | RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)) | 281 | RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)) |
251 | return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; | 282 | return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; |
252 | } | 283 | } |
@@ -257,8 +288,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startO | |||
257 | 288 | ||
258 | void Xzs_Construct(CXzs *p) | 289 | void Xzs_Construct(CXzs *p) |
259 | { | 290 | { |
260 | p->num = p->numAllocated = 0; | 291 | Xzs_CONSTRUCT(p) |
261 | p->streams = 0; | ||
262 | } | 292 | } |
263 | 293 | ||
264 | void Xzs_Free(CXzs *p, ISzAllocPtr alloc) | 294 | void Xzs_Free(CXzs *p, ISzAllocPtr alloc) |
@@ -268,7 +298,7 @@ void Xzs_Free(CXzs *p, ISzAllocPtr alloc) | |||
268 | Xz_Free(&p->streams[i], alloc); | 298 | Xz_Free(&p->streams[i], alloc); |
269 | ISzAlloc_Free(alloc, p->streams); | 299 | ISzAlloc_Free(alloc, p->streams); |
270 | p->num = p->numAllocated = 0; | 300 | p->num = p->numAllocated = 0; |
271 | p->streams = 0; | 301 | p->streams = NULL; |
272 | } | 302 | } |
273 | 303 | ||
274 | UInt64 Xzs_GetNumBlocks(const CXzs *p) | 304 | UInt64 Xzs_GetNumBlocks(const CXzs *p) |
@@ -307,34 +337,49 @@ UInt64 Xzs_GetPackSize(const CXzs *p) | |||
307 | SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc) | 337 | SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc) |
308 | { | 338 | { |
309 | Int64 endOffset = 0; | 339 | Int64 endOffset = 0; |
340 | // it's supposed that CXzs object is empty here. | ||
341 | // if CXzs object is not empty, it will add new streams to that non-empty object. | ||
342 | // Xzs_Free(p, alloc); // it's optional call to empty CXzs object. | ||
310 | RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)) | 343 | RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)) |
311 | *startOffset = endOffset; | 344 | *startOffset = endOffset; |
312 | for (;;) | 345 | for (;;) |
313 | { | 346 | { |
314 | CXzStream st; | 347 | CXzStream st; |
315 | SRes res; | 348 | SRes res; |
316 | Xz_Construct(&st); | 349 | Xz_CONSTRUCT(&st) |
317 | res = Xz_ReadBackward(&st, stream, startOffset, alloc); | 350 | res = Xz_ReadBackward(&st, stream, startOffset, alloc); |
351 | // if (res == SZ_OK), then (*startOffset) is start offset of new stream if | ||
352 | // if (res != SZ_OK), then (*startOffset) is unchend or it's expected start offset of stream with error | ||
318 | st.startOffset = (UInt64)*startOffset; | 353 | st.startOffset = (UInt64)*startOffset; |
319 | RINOK(res) | 354 | // we must store (st) object to array, or we must free (st) local object. |
355 | if (res != SZ_OK) | ||
356 | { | ||
357 | Xz_Free(&st, alloc); | ||
358 | return res; | ||
359 | } | ||
320 | if (p->num == p->numAllocated) | 360 | if (p->num == p->numAllocated) |
321 | { | 361 | { |
322 | const size_t newNum = p->num + p->num / 4 + 1; | 362 | const size_t newNum = p->num + p->num / 4 + 1; |
323 | void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); | 363 | void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); |
324 | if (!data) | 364 | if (!data) |
365 | { | ||
366 | Xz_Free(&st, alloc); | ||
325 | return SZ_ERROR_MEM; | 367 | return SZ_ERROR_MEM; |
368 | } | ||
326 | p->numAllocated = newNum; | 369 | p->numAllocated = newNum; |
327 | if (p->num != 0) | 370 | if (p->num != 0) |
328 | memcpy(data, p->streams, p->num * sizeof(CXzStream)); | 371 | memcpy(data, p->streams, p->num * sizeof(CXzStream)); |
329 | ISzAlloc_Free(alloc, p->streams); | 372 | ISzAlloc_Free(alloc, p->streams); |
330 | p->streams = (CXzStream *)data; | 373 | p->streams = (CXzStream *)data; |
331 | } | 374 | } |
375 | // we use direct copying of raw data from local variable (st) to object in array. | ||
376 | // so we don't need to call Xz_Free(&st, alloc) after copying and after p->num++ | ||
332 | p->streams[p->num++] = st; | 377 | p->streams[p->num++] = st; |
333 | if (*startOffset == 0) | 378 | if (*startOffset == 0) |
334 | break; | 379 | return SZ_OK; |
335 | RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset)) | 380 | // seek operation is optional: |
381 | // RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset)) | ||
336 | if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK) | 382 | if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK) |
337 | return SZ_ERROR_PROGRESS; | 383 | return SZ_ERROR_PROGRESS; |
338 | } | 384 | } |
339 | return SZ_OK; | ||
340 | } | 385 | } |
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index 45c9ab3..12f1ef2 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak | |||
@@ -302,6 +302,8 @@ $O/ListFileUtils.o: ../../../Common/ListFileUtils.cpp | |||
302 | $(CXX) $(CXXFLAGS) $< | 302 | $(CXX) $(CXXFLAGS) $< |
303 | $O/LzFindPrepare.o: ../../../Common/LzFindPrepare.cpp | 303 | $O/LzFindPrepare.o: ../../../Common/LzFindPrepare.cpp |
304 | $(CXX) $(CXXFLAGS) $< | 304 | $(CXX) $(CXXFLAGS) $< |
305 | $O/Md5Reg.o: ../../../Common/Md5Reg.cpp | ||
306 | $(CXX) $(CXXFLAGS) $< | ||
305 | $O/MyMap.o: ../../../Common/MyMap.cpp | 307 | $O/MyMap.o: ../../../Common/MyMap.cpp |
306 | $(CXX) $(CXXFLAGS) $< | 308 | $(CXX) $(CXXFLAGS) $< |
307 | $O/MyString.o: ../../../Common/MyString.cpp | 309 | $O/MyString.o: ../../../Common/MyString.cpp |
@@ -326,6 +328,12 @@ $O/Sha256Prepare.o: ../../../Common/Sha256Prepare.cpp | |||
326 | $(CXX) $(CXXFLAGS) $< | 328 | $(CXX) $(CXXFLAGS) $< |
327 | $O/Sha256Reg.o: ../../../Common/Sha256Reg.cpp | 329 | $O/Sha256Reg.o: ../../../Common/Sha256Reg.cpp |
328 | $(CXX) $(CXXFLAGS) $< | 330 | $(CXX) $(CXXFLAGS) $< |
331 | $O/Sha3Reg.o: ../../../Common/Sha3Reg.cpp | ||
332 | $(CXX) $(CXXFLAGS) $< | ||
333 | $O/Sha512Prepare.o: ../../../Common/Sha512Prepare.cpp | ||
334 | $(CXX) $(CXXFLAGS) $< | ||
335 | $O/Sha512Reg.o: ../../../Common/Sha512Reg.cpp | ||
336 | $(CXX) $(CXXFLAGS) $< | ||
329 | $O/StdInStream.o: ../../../Common/StdInStream.cpp | 337 | $O/StdInStream.o: ../../../Common/StdInStream.cpp |
330 | $(CXX) $(CXXFLAGS) $< | 338 | $(CXX) $(CXXFLAGS) $< |
331 | $O/StdOutStream.o: ../../../Common/StdOutStream.cpp | 339 | $O/StdOutStream.o: ../../../Common/StdOutStream.cpp |
@@ -1207,6 +1215,8 @@ $O/Lzma2Enc.o: ../../../../C/Lzma2Enc.c | |||
1207 | $(CC) $(CFLAGS) $< | 1215 | $(CC) $(CFLAGS) $< |
1208 | $O/LzmaLib.o: ../../../../C/LzmaLib.c | 1216 | $O/LzmaLib.o: ../../../../C/LzmaLib.c |
1209 | $(CC) $(CFLAGS) $< | 1217 | $(CC) $(CFLAGS) $< |
1218 | $O/Md5.o: ../../../../C/Md5.c | ||
1219 | $(CC) $(CFLAGS) $< | ||
1210 | $O/MtCoder.o: ../../../../C/MtCoder.c | 1220 | $O/MtCoder.o: ../../../../C/MtCoder.c |
1211 | $(CC) $(CFLAGS) $< | 1221 | $(CC) $(CFLAGS) $< |
1212 | $O/MtDec.o: ../../../../C/MtDec.c | 1222 | $O/MtDec.o: ../../../../C/MtDec.c |
@@ -1229,7 +1239,11 @@ $O/Sha1.o: ../../../../C/Sha1.c | |||
1229 | $(CC) $(CFLAGS) $< | 1239 | $(CC) $(CFLAGS) $< |
1230 | $O/Sha256.o: ../../../../C/Sha256.c | 1240 | $O/Sha256.o: ../../../../C/Sha256.c |
1231 | $(CC) $(CFLAGS) $< | 1241 | $(CC) $(CFLAGS) $< |
1232 | $O/Sort.o: ../../../../C/Sort.c | 1242 | $O/Sha3.o: ../../../../C/Sha3.c |
1243 | $(CC) $(CFLAGS) $< | ||
1244 | $O/Sha512.o: ../../../../C/Sha512.c | ||
1245 | $(CC) $(CFLAGS) $< | ||
1246 | $O/Sha512Opt.o: ../../../../C/Sha512Opt.c | ||
1233 | $(CC) $(CFLAGS) $< | 1247 | $(CC) $(CFLAGS) $< |
1234 | $O/SwapBytes.o: ../../../../C/SwapBytes.c | 1248 | $O/SwapBytes.o: ../../../../C/SwapBytes.c |
1235 | $(CC) $(CFLAGS) $< | 1249 | $(CC) $(CFLAGS) $< |
@@ -1269,6 +1283,8 @@ $O/Sha1Opt.o: ../../../../Asm/x86/Sha1Opt.asm | |||
1269 | $(MY_ASM) $(AFLAGS) $< | 1283 | $(MY_ASM) $(AFLAGS) $< |
1270 | $O/Sha256Opt.o: ../../../../Asm/x86/Sha256Opt.asm | 1284 | $O/Sha256Opt.o: ../../../../Asm/x86/Sha256Opt.asm |
1271 | $(MY_ASM) $(AFLAGS) $< | 1285 | $(MY_ASM) $(AFLAGS) $< |
1286 | $O/Sort.o: ../../../../Asm/x86/Sort.asm | ||
1287 | $(MY_ASM) $(AFLAGS) $< | ||
1272 | 1288 | ||
1273 | ifndef USE_JWASM | 1289 | ifndef USE_JWASM |
1274 | USE_X86_ASM_AES=1 | 1290 | USE_X86_ASM_AES=1 |
@@ -1283,6 +1299,8 @@ $O/Sha1Opt.o: ../../../../C/Sha1Opt.c | |||
1283 | $(CC) $(CFLAGS) $< | 1299 | $(CC) $(CFLAGS) $< |
1284 | $O/Sha256Opt.o: ../../../../C/Sha256Opt.c | 1300 | $O/Sha256Opt.o: ../../../../C/Sha256Opt.c |
1285 | $(CC) $(CFLAGS) $< | 1301 | $(CC) $(CFLAGS) $< |
1302 | $O/Sort.o: ../../../../C/Sort.c | ||
1303 | $(CC) $(CFLAGS) $< | ||
1286 | endif | 1304 | endif |
1287 | 1305 | ||
1288 | 1306 | ||
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index 737722d..ecfee7c 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h | |||
@@ -59,6 +59,7 @@ struct CCompressionMethodMode | |||
59 | bool NumThreads_WasForced; | 59 | bool NumThreads_WasForced; |
60 | bool MultiThreadMixer; | 60 | bool MultiThreadMixer; |
61 | UInt32 NumThreads; | 61 | UInt32 NumThreads; |
62 | UInt32 NumThreadGroups; | ||
62 | #endif | 63 | #endif |
63 | 64 | ||
64 | UString Password; // _Wipe | 65 | UString Password; // _Wipe |
@@ -74,6 +75,7 @@ struct CCompressionMethodMode | |||
74 | , NumThreads_WasForced(false) | 75 | , NumThreads_WasForced(false) |
75 | , MultiThreadMixer(true) | 76 | , MultiThreadMixer(true) |
76 | , NumThreads(1) | 77 | , NumThreads(1) |
78 | , NumThreadGroups(0) | ||
77 | #endif | 79 | #endif |
78 | , MemoryUsageLimit((UInt64)1 << 30) | 80 | , MemoryUsageLimit((UInt64)1 << 30) |
79 | {} | 81 | {} |
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index ea5ea0f..c1c2b63 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp | |||
@@ -111,8 +111,8 @@ HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | const UInt64 kSolidBytes_Min = (1 << 24); | 114 | const UInt64 kSolidBytes_Min = 1 << 24; |
115 | const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); | 115 | const UInt64 kSolidBytes_Max = (UInt64)1 << 32; // for non-LZMA2 methods |
116 | 116 | ||
117 | bool needSolid = false; | 117 | bool needSolid = false; |
118 | 118 | ||
@@ -122,22 +122,24 @@ HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) | |||
122 | 122 | ||
123 | SetGlobalLevelTo(oneMethodInfo); | 123 | SetGlobalLevelTo(oneMethodInfo); |
124 | 124 | ||
125 | #ifndef Z7_ST | 125 | #ifndef Z7_ST |
126 | const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); | 126 | const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); |
127 | if (!numThreads_WasSpecifiedInMethod) | 127 | if (!numThreads_WasSpecifiedInMethod) |
128 | { | 128 | { |
129 | // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already | 129 | // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already |
130 | CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads); | 130 | CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads); |
131 | } | 131 | } |
132 | #endif | 132 | if (methodMode.NumThreadGroups > 1) |
133 | CMultiMethodProps::Set_Method_NumThreadGroups_IfNotFinded(oneMethodInfo, methodMode.NumThreadGroups); | ||
134 | #endif | ||
133 | 135 | ||
134 | CMethodFull &methodFull = methodMode.Methods.AddNew(); | 136 | CMethodFull &methodFull = methodMode.Methods.AddNew(); |
135 | RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)) | 137 | RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)) |
136 | 138 | ||
137 | #ifndef Z7_ST | 139 | #ifndef Z7_ST |
138 | methodFull.Set_NumThreads = true; | 140 | methodFull.Set_NumThreads = true; |
139 | methodFull.NumThreads = methodMode.NumThreads; | 141 | methodFull.NumThreads = methodMode.NumThreads; |
140 | #endif | 142 | #endif |
141 | 143 | ||
142 | if (methodFull.Id != k_Copy) | 144 | if (methodFull.Id != k_Copy) |
143 | needSolid = true; | 145 | needSolid = true; |
@@ -217,19 +219,18 @@ HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) | |||
217 | // here we get real chunkSize | 219 | // here we get real chunkSize |
218 | cs = oneMethodInfo.Get_Xz_BlockSize(); | 220 | cs = oneMethodInfo.Get_Xz_BlockSize(); |
219 | if (dicSize > cs) | 221 | if (dicSize > cs) |
220 | dicSize = cs; | 222 | dicSize = cs; |
221 | 223 | ||
222 | const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); | 224 | const UInt64 kSolidBytes_Lzma2_Max = (UInt64)1 << 34; |
223 | if (numSolidBytes > kSolidBytes_Lzma2_Max) | 225 | if (numSolidBytes > kSolidBytes_Lzma2_Max) |
224 | numSolidBytes = kSolidBytes_Lzma2_Max; | 226 | numSolidBytes = kSolidBytes_Lzma2_Max; |
225 | 227 | ||
226 | methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder | 228 | methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder |
227 | 229 | ||
228 | #ifndef Z7_ST | 230 | #ifndef Z7_ST |
229 | if (!numThreads_WasSpecifiedInMethod | 231 | if (!numThreads_WasSpecifiedInMethod |
230 | && !methodMode.NumThreads_WasForced | 232 | && !methodMode.NumThreads_WasForced |
231 | && methodMode.MemoryUsageLimit_WasSet | 233 | && methodMode.MemoryUsageLimit_WasSet) |
232 | ) | ||
233 | { | 234 | { |
234 | const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); | 235 | const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); |
235 | const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads; | 236 | const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads; |
@@ -273,14 +274,14 @@ HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) | |||
273 | { | 274 | { |
274 | numSolidBytes = (UInt64)dicSize << 7; | 275 | numSolidBytes = (UInt64)dicSize << 7; |
275 | if (numSolidBytes > kSolidBytes_Max) | 276 | if (numSolidBytes > kSolidBytes_Max) |
276 | numSolidBytes = kSolidBytes_Max; | 277 | numSolidBytes = kSolidBytes_Max; |
277 | } | 278 | } |
278 | 279 | ||
279 | if (_numSolidBytesDefined) | 280 | if (_numSolidBytesDefined) |
280 | continue; | 281 | continue; |
281 | 282 | ||
282 | if (numSolidBytes < kSolidBytes_Min) | 283 | if (numSolidBytes < kSolidBytes_Min) |
283 | numSolidBytes = kSolidBytes_Min; | 284 | numSolidBytes = kSolidBytes_Min; |
284 | _numSolidBytes = numSolidBytes; | 285 | _numSolidBytes = numSolidBytes; |
285 | _numSolidBytesDefined = true; | 286 | _numSolidBytesDefined = true; |
286 | } | 287 | } |
@@ -704,6 +705,9 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
704 | methodMode.NumThreads = numThreads; | 705 | methodMode.NumThreads = numThreads; |
705 | methodMode.NumThreads_WasForced = _numThreads_WasForced; | 706 | methodMode.NumThreads_WasForced = _numThreads_WasForced; |
706 | methodMode.MultiThreadMixer = _useMultiThreadMixer; | 707 | methodMode.MultiThreadMixer = _useMultiThreadMixer; |
708 | #ifdef _WIN32 | ||
709 | methodMode.NumThreadGroups = _numThreadGroups; // _change it | ||
710 | #endif | ||
707 | // headerMethod.NumThreads = 1; | 711 | // headerMethod.NumThreads = 1; |
708 | headerMethod.MultiThreadMixer = _useMultiThreadMixer; | 712 | headerMethod.MultiThreadMixer = _useMultiThreadMixer; |
709 | } | 713 | } |
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index 56d9b6e..e88d2fe 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp | |||
@@ -6,7 +6,6 @@ | |||
6 | 6 | ||
7 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
8 | 8 | ||
9 | #include "../../Windows/PropVariant.h" | ||
10 | #include "../../Windows/PropVariantUtils.h" | 9 | #include "../../Windows/PropVariantUtils.h" |
11 | 10 | ||
12 | #include "../Common/RegisterArc.h" | 11 | #include "../Common/RegisterArc.h" |
@@ -14,8 +13,7 @@ | |||
14 | 13 | ||
15 | #include "HandlerCont.h" | 14 | #include "HandlerCont.h" |
16 | 15 | ||
17 | // #define Get16(p) GetBe16(p) | 16 | #define Get32(p) GetBe32a(p) |
18 | #define Get32(p) GetBe32(p) | ||
19 | 17 | ||
20 | using namespace NWindows; | 18 | using namespace NWindows; |
21 | 19 | ||
@@ -41,8 +39,8 @@ static const CUInt32PCharPair k_Flags[] = | |||
41 | { 5, "WRITABLE" }, | 39 | { 5, "WRITABLE" }, |
42 | { 6, "OS_PIC_CODE" }, | 40 | { 6, "OS_PIC_CODE" }, |
43 | // { 7, "OS_SPECIFIC_2" }, // "Unused" | 41 | // { 7, "OS_SPECIFIC_2" }, // "Unused" |
44 | // { 8, "ChainCompatible" }, // "OS_SPECIFIC_1" | 42 | { 8, "ChainCompatible" }, // "OS_SPECIFIC_1" |
45 | // { 9, "RealDeviceDriver" }, | 43 | { 9, "RealDeviceDriver" }, |
46 | // { 10, "CanChainToNext" }, | 44 | // { 10, "CanChainToNext" }, |
47 | { 30, "MOUNTED_AT_STARTUP" }, | 45 | { 30, "MOUNTED_AT_STARTUP" }, |
48 | { 31, "STARTUP" } | 46 | { 31, "STARTUP" } |
@@ -74,16 +72,16 @@ struct CItem | |||
74 | bool Is_Valid_and_Allocated() const | 72 | bool Is_Valid_and_Allocated() const |
75 | { return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; } | 73 | { return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; } |
76 | 74 | ||
77 | bool Parse(const Byte *p, UInt32 &numBlocksInMap) | 75 | bool Parse(const UInt32 *p32, UInt32 &numBlocksInMap) |
78 | { | 76 | { |
79 | numBlocksInMap = Get32(p + 4); | 77 | if (GetUi32a(p32) != 0x4d50) // "PM" |
80 | StartBlock = Get32(p + 8); | ||
81 | NumBlocks = Get32(p + 0xc); | ||
82 | Flags = Get32(p + 0x58); | ||
83 | memcpy(Name, p + 0x10, k_Str_Size); | ||
84 | memcpy(Type, p + 0x30, k_Str_Size); | ||
85 | if (GetUi32(p) != 0x4d50) // "PM" | ||
86 | return false; | 78 | return false; |
79 | numBlocksInMap = Get32(p32 + 4 / 4); | ||
80 | StartBlock = Get32(p32 + 8 / 4); | ||
81 | NumBlocks = Get32(p32 + 0xc / 4); | ||
82 | Flags = Get32(p32 + 0x58 / 4); | ||
83 | memcpy(Name, p32 + 0x10 / 4, k_Str_Size); | ||
84 | memcpy(Type, p32 + 0x30 / 4, k_Str_Size); | ||
87 | /* | 85 | /* |
88 | DataStartBlock = Get32(p + 0x50); | 86 | DataStartBlock = Get32(p + 0x50); |
89 | NumDataBlocks = Get32(p + 0x54); | 87 | NumDataBlocks = Get32(p + 0x54); |
@@ -96,7 +94,7 @@ struct CItem | |||
96 | if (Get32(p + 0x70) != 0) | 94 | if (Get32(p + 0x70) != 0) |
97 | return false; | 95 | return false; |
98 | BootChecksum = Get32(p + 0x74); | 96 | BootChecksum = Get32(p + 0x74); |
99 | memcpy(Processor, p + 0x78, 16); | 97 | memcpy(Processor, p32 + 0x78 / 4, 16); |
100 | */ | 98 | */ |
101 | return true; | 99 | return true; |
102 | } | 100 | } |
@@ -109,9 +107,9 @@ Z7_class_CHandler_final: public CHandlerCont | |||
109 | 107 | ||
110 | CRecordVector<CItem> _items; | 108 | CRecordVector<CItem> _items; |
111 | unsigned _blockSizeLog; | 109 | unsigned _blockSizeLog; |
112 | UInt32 _numBlocks; | ||
113 | UInt64 _phySize; | ||
114 | bool _isArc; | 110 | bool _isArc; |
111 | // UInt32 _numBlocks; | ||
112 | UInt64 _phySize; | ||
115 | 113 | ||
116 | UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } | 114 | UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } |
117 | 115 | ||
@@ -132,11 +130,11 @@ API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size) | |||
132 | { | 130 | { |
133 | if (size < kSectorSize) | 131 | if (size < kSectorSize) |
134 | return k_IsArc_Res_NEED_MORE; | 132 | return k_IsArc_Res_NEED_MORE; |
135 | if (GetUi64(p + 8) != 0) | 133 | if (GetUi32(p + 12) != 0) |
136 | return k_IsArc_Res_NO; | 134 | return k_IsArc_Res_NO; |
137 | UInt32 v = GetUi32(p); // we read as little-endian | 135 | UInt32 v = GetUi32(p); // we read as little-endian |
138 | v ^= (kSig0 | (unsigned)kSig1 << 8); | 136 | v ^= kSig0 | (unsigned)kSig1 << 8; |
139 | if ((v & ~((UInt32)0xf << 17))) | 137 | if (v & ~((UInt32)0xf << 17)) |
140 | return k_IsArc_Res_NO; | 138 | return k_IsArc_Res_NO; |
141 | if ((0x116u >> (v >> 17)) & 1) | 139 | if ((0x116u >> (v >> 17)) & 1) |
142 | return k_IsArc_Res_YES; | 140 | return k_IsArc_Res_YES; |
@@ -149,55 +147,103 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
149 | COM_TRY_BEGIN | 147 | COM_TRY_BEGIN |
150 | Close(); | 148 | Close(); |
151 | 149 | ||
152 | Byte buf[kSectorSize]; | 150 | UInt32 buf32[kSectorSize / 4]; |
153 | unsigned numSectors_in_Cluster; | 151 | unsigned numPadSectors, blockSizeLog_from_Header; |
154 | { | 152 | { |
155 | RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) | 153 | // Driver Descriptor Map (DDM) |
156 | if (GetUi64(buf + 8) != 0) | 154 | RINOK(ReadStream_FALSE(stream, buf32, kSectorSize)) |
155 | // 8: UInt16 sbDevType : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso | ||
156 | // 10: UInt16 sbDevId : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso | ||
157 | // 12: UInt32 sbData : =0 | ||
158 | if (buf32[3] != 0) | ||
157 | return S_FALSE; | 159 | return S_FALSE; |
158 | UInt32 v = GetUi32(buf); // we read as little-endian | 160 | UInt32 v = GetUi32a(buf32); // we read as little-endian |
159 | v ^= (kSig0 | (unsigned)kSig1 << 8); | 161 | v ^= kSig0 | (unsigned)kSig1 << 8; |
160 | if ((v & ~((UInt32)0xf << 17))) | 162 | if (v & ~((UInt32)0xf << 17)) |
161 | return S_FALSE; | 163 | return S_FALSE; |
162 | v >>= 16; | 164 | v >>= 16; |
163 | if (v == 0) | 165 | if (v == 0) |
164 | return S_FALSE; | 166 | return S_FALSE; |
165 | if (v & (v - 1)) | 167 | if (v & (v - 1)) |
166 | return S_FALSE; | 168 | return S_FALSE; |
167 | const unsigned a = (0x30210u >> v) & 3; | 169 | // v == { 16,8,4,2 } : block size (x256 bytes) |
168 | // a = 0; // for debug | 170 | const unsigned a = |
169 | numSectors_in_Cluster = 1u << a; | 171 | #if 1 |
170 | _blockSizeLog = 9 + a; | 172 | (0x30210u >> v) & 3; |
173 | #else | ||
174 | 0; // for debug : hardcoded switch to 512-bytes mode | ||
175 | #endif | ||
176 | numPadSectors = (1u << a) - 1; | ||
177 | _blockSizeLog = blockSizeLog_from_Header = 9 + a; | ||
171 | } | 178 | } |
172 | 179 | ||
173 | UInt32 numBlocks = Get32(buf + 4); | 180 | /* |
174 | _numBlocks = numBlocks; | 181 | some APMs (that are ".iso" macOS installation files) contain |
175 | 182 | (blockSizeLog == 11) in DDM header, | |
183 | and contain 2 overlapping maps: | ||
184 | 1) map for 512-bytes-step | ||
185 | 2) map for 2048-bytes-step | ||
186 | 512-bytes-step map is correct. | ||
187 | 2048-bytes-step map can be incorrect in some cases. | ||
188 | |||
189 | macos 8 / OSX DP2 iso: | ||
190 | There is shared "hfs" item in both maps. | ||
191 | And correct (offset/size) values for "hfs" partition | ||
192 | can be calculated only in 512-bytes mode (ignoring blockSizeLog == 11). | ||
193 | But some records (Macintosh.Apple_Driver*_) | ||
194 | can be correct on both modes: 512-bytes mode / 2048-bytes-step. | ||
195 | |||
196 | macos 921 ppc / Apple Mac OS X 10.3.0 iso: | ||
197 | Both maps are correct. | ||
198 | If we use 512-bytes-step, each 4th item is (Apple_Void) with zero size. | ||
199 | And these zero size (Apple_Void) items will be first items in 2048-bytes-step map. | ||
200 | */ | ||
201 | |||
202 | // we define Z7_APM_SWITCH_TO_512_BYTES, because | ||
203 | // we want to support old MACOS APMs that contain correct value only | ||
204 | // for 512-bytes-step mode | ||
205 | #define Z7_APM_SWITCH_TO_512_BYTES | ||
206 | |||
207 | const UInt32 numBlocks_from_Header = Get32(buf32 + 1); | ||
208 | UInt32 numBlocks = 0; | ||
176 | { | 209 | { |
177 | for (unsigned k = numSectors_in_Cluster; --k != 0;) | 210 | for (unsigned k = 0; k < numPadSectors; k++) |
178 | { | 211 | { |
179 | RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) | 212 | RINOK(ReadStream_FALSE(stream, buf32, kSectorSize)) |
213 | #ifdef Z7_APM_SWITCH_TO_512_BYTES | ||
214 | if (k == 0) | ||
215 | { | ||
216 | if (GetUi32a(buf32) == 0x4d50 // "PM" | ||
217 | // && (Get32(buf32 + 0x58 / 4) & 1) // Flags::VALID | ||
218 | // some old APMs don't use VALID flag for Apple_partition_map item | ||
219 | && Get32(buf32 + 8 / 4) == 1) // StartBlock | ||
220 | { | ||
221 | // we switch the mode to 512-bytes-step map reading: | ||
222 | numPadSectors = 0; | ||
223 | _blockSizeLog = 9; | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | #endif | ||
180 | } | 228 | } |
181 | } | 229 | } |
182 | 230 | ||
183 | UInt32 numBlocksInMap = 0; | ||
184 | |||
185 | for (unsigned i = 0;;) | 231 | for (unsigned i = 0;;) |
186 | { | 232 | { |
187 | RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) | 233 | #ifdef Z7_APM_SWITCH_TO_512_BYTES |
234 | if (i != 0 || _blockSizeLog == blockSizeLog_from_Header) | ||
235 | #endif | ||
236 | { | ||
237 | RINOK(ReadStream_FALSE(stream, buf32, kSectorSize)) | ||
238 | } | ||
188 | 239 | ||
189 | CItem item; | 240 | CItem item; |
190 | 241 | UInt32 numBlocksInMap = 0; | |
191 | UInt32 numBlocksInMap2 = 0; | 242 | if (!item.Parse(buf32, numBlocksInMap)) |
192 | if (!item.Parse(buf, numBlocksInMap2)) | ||
193 | return S_FALSE; | 243 | return S_FALSE; |
194 | if (i == 0) | 244 | // v24.09: we don't check that all entries have same (numBlocksInMap) values, |
195 | { | 245 | // because some APMs have different (numBlocksInMap) values, if (Apple_Void) is used. |
196 | numBlocksInMap = numBlocksInMap2; | 246 | if (numBlocksInMap > (1 << 8) || numBlocksInMap <= i) |
197 | if (numBlocksInMap > (1 << 8) || numBlocksInMap == 0) | ||
198 | return S_FALSE; | ||
199 | } | ||
200 | else if (numBlocksInMap2 != numBlocksInMap) | ||
201 | return S_FALSE; | 247 | return S_FALSE; |
202 | 248 | ||
203 | const UInt32 finish = item.StartBlock + item.NumBlocks; | 249 | const UInt32 finish = item.StartBlock + item.NumBlocks; |
@@ -207,15 +253,19 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
207 | numBlocks = finish; | 253 | numBlocks = finish; |
208 | 254 | ||
209 | _items.Add(item); | 255 | _items.Add(item); |
210 | for (unsigned k = numSectors_in_Cluster; --k != 0;) | 256 | if (numPadSectors != 0) |
211 | { | 257 | { |
212 | RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) | 258 | RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL)) |
213 | } | 259 | } |
214 | if (++i == numBlocksInMap) | 260 | if (++i == numBlocksInMap) |
215 | break; | 261 | break; |
216 | } | 262 | } |
217 | 263 | ||
218 | _phySize = BlocksToBytes(numBlocks); | 264 | _phySize = BlocksToBytes(numBlocks); |
265 | // _numBlocks = numBlocks; | ||
266 | const UInt64 physSize = (UInt64)numBlocks_from_Header << blockSizeLog_from_Header; | ||
267 | if (_phySize < physSize) | ||
268 | _phySize = physSize; | ||
219 | _isArc = true; | 269 | _isArc = true; |
220 | _stream = stream; | 270 | _stream = stream; |
221 | 271 | ||
@@ -240,22 +290,21 @@ static const Byte kProps[] = | |||
240 | kpidSize, | 290 | kpidSize, |
241 | kpidOffset, | 291 | kpidOffset, |
242 | kpidCharacts | 292 | kpidCharacts |
293 | // , kpidCpu | ||
243 | }; | 294 | }; |
244 | 295 | ||
245 | static const Byte kArcProps[] = | 296 | static const Byte kArcProps[] = |
246 | { | 297 | { |
247 | kpidClusterSize, | 298 | kpidClusterSize |
248 | kpidNumBlocks | 299 | // , kpidNumBlocks |
249 | }; | 300 | }; |
250 | 301 | ||
251 | IMP_IInArchive_Props | 302 | IMP_IInArchive_Props |
252 | IMP_IInArchive_ArcProps | 303 | IMP_IInArchive_ArcProps |
253 | 304 | ||
254 | static AString GetString(const char *s) | 305 | static void GetString(AString &dest, const char *src) |
255 | { | 306 | { |
256 | AString res; | 307 | dest.SetFrom_CalcLen(src, k_Str_Size); |
257 | res.SetFrom_CalcLen(s, k_Str_Size); | ||
258 | return res; | ||
259 | } | 308 | } |
260 | 309 | ||
261 | Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | 310 | Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) |
@@ -272,7 +321,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
272 | const CItem &item = _items[i]; | 321 | const CItem &item = _items[i]; |
273 | if (!item.Is_Valid_and_Allocated()) | 322 | if (!item.Is_Valid_and_Allocated()) |
274 | continue; | 323 | continue; |
275 | AString s (GetString(item.Type)); | 324 | AString s; |
325 | GetString(s, item.Type); | ||
276 | if (NDmg::Is_Apple_FS_Or_Unknown(s)) | 326 | if (NDmg::Is_Apple_FS_Or_Unknown(s)) |
277 | { | 327 | { |
278 | if (mainIndex != -1) | 328 | if (mainIndex != -1) |
@@ -289,7 +339,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
289 | } | 339 | } |
290 | case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; | 340 | case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; |
291 | case kpidPhySize: prop = _phySize; break; | 341 | case kpidPhySize: prop = _phySize; break; |
292 | case kpidNumBlocks: prop = _numBlocks; break; | 342 | // case kpidNumBlocks: prop = _numBlocks; break; |
293 | 343 | ||
294 | case kpidErrorFlags: | 344 | case kpidErrorFlags: |
295 | { | 345 | { |
@@ -319,10 +369,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
319 | { | 369 | { |
320 | case kpidPath: | 370 | case kpidPath: |
321 | { | 371 | { |
322 | AString s (GetString(item.Name)); | 372 | AString s; |
373 | GetString(s, item.Name); | ||
323 | if (s.IsEmpty()) | 374 | if (s.IsEmpty()) |
324 | s.Add_UInt32(index); | 375 | s.Add_UInt32(index); |
325 | AString type (GetString(item.Type)); | 376 | AString type; |
377 | GetString(type, item.Type); | ||
326 | { | 378 | { |
327 | const char *ext = NDmg::Find_Apple_FS_Ext(type); | 379 | const char *ext = NDmg::Find_Apple_FS_Ext(type); |
328 | if (ext) | 380 | if (ext) |
@@ -336,6 +388,16 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
336 | prop = s; | 388 | prop = s; |
337 | break; | 389 | break; |
338 | } | 390 | } |
391 | /* | ||
392 | case kpidCpu: | ||
393 | { | ||
394 | AString s; | ||
395 | s.SetFrom_CalcLen(item.Processor, sizeof(item.Processor)); | ||
396 | if (!s.IsEmpty()) | ||
397 | prop = s; | ||
398 | break; | ||
399 | } | ||
400 | */ | ||
339 | case kpidSize: | 401 | case kpidSize: |
340 | case kpidPackSize: | 402 | case kpidPackSize: |
341 | prop = BlocksToBytes(item.NumBlocks); | 403 | prop = BlocksToBytes(item.NumBlocks); |
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 95e4719..944eec4 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp | |||
@@ -325,7 +325,7 @@ HRESULT CHandler::ParseLongNames(IInStream *stream) | |||
325 | { | 325 | { |
326 | unsigned i; | 326 | unsigned i; |
327 | for (i = 0; i < _items.Size(); i++) | 327 | for (i = 0; i < _items.Size(); i++) |
328 | if (_items[i].Name == "//") | 328 | if (_items[i].Name.IsEqualTo("//")) |
329 | break; | 329 | break; |
330 | if (i == _items.Size()) | 330 | if (i == _items.Size()) |
331 | return S_OK; | 331 | return S_OK; |
@@ -378,7 +378,7 @@ void CHandler::ChangeDuplicateNames() | |||
378 | if (item.Name[0] == '/') | 378 | if (item.Name[0] == '/') |
379 | continue; | 379 | continue; |
380 | CItem &prev = _items[i - 1]; | 380 | CItem &prev = _items[i - 1]; |
381 | if (item.Name == prev.Name) | 381 | if (item.Name.IsEqualTo(prev.Name)) |
382 | { | 382 | { |
383 | if (prev.SameNameIndex < 0) | 383 | if (prev.SameNameIndex < 0) |
384 | prev.SameNameIndex = 0; | 384 | prev.SameNameIndex = 0; |
@@ -448,9 +448,9 @@ static UInt32 Get32(const Byte *p, unsigned be) { if (be) return GetBe32(p); ret | |||
448 | HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex) | 448 | HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex) |
449 | { | 449 | { |
450 | CItem &item = _items[fileIndex]; | 450 | CItem &item = _items[fileIndex]; |
451 | if (item.Name != "/" && | 451 | if (!item.Name.IsEqualTo("/") && |
452 | item.Name != "__.SYMDEF" && | 452 | !item.Name.IsEqualTo("__.SYMDEF") && |
453 | item.Name != "__.SYMDEF SORTED") | 453 | !item.Name.IsEqualTo("__.SYMDEF SORTED")) |
454 | return S_OK; | 454 | return S_OK; |
455 | if (item.Size > ((UInt32)1 << 30) || | 455 | if (item.Size > ((UInt32)1 << 30) || |
456 | item.Size < 4) | 456 | item.Size < 4) |
@@ -462,7 +462,7 @@ HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex) | |||
462 | 462 | ||
463 | size_t pos = 0; | 463 | size_t pos = 0; |
464 | 464 | ||
465 | if (item.Name != "/") | 465 | if (!item.Name.IsEqualTo("/")) |
466 | { | 466 | { |
467 | // "__.SYMDEF" parsing (BSD) | 467 | // "__.SYMDEF" parsing (BSD) |
468 | unsigned be; | 468 | unsigned be; |
@@ -603,7 +603,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, | |||
603 | if (_longNames_FileIndex >= 0) | 603 | if (_longNames_FileIndex >= 0) |
604 | _items.Delete((unsigned)_longNames_FileIndex); | 604 | _items.Delete((unsigned)_longNames_FileIndex); |
605 | 605 | ||
606 | if (!_items.IsEmpty() && _items[0].Name == "debian-binary") | 606 | if (!_items.IsEmpty() && _items[0].Name.IsEqualTo("debian-binary")) |
607 | { | 607 | { |
608 | _type = kType_Deb; | 608 | _type = kType_Deb; |
609 | _items.DeleteFrontal(1); | 609 | _items.DeleteFrontal(1); |
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp index ffd7ad0..02eeee6 100644 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp | |||
@@ -427,9 +427,13 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
427 | } | 427 | } |
428 | 428 | ||
429 | CMethodProps props2 = _props; | 429 | CMethodProps props2 = _props; |
430 | #ifndef Z7_ST | 430 | #ifndef Z7_ST |
431 | props2.AddProp_NumThreads(_props._numThreads); | 431 | props2.AddProp_NumThreads(_props._numThreads); |
432 | #endif | 432 | #ifdef _WIN32 |
433 | if (_props._numThreadGroups > 1) | ||
434 | props2.AddProp32(NCoderPropID::kNumThreadGroups, _props._numThreadGroups); | ||
435 | #endif | ||
436 | #endif | ||
433 | 437 | ||
434 | return UpdateArchive(size, outStream, props2, updateCallback); | 438 | return UpdateArchive(size, outStream, props2, updateCallback); |
435 | } | 439 | } |
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index 82d939d..144369e 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp | |||
@@ -68,7 +68,7 @@ namespace NItemType | |||
68 | static const Byte kRootStorage = 5; | 68 | static const Byte kRootStorage = 5; |
69 | } | 69 | } |
70 | 70 | ||
71 | static const UInt32 kNameSizeMax = 64; | 71 | static const unsigned kNameSizeMax = 64; |
72 | 72 | ||
73 | struct CItem | 73 | struct CItem |
74 | { | 74 | { |
@@ -98,30 +98,30 @@ struct CRef | |||
98 | 98 | ||
99 | class CDatabase | 99 | class CDatabase |
100 | { | 100 | { |
101 | UInt32 NumSectorsInMiniStream; | ||
102 | CObjArray<UInt32> MiniSids; | 101 | CObjArray<UInt32> MiniSids; |
103 | 102 | ||
104 | HRESULT AddNode(int parent, UInt32 did); | 103 | HRESULT AddNode(int parent, UInt32 did); |
105 | public: | ||
106 | 104 | ||
105 | public: | ||
107 | CObjArray<UInt32> Fat; | 106 | CObjArray<UInt32> Fat; |
108 | UInt32 FatSize; | ||
109 | |||
110 | CObjArray<UInt32> Mat; | 107 | CObjArray<UInt32> Mat; |
111 | UInt32 MatSize; | ||
112 | |||
113 | CObjectVector<CItem> Items; | 108 | CObjectVector<CItem> Items; |
114 | CRecordVector<CRef> Refs; | 109 | CRecordVector<CRef> Refs; |
110 | private: | ||
111 | UInt32 NumSectorsInMiniStream; | ||
112 | public: | ||
113 | UInt32 MatSize; | ||
114 | UInt32 FatSize; | ||
115 | 115 | ||
116 | UInt32 LongStreamMinSize; | 116 | UInt32 LongStreamMinSize; |
117 | unsigned SectorSizeBits; | 117 | unsigned SectorSizeBits; |
118 | unsigned MiniSectorSizeBits; | 118 | unsigned MiniSectorSizeBits; |
119 | 119 | ||
120 | Int32 MainSubfile; | 120 | Int32 MainSubfile; |
121 | EType Type; | ||
121 | 122 | ||
122 | UInt64 PhySize; | 123 | UInt64 PhySize; |
123 | UInt64 PhySize_Aligned; | 124 | UInt64 PhySize_Aligned; |
124 | EType Type; | ||
125 | 125 | ||
126 | bool IsNotArcType() const | 126 | bool IsNotArcType() const |
127 | { | 127 | { |
@@ -148,14 +148,14 @@ public: | |||
148 | 148 | ||
149 | UInt64 GetItemPackSize(UInt64 size) const | 149 | UInt64 GetItemPackSize(UInt64 size) const |
150 | { | 150 | { |
151 | UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; | 151 | const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; |
152 | return (size + mask) & ~mask; | 152 | return (size + mask) & ~mask; |
153 | } | 153 | } |
154 | 154 | ||
155 | bool GetMiniCluster(UInt32 sid, UInt64 &res) const | 155 | bool GetMiniCluster(UInt32 sid, UInt64 &res) const |
156 | { | 156 | { |
157 | unsigned subBits = SectorSizeBits - MiniSectorSizeBits; | 157 | const unsigned subBits = SectorSizeBits - MiniSectorSizeBits; |
158 | UInt32 fid = sid >> subBits; | 158 | const UInt32 fid = sid >> subBits; |
159 | if (fid >= NumSectorsInMiniStream) | 159 | if (fid >= NumSectorsInMiniStream) |
160 | return false; | 160 | return false; |
161 | res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); | 161 | res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); |
@@ -177,7 +177,7 @@ HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSiz | |||
177 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest) | 177 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest) |
178 | { | 178 | { |
179 | RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)) | 179 | RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)) |
180 | UInt32 sectorSize = (UInt32)1 << sectorSizeBits; | 180 | const UInt32 sectorSize = (UInt32)1 << sectorSizeBits; |
181 | for (UInt32 t = 0; t < sectorSize; t += 4) | 181 | for (UInt32 t = 0; t < sectorSize; t += 4) |
182 | *dest++ = Get32(buf + t); | 182 | *dest++ = Get32(buf + t); |
183 | return S_OK; | 183 | return S_OK; |
@@ -373,7 +373,7 @@ UString CDatabase::GetItemPath(UInt32 index) const | |||
373 | HRESULT CDatabase::Update_PhySize_WithItem(unsigned index) | 373 | HRESULT CDatabase::Update_PhySize_WithItem(unsigned index) |
374 | { | 374 | { |
375 | const CItem &item = Items[index]; | 375 | const CItem &item = Items[index]; |
376 | bool isLargeStream = (index == 0 || IsLargeStream(item.Size)); | 376 | const bool isLargeStream = (index == 0 || IsLargeStream(item.Size)); |
377 | if (!isLargeStream) | 377 | if (!isLargeStream) |
378 | return S_OK; | 378 | return S_OK; |
379 | const unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits; | 379 | const unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits; |
@@ -527,6 +527,10 @@ HRESULT CDatabase::Open(IInStream *inStream) | |||
527 | { | 527 | { |
528 | CItem item; | 528 | CItem item; |
529 | item.Parse(sect + i, mode64bit); | 529 | item.Parse(sect + i, mode64bit); |
530 | // we use (item.Size) check here. | ||
531 | // so we don't need additional overflow checks for (item.Size +) in another code | ||
532 | if (item.Size >= ((UInt64)1 << 63)) | ||
533 | return S_FALSE; | ||
530 | Items.Add(item); | 534 | Items.Add(item); |
531 | } | 535 | } |
532 | sid = Fat[sid]; | 536 | sid = Fat[sid]; |
@@ -767,11 +771,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
767 | UInt64 totalPackSize; | 771 | UInt64 totalPackSize; |
768 | totalSize = totalPackSize = 0; | 772 | totalSize = totalPackSize = 0; |
769 | 773 | ||
770 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | 774 | CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; |
771 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | 775 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
772 | |||
773 | CLocalProgress *lps = new CLocalProgress; | ||
774 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
775 | lps->Init(extractCallback, false); | 776 | lps->Init(extractCallback, false); |
776 | 777 | ||
777 | for (i = 0; i < numItems; i++) | 778 | for (i = 0; i < numItems; i++) |
@@ -781,7 +782,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
781 | RINOK(lps->SetCur()) | 782 | RINOK(lps->SetCur()) |
782 | const UInt32 index = allFilesMode ? i : indices[i]; | 783 | const UInt32 index = allFilesMode ? i : indices[i]; |
783 | const CItem &item = _db.Items[_db.Refs[index].Did]; | 784 | const CItem &item = _db.Items[_db.Refs[index].Did]; |
784 | 785 | Int32 res; | |
786 | { | ||
785 | CMyComPtr<ISequentialOutStream> outStream; | 787 | CMyComPtr<ISequentialOutStream> outStream; |
786 | const Int32 askMode = testMode ? | 788 | const Int32 askMode = testMode ? |
787 | NExtract::NAskMode::kTest : | 789 | NExtract::NAskMode::kTest : |
@@ -801,7 +803,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
801 | if (!testMode && !outStream) | 803 | if (!testMode && !outStream) |
802 | continue; | 804 | continue; |
803 | RINOK(extractCallback->PrepareOperation(askMode)) | 805 | RINOK(extractCallback->PrepareOperation(askMode)) |
804 | Int32 res = NExtract::NOperationResult::kDataError; | 806 | res = NExtract::NOperationResult::kDataError; |
805 | CMyComPtr<ISequentialInStream> inStream; | 807 | CMyComPtr<ISequentialInStream> inStream; |
806 | HRESULT hres = GetStream(index, &inStream); | 808 | HRESULT hres = GetStream(index, &inStream); |
807 | if (hres == S_FALSE) | 809 | if (hres == S_FALSE) |
@@ -813,12 +815,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
813 | RINOK(hres) | 815 | RINOK(hres) |
814 | if (inStream) | 816 | if (inStream) |
815 | { | 817 | { |
816 | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) | 818 | RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps)) |
817 | if (copyCoderSpec->TotalSize == item.Size) | 819 | if (copyCoder->TotalSize == item.Size) |
818 | res = NExtract::NOperationResult::kOK; | 820 | res = NExtract::NOperationResult::kOK; |
819 | } | 821 | } |
820 | } | 822 | } |
821 | outStream.Release(); | 823 | } |
822 | RINOK(extractCallback->SetOperationResult(res)) | 824 | RINOK(extractCallback->SetOperationResult(res)) |
823 | } | 825 | } |
824 | return S_OK; | 826 | return S_OK; |
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 17fed67..5a11e30 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp | |||
@@ -4,8 +4,6 @@ | |||
4 | 4 | ||
5 | #include "../../../Common/StringToInt.h" | 5 | #include "../../../Common/StringToInt.h" |
6 | 6 | ||
7 | #include "../Common/ParseProperties.h" | ||
8 | |||
9 | #include "HandlerOut.h" | 7 | #include "HandlerOut.h" |
10 | 8 | ||
11 | namespace NArchive { | 9 | namespace NArchive { |
@@ -82,6 +80,7 @@ bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsB | |||
82 | return true; | 80 | return true; |
83 | } | 81 | } |
84 | 82 | ||
83 | |||
85 | bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres) | 84 | bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres) |
86 | { | 85 | { |
87 | hres = S_OK; | 86 | hres = S_OK; |
@@ -151,6 +150,11 @@ void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, | |||
151 | SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); | 150 | SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); |
152 | } | 151 | } |
153 | 152 | ||
153 | void CMultiMethodProps::Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreadGroups) | ||
154 | { | ||
155 | SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreadGroups, numThreadGroups); | ||
156 | } | ||
157 | |||
154 | #endif // Z7_ST | 158 | #endif // Z7_ST |
155 | 159 | ||
156 | 160 | ||
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index cfba46e..3122b05 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h | |||
@@ -17,12 +17,22 @@ protected: | |||
17 | void InitCommon() | 17 | void InitCommon() |
18 | { | 18 | { |
19 | // _Write_MTime = true; | 19 | // _Write_MTime = true; |
20 | #ifndef Z7_ST | 20 | { |
21 | _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); | 21 | #ifndef Z7_ST |
22 | _numThreads_WasForced = false; | 22 | _numThreads_WasForced = false; |
23 | #endif | 23 | UInt32 numThreads; |
24 | 24 | #ifdef _WIN32 | |
25 | UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28; | 25 | NWindows::NSystem::CProcessAffinity aff; |
26 | numThreads = aff.Load_and_GetNumberOfThreads(); | ||
27 | _numThreadGroups = aff.IsGroupMode ? aff.Groups.GroupSizes.Size() : 0; | ||
28 | #else | ||
29 | numThreads = NWindows::NSystem::GetNumberOfProcessors(); | ||
30 | #endif // _WIN32 | ||
31 | _numProcessors = _numThreads = numThreads; | ||
32 | #endif // Z7_ST | ||
33 | } | ||
34 | |||
35 | size_t memAvail = (size_t)sizeof(size_t) << 28; | ||
26 | _memAvail = memAvail; | 36 | _memAvail = memAvail; |
27 | _memUsage_Compress = memAvail; | 37 | _memUsage_Compress = memAvail; |
28 | _memUsage_Decompress = memAvail; | 38 | _memUsage_Decompress = memAvail; |
@@ -46,16 +56,19 @@ protected: | |||
46 | } | 56 | } |
47 | 57 | ||
48 | public: | 58 | public: |
49 | #ifndef Z7_ST | 59 | #ifndef Z7_ST |
50 | UInt32 _numThreads; | 60 | UInt32 _numThreads; |
51 | UInt32 _numProcessors; | 61 | UInt32 _numProcessors; |
62 | #ifdef _WIN32 | ||
63 | UInt32 _numThreadGroups; | ||
64 | #endif | ||
52 | bool _numThreads_WasForced; | 65 | bool _numThreads_WasForced; |
53 | #endif | 66 | #endif |
54 | 67 | ||
55 | bool _memUsage_WasSet; | 68 | bool _memUsage_WasSet; |
56 | UInt64 _memUsage_Compress; | 69 | UInt64 _memUsage_Compress; |
57 | UInt64 _memUsage_Decompress; | 70 | UInt64 _memUsage_Decompress; |
58 | UInt64 _memAvail; | 71 | size_t _memAvail; |
59 | 72 | ||
60 | bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres); | 73 | bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres); |
61 | 74 | ||
@@ -80,10 +93,12 @@ public: | |||
80 | 93 | ||
81 | void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const; | 94 | void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const; |
82 | 95 | ||
83 | #ifndef Z7_ST | 96 | #ifndef Z7_ST |
84 | static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads); | 97 | static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads); |
85 | static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads); | 98 | static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads); |
86 | #endif | 99 | |
100 | static void Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &props, UInt32 numThreadGroups); | ||
101 | #endif | ||
87 | 102 | ||
88 | 103 | ||
89 | unsigned GetNumEmptyMethods() const | 104 | unsigned GetNumEmptyMethods() const |
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index 8caf1d1..150efc9 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp | |||
@@ -47,6 +47,25 @@ UString GetOsPath_Remove_TailSlash(const UString &name) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | 49 | ||
50 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
51 | void ReplaceToWinSlashes(UString &name, bool useBackslashReplacement) | ||
52 | { | ||
53 | // name.Replace(kUnixPathSepar, kOsPathSepar); | ||
54 | const unsigned len = name.Len(); | ||
55 | for (unsigned i = 0; i < len; i++) | ||
56 | { | ||
57 | wchar_t c = name[i]; | ||
58 | if (c == L'/') | ||
59 | c = WCHAR_PATH_SEPARATOR; | ||
60 | else if (useBackslashReplacement && c == L'\\') | ||
61 | c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme | ||
62 | else | ||
63 | continue; | ||
64 | name.ReplaceOneCharAtPos(i, c); | ||
65 | } | ||
66 | } | ||
67 | #endif | ||
68 | |||
50 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool | 69 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool |
51 | #if WCHAR_PATH_SEPARATOR != L'/' | 70 | #if WCHAR_PATH_SEPARATOR != L'/' |
52 | useBackslashReplacement | 71 | useBackslashReplacement |
@@ -57,21 +76,7 @@ void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool | |||
57 | return; | 76 | return; |
58 | 77 | ||
59 | #if WCHAR_PATH_SEPARATOR != L'/' | 78 | #if WCHAR_PATH_SEPARATOR != L'/' |
60 | { | 79 | ReplaceToWinSlashes(name, useBackslashReplacement); |
61 | // name.Replace(kUnixPathSepar, kOsPathSepar); | ||
62 | const unsigned len = name.Len(); | ||
63 | for (unsigned i = 0; i < len; i++) | ||
64 | { | ||
65 | wchar_t c = name[i]; | ||
66 | if (c == L'/') | ||
67 | c = WCHAR_PATH_SEPARATOR; | ||
68 | else if (useBackslashReplacement && c == L'\\') | ||
69 | c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme | ||
70 | else | ||
71 | continue; | ||
72 | name.ReplaceOneCharAtPos(i, c); | ||
73 | } | ||
74 | } | ||
75 | #endif | 80 | #endif |
76 | 81 | ||
77 | if (name.Back() == kOsPathSepar) | 82 | if (name.Back() == kOsPathSepar) |
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h index 8ab9b61..cea8dcc 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h | |||
@@ -13,6 +13,9 @@ void ReplaceSlashes_OsToUnix(UString &name); | |||
13 | UString GetOsPath(const UString &name); | 13 | UString GetOsPath(const UString &name); |
14 | UString GetOsPath_Remove_TailSlash(const UString &name); | 14 | UString GetOsPath_Remove_TailSlash(const UString &name); |
15 | 15 | ||
16 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
17 | void ReplaceToWinSlashes(UString &name, bool useBackslashReplacement); | ||
18 | #endif | ||
16 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); | 19 | void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); |
17 | void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len); | 20 | void NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len); |
18 | void NormalizeSlashes_in_FileName_for_OsPath(UString &name); | 21 | void NormalizeSlashes_in_FileName_for_OsPath(UString &name); |
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index 2228040..62184f0 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp | |||
@@ -437,7 +437,14 @@ HRESULT CInArchive::GetNextItem() | |||
437 | return S_OK; | 437 | return S_OK; |
438 | 438 | ||
439 | /* v23.02: we have disabled rDevMinor check because real file | 439 | /* v23.02: we have disabled rDevMinor check because real file |
440 | from Apple contains rDevMinor==255 by some unknown reason */ | 440 | from Apple contains rDevMinor==255 by some unknown reason |
441 | cpio 2.13 and older versions: it copies stat::st_rdev to archive. | ||
442 | and stat::st_rdev can be non-zero for some old linux/filesystems cases for regular files. | ||
443 | cpio 2.14 (2023) copies st_rdev to archive only if (S_ISBLK (st->st_mode) || S_ISCHR (st->st_mode)) | ||
444 | v25.00: we have disabled RDevMajor check here to support some rare case created by cpio 2.13- with old linux. | ||
445 | But we still keep full check in IsArc_Cpio() to reduce false cpio detection cases. | ||
446 | */ | ||
447 | #if 0 // 0 : to disable check to support some old linux cpio archives. | ||
441 | if (item.RDevMajor != 0 | 448 | if (item.RDevMajor != 0 |
442 | // || item.RDevMinor != 0 | 449 | // || item.RDevMinor != 0 |
443 | ) | 450 | ) |
@@ -446,6 +453,7 @@ HRESULT CInArchive::GetNextItem() | |||
446 | !MY_LIN_S_ISBLK(item.Mode)) | 453 | !MY_LIN_S_ISBLK(item.Mode)) |
447 | return S_OK; | 454 | return S_OK; |
448 | } | 455 | } |
456 | #endif | ||
449 | 457 | ||
450 | // Size must be 0 for FIFOs and directories | 458 | // Size must be 0 for FIFOs and directories |
451 | if (item.IsDir() || MY_LIN_S_ISFIFO(item.Mode)) | 459 | if (item.IsDir() || MY_LIN_S_ISFIFO(item.Mode)) |
@@ -873,17 +881,13 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
873 | { | 881 | { |
874 | case kpidPath: | 882 | case kpidPath: |
875 | { | 883 | { |
876 | UString res; | 884 | #ifdef _WIN32 |
877 | bool needConvert = true; | 885 | UString u; |
878 | #ifdef _WIN32 | 886 | ConvertUTF8ToUnicode(item.Name, u); |
879 | // if ( | 887 | #else |
880 | ConvertUTF8ToUnicode(item.Name, res); | 888 | const UString u = MultiByteToUnicodeString(item.Name, CP_OEMCP); |
881 | // ) | 889 | #endif |
882 | needConvert = false; | 890 | prop = NItemName::GetOsPath(u); |
883 | #endif | ||
884 | if (needConvert) | ||
885 | res = MultiByteToUnicodeString(item.Name, CP_OEMCP); | ||
886 | prop = NItemName::GetOsPath(res); | ||
887 | break; | 891 | break; |
888 | } | 892 | } |
889 | case kpidIsDir: prop = item.IsDir(); break; | 893 | case kpidIsDir: prop = item.IsDir(); break; |
@@ -921,16 +925,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
921 | s.SetFrom_CalcLen((const char *)(const void *)(const Byte *)item.Data, (unsigned)item.Data.Size()); | 925 | s.SetFrom_CalcLen((const char *)(const void *)(const Byte *)item.Data, (unsigned)item.Data.Size()); |
922 | if (s.Len() == item.Data.Size()) | 926 | if (s.Len() == item.Data.Size()) |
923 | { | 927 | { |
928 | #ifdef _WIN32 | ||
924 | UString u; | 929 | UString u; |
925 | bool needConvert = true; | 930 | ConvertUTF8ToUnicode(item.Name, u); |
926 | #ifdef _WIN32 | 931 | #else |
927 | // if ( | 932 | const UString u = MultiByteToUnicodeString(s, CP_OEMCP); |
928 | ConvertUTF8ToUnicode(item.Name, u); | 933 | #endif |
929 | // ) | ||
930 | needConvert = false; | ||
931 | #endif | ||
932 | if (needConvert) | ||
933 | u = MultiByteToUnicodeString(s, CP_OEMCP); | ||
934 | prop = u; | 934 | prop = u; |
935 | } | 935 | } |
936 | } | 936 | } |
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 3901192..9079dc7 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp | |||
@@ -444,7 +444,7 @@ const char *Find_Apple_FS_Ext(const AString &name) | |||
444 | { | 444 | { |
445 | const CAppleName &a = k_Names[i]; | 445 | const CAppleName &a = k_Names[i]; |
446 | if (a.Ext) | 446 | if (a.Ext) |
447 | if (name == a.AppleName) | 447 | if (name.IsEqualTo(a.AppleName)) |
448 | return a.Ext; | 448 | return a.Ext; |
449 | } | 449 | } |
450 | return NULL; | 450 | return NULL; |
@@ -784,7 +784,7 @@ static const CXmlItem *FindKeyPair(const CXmlItem &item, const char *key, const | |||
784 | for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++) | 784 | for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++) |
785 | { | 785 | { |
786 | const CXmlItem &si = item.SubItems[i]; | 786 | const CXmlItem &si = item.SubItems[i]; |
787 | if (si.IsTagged("key") && si.GetSubString() == key) | 787 | if (si.IsTagged("key") && si.GetSubString().IsEqualTo(key)) |
788 | { | 788 | { |
789 | const CXmlItem *si_1 = &item.SubItems[i + 1]; | 789 | const CXmlItem *si_1 = &item.SubItems[i + 1]; |
790 | if (si_1->IsTagged(nextTag)) | 790 | if (si_1->IsTagged(nextTag)) |
@@ -1251,7 +1251,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCall | |||
1251 | #endif | 1251 | #endif |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | if (xml.Root.Name != "plist") | 1254 | if (!xml.Root.Name.IsEqualTo("plist")) |
1255 | return S_FALSE; | 1255 | return S_FALSE; |
1256 | 1256 | ||
1257 | const CXmlItem *dictItem = xml.Root.FindSubTag_GetPtr("dict"); | 1257 | const CXmlItem *dictItem = xml.Root.FindSubTag_GetPtr("dict"); |
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index b31ee4f..18fce91 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp | |||
@@ -2,13 +2,12 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | // #include <stdio.h> | ||
6 | |||
7 | #include "../../../C/CpuArch.h" | 5 | #include "../../../C/CpuArch.h" |
8 | 6 | ||
9 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
10 | #include "../../Common/IntToString.h" | 8 | #include "../../Common/IntToString.h" |
11 | #include "../../Common/MyBuffer.h" | 9 | #include "../../Common/MyBuffer.h" |
10 | #include "../../Common/MyBuffer2.h" | ||
12 | #include "../../Common/MyCom.h" | 11 | #include "../../Common/MyCom.h" |
13 | #include "../../Common/StringConvert.h" | 12 | #include "../../Common/StringConvert.h" |
14 | 13 | ||
@@ -22,14 +21,19 @@ | |||
22 | 21 | ||
23 | #include "../Compress/CopyCoder.h" | 22 | #include "../Compress/CopyCoder.h" |
24 | 23 | ||
25 | #include "Common/DummyOutStream.h" | 24 | #include "Common/ItemNameUtils.h" |
26 | 25 | ||
27 | #define Get16(p) GetUi16(p) | 26 | #define Get16(p) GetUi16(p) |
28 | #define Get32(p) GetUi32(p) | 27 | #define Get32(p) GetUi32(p) |
29 | #define Get16a(p) GetUi16a(p) | 28 | #define Get16a(p) GetUi16a(p) |
30 | #define Get32a(p) GetUi32a(p) | 29 | #define Get32a(p) GetUi32a(p) |
31 | 30 | ||
32 | #define PRF(x) /* x */ | 31 | #if 0 |
32 | #include <stdio.h> | ||
33 | #define PRF(x) x | ||
34 | #else | ||
35 | #define PRF(x) | ||
36 | #endif | ||
33 | 37 | ||
34 | namespace NArchive { | 38 | namespace NArchive { |
35 | namespace NFat { | 39 | namespace NFat { |
@@ -38,35 +42,34 @@ static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31; | |||
38 | 42 | ||
39 | struct CHeader | 43 | struct CHeader |
40 | { | 44 | { |
41 | UInt32 NumSectors; | 45 | Byte NumFatBits; |
42 | UInt16 NumReservedSectors; | 46 | Byte SectorSizeLog; |
47 | Byte SectorsPerClusterLog; | ||
48 | Byte ClusterSizeLog; | ||
43 | Byte NumFats; | 49 | Byte NumFats; |
50 | Byte MediaType; | ||
51 | |||
52 | bool VolFieldsDefined; | ||
53 | bool HeadersWarning; | ||
54 | |||
55 | UInt32 FatSize; | ||
56 | UInt32 BadCluster; | ||
57 | |||
58 | UInt16 NumReservedSectors; | ||
59 | UInt32 NumSectors; | ||
44 | UInt32 NumFatSectors; | 60 | UInt32 NumFatSectors; |
45 | UInt32 RootDirSector; | 61 | UInt32 RootDirSector; |
46 | UInt32 NumRootDirSectors; | 62 | UInt32 NumRootDirSectors; |
47 | UInt32 DataSector; | 63 | UInt32 DataSector; |
48 | 64 | ||
49 | UInt32 FatSize; | ||
50 | UInt32 BadCluster; | ||
51 | |||
52 | Byte NumFatBits; | ||
53 | Byte SectorSizeLog; | ||
54 | Byte SectorsPerClusterLog; | ||
55 | Byte ClusterSizeLog; | ||
56 | |||
57 | UInt16 SectorsPerTrack; | 65 | UInt16 SectorsPerTrack; |
58 | UInt16 NumHeads; | 66 | UInt16 NumHeads; |
59 | UInt32 NumHiddenSectors; | 67 | UInt32 NumHiddenSectors; |
60 | |||
61 | bool VolFieldsDefined; | ||
62 | bool HeadersWarning; | ||
63 | 68 | ||
64 | UInt32 VolId; | 69 | UInt32 VolId; |
65 | // Byte VolName[11]; | 70 | // Byte VolName[11]; |
66 | // Byte FileSys[8]; | 71 | // Byte FileSys[8]; |
67 | |||
68 | // Byte OemName[5]; | 72 | // Byte OemName[5]; |
69 | Byte MediaType; | ||
70 | 73 | ||
71 | // 32-bit FAT | 74 | // 32-bit FAT |
72 | UInt16 Flags; | 75 | UInt16 Flags; |
@@ -104,15 +107,8 @@ struct CHeader | |||
104 | bool Parse(const Byte *p); | 107 | bool Parse(const Byte *p); |
105 | }; | 108 | }; |
106 | 109 | ||
107 | static int GetLog(UInt32 num) | ||
108 | { | ||
109 | for (int i = 0; i < 31; i++) | ||
110 | if (((UInt32)1 << i) == num) | ||
111 | return i; | ||
112 | return -1; | ||
113 | } | ||
114 | 110 | ||
115 | static const UInt32 kHeaderSize = 512; | 111 | static const unsigned kHeaderSize = 512; |
116 | 112 | ||
117 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size); | 113 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size); |
118 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size) | 114 | API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size) |
@@ -125,7 +121,7 @@ API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size) | |||
125 | 121 | ||
126 | bool CHeader::Parse(const Byte *p) | 122 | bool CHeader::Parse(const Byte *p) |
127 | { | 123 | { |
128 | if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) | 124 | if (Get16(p + 0x1FE) != 0xAA55) |
129 | return false; | 125 | return false; |
130 | 126 | ||
131 | HeadersWarning = false; | 127 | HeadersWarning = false; |
@@ -139,22 +135,40 @@ bool CHeader::Parse(const Byte *p) | |||
139 | } | 135 | } |
140 | { | 136 | { |
141 | { | 137 | { |
142 | const UInt32 val32 = Get16(p + 11); | 138 | const unsigned num = Get16(p + 11); |
143 | const int s = GetLog(val32); | 139 | unsigned i = 9; |
144 | if (s < 9 || s > 12) | 140 | unsigned m = 1 << i; |
145 | return false; | 141 | for (;;) |
146 | SectorSizeLog = (Byte)s; | 142 | { |
143 | if (m == num) | ||
144 | break; | ||
145 | m <<= 1; | ||
146 | if (++i > 12) | ||
147 | return false; | ||
148 | } | ||
149 | SectorSizeLog = (Byte)i; | ||
147 | } | 150 | } |
148 | { | 151 | { |
149 | const UInt32 val32 = p[13]; | 152 | const unsigned num = p[13]; |
150 | const int s = GetLog(val32); | 153 | unsigned i = 0; |
151 | if (s < 0) | 154 | unsigned m = 1 << i; |
155 | for (;;) | ||
156 | { | ||
157 | if (m == num) | ||
158 | break; | ||
159 | m <<= 1; | ||
160 | if (++i > 7) | ||
161 | return false; | ||
162 | } | ||
163 | SectorsPerClusterLog = (Byte)i; | ||
164 | i += SectorSizeLog; | ||
165 | ClusterSizeLog = (Byte)i; | ||
166 | // (2^15 = 32 KB is safe cluster size that is suported by all system. | ||
167 | // (2^16 = 64 KB is supported by some systems | ||
168 | // (128 KB / 256 KB) can be created by some tools, but it is not supported by many tools. | ||
169 | if (i > 18) // 256 KB | ||
152 | return false; | 170 | return false; |
153 | SectorsPerClusterLog = (Byte)s; | ||
154 | } | 171 | } |
155 | ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog); | ||
156 | if (ClusterSizeLog > 24) | ||
157 | return false; | ||
158 | } | 172 | } |
159 | 173 | ||
160 | NumReservedSectors = Get16(p + 14); | 174 | NumReservedSectors = Get16(p + 14); |
@@ -169,7 +183,7 @@ bool CHeader::Parse(const Byte *p) | |||
169 | const bool isOkOffset = (codeOffset == 0) | 183 | const bool isOkOffset = (codeOffset == 0) |
170 | || (codeOffset == (p[0] == 0xEB ? 2 : 3)); | 184 | || (codeOffset == (p[0] == 0xEB ? 2 : 3)); |
171 | 185 | ||
172 | const UInt16 numRootDirEntries = Get16(p + 17); | 186 | const unsigned numRootDirEntries = Get16(p + 17); |
173 | if (numRootDirEntries == 0) | 187 | if (numRootDirEntries == 0) |
174 | { | 188 | { |
175 | if (codeOffset < 90 && !isOkOffset) | 189 | if (codeOffset < 90 && !isOkOffset) |
@@ -183,10 +197,10 @@ bool CHeader::Parse(const Byte *p) | |||
183 | if (codeOffset < 62 - 24 && !isOkOffset) | 197 | if (codeOffset < 62 - 24 && !isOkOffset) |
184 | return false; | 198 | return false; |
185 | NumFatBits = 0; | 199 | NumFatBits = 0; |
186 | const UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; | 200 | const unsigned mask = (1u << (SectorSizeLog - 5)) - 1; |
187 | if ((numRootDirEntries & mask) != 0) | 201 | if (numRootDirEntries & mask) |
188 | return false; | 202 | return false; |
189 | NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5); | 203 | NumRootDirSectors = (numRootDirEntries /* + mask */) >> (SectorSizeLog - 5); |
190 | } | 204 | } |
191 | 205 | ||
192 | NumSectors = Get16(p + 19); | 206 | NumSectors = Get16(p + 19); |
@@ -198,7 +212,6 @@ bool CHeader::Parse(const Byte *p) | |||
198 | else if (IsFat32()) | 212 | else if (IsFat32()) |
199 | return false; | 213 | return false; |
200 | */ | 214 | */ |
201 | |||
202 | MediaType = p[21]; | 215 | MediaType = p[21]; |
203 | NumFatSectors = Get16(p + 22); | 216 | NumFatSectors = Get16(p + 22); |
204 | SectorsPerTrack = Get16(p + 24); | 217 | SectorsPerTrack = Get16(p + 24); |
@@ -222,7 +235,7 @@ bool CHeader::Parse(const Byte *p) | |||
222 | return false; | 235 | return false; |
223 | RootCluster = Get32(p + 8); | 236 | RootCluster = Get32(p + 8); |
224 | FsInfoSector = Get16(p + 12); | 237 | FsInfoSector = Get16(p + 12); |
225 | for (int i = 16; i < 28; i++) | 238 | for (unsigned i = 16; i < 28; i++) |
226 | if (p[i] != 0) | 239 | if (p[i] != 0) |
227 | return false; | 240 | return false; |
228 | p += 28; | 241 | p += 28; |
@@ -260,7 +273,7 @@ bool CHeader::Parse(const Byte *p) | |||
260 | if (numClusters >= 0xFFF5) | 273 | if (numClusters >= 0xFFF5) |
261 | return false; | 274 | return false; |
262 | NumFatBits = (Byte)(numClusters < 0xFF5 ? 12 : 16); | 275 | NumFatBits = (Byte)(numClusters < 0xFF5 ? 12 : 16); |
263 | BadCluster &= ((1 << NumFatBits) - 1); | 276 | BadCluster &= (((UInt32)1 << NumFatBits) - 1); |
264 | } | 277 | } |
265 | 278 | ||
266 | FatSize = numClusters + 2; | 279 | FatSize = numClusters + 2; |
@@ -283,103 +296,157 @@ bool CHeader::Parse(const Byte *p) | |||
283 | return true; | 296 | return true; |
284 | } | 297 | } |
285 | 298 | ||
286 | struct CItem | 299 | |
300 | |||
301 | class CItem | ||
287 | { | 302 | { |
288 | UString UName; | 303 | Z7_CLASS_NO_COPY(CItem) |
289 | char DosName[11]; | 304 | public: |
305 | UInt32 Size; | ||
306 | Byte Attrib; | ||
290 | Byte CTime2; | 307 | Byte CTime2; |
291 | UInt32 CTime; | ||
292 | UInt32 MTime; | ||
293 | UInt16 ADate; | 308 | UInt16 ADate; |
294 | Byte Attrib; | 309 | CByteBuffer LongName; // if LongName.Size() == 0 : no long name |
310 | // if LongName.Size() != 0 : it's NULL terminated UTF16-LE string. | ||
311 | char DosName[11]; | ||
295 | Byte Flags; | 312 | Byte Flags; |
296 | UInt32 Size; | 313 | UInt32 MTime; |
314 | UInt32 CTime; | ||
297 | UInt32 Cluster; | 315 | UInt32 Cluster; |
298 | Int32 Parent; | 316 | Int32 Parent; |
299 | 317 | ||
318 | CItem() {} | ||
319 | |||
300 | // NT uses Flags to store Low Case status | 320 | // NT uses Flags to store Low Case status |
301 | bool NameIsLow() const { return (Flags & 0x8) != 0; } | 321 | bool NameIsLow() const { return (Flags & 0x8) != 0; } |
302 | bool ExtIsLow() const { return (Flags & 0x10) != 0; } | 322 | bool ExtIsLow() const { return (Flags & 0x10) != 0; } |
303 | bool IsDir() const { return (Attrib & 0x10) != 0; } | 323 | bool IsDir() const { return (Attrib & 0x10) != 0; } |
304 | UString GetShortName() const; | 324 | void GetShortName(UString &dest) const; |
305 | UString GetName() const; | 325 | void GetName(UString &name) const; |
306 | UString GetVolName() const; | ||
307 | }; | 326 | }; |
308 | 327 | ||
309 | static unsigned CopyAndTrim(char *dest, const char *src, unsigned size, bool toLower) | 328 | |
329 | static char *CopyAndTrim(char *dest, const char *src, | ||
330 | unsigned size, unsigned toLower) | ||
310 | { | 331 | { |
311 | memcpy(dest, src, size); | 332 | do |
312 | if (toLower) | ||
313 | { | 333 | { |
314 | for (unsigned i = 0; i < size; i++) | 334 | if (src[(size_t)size - 1] != ' ') |
315 | { | 335 | { |
316 | char c = dest[i]; | 336 | const unsigned range = toLower ? 'Z' - 'A' + 1 : 0; |
317 | if (c >= 'A' && c <= 'Z') | 337 | do |
318 | dest[i] = (char)(c + 0x20); | 338 | { |
339 | unsigned c = (Byte)*src++; | ||
340 | if ((unsigned)(c - 'A') < range) | ||
341 | c += 0x20; | ||
342 | *dest++ = (char)c; | ||
343 | } | ||
344 | while (--size); | ||
345 | break; | ||
319 | } | 346 | } |
320 | } | 347 | } |
321 | 348 | while (--size); | |
322 | for (unsigned i = size;;) | 349 | *dest = 0; |
323 | { | 350 | return dest; |
324 | if (i == 0) | ||
325 | return 0; | ||
326 | if (dest[i - 1] != ' ') | ||
327 | return i; | ||
328 | i--; | ||
329 | } | ||
330 | } | 351 | } |
331 | 352 | ||
332 | static UString FatStringToUnicode(const char *s) | 353 | |
354 | static void FatStringToUnicode(UString &dest, const char *s) | ||
333 | { | 355 | { |
334 | return MultiByteToUnicodeString(s, CP_OEMCP); | 356 | MultiByteToUnicodeString2(dest, AString(s), CP_OEMCP); |
335 | } | 357 | } |
336 | 358 | ||
337 | UString CItem::GetShortName() const | 359 | void CItem::GetShortName(UString &shortName) const |
338 | { | 360 | { |
339 | char s[16]; | 361 | char s[16]; |
340 | unsigned i = CopyAndTrim(s, DosName, 8, NameIsLow()); | 362 | char *dest = CopyAndTrim(s, DosName, 8, NameIsLow()); |
341 | s[i++] = '.'; | 363 | *dest++ = '.'; |
342 | unsigned j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); | 364 | char *dest2 = CopyAndTrim(dest, DosName + 8, 3, ExtIsLow()); |
343 | if (j == 0) | 365 | if (dest == dest2) |
344 | i--; | 366 | dest[-1] = 0; |
345 | s[i + j] = 0; | 367 | FatStringToUnicode(shortName, s); |
346 | return FatStringToUnicode(s); | ||
347 | } | 368 | } |
348 | 369 | ||
349 | UString CItem::GetName() const | 370 | |
371 | |||
372 | // numWords != 0 | ||
373 | static unsigned ParseLongName(UInt16 *buf, unsigned numWords) | ||
350 | { | 374 | { |
351 | if (!UName.IsEmpty()) | 375 | unsigned i; |
352 | return UName; | 376 | for (i = 0; i < numWords; i++) |
353 | return GetShortName(); | 377 | { |
378 | const unsigned c = buf[i]; | ||
379 | if (c == 0) | ||
380 | break; | ||
381 | if (c == 0xFFFF) | ||
382 | return 0; | ||
383 | } | ||
384 | if (i == 0) | ||
385 | return 0; | ||
386 | buf[i] = 0; | ||
387 | numWords -= i; | ||
388 | i++; | ||
389 | if (numWords > 1) | ||
390 | { | ||
391 | numWords--; | ||
392 | buf += i; | ||
393 | do | ||
394 | if (*buf++ != 0xFFFF) | ||
395 | return 0; | ||
396 | while (--numWords); | ||
397 | } | ||
398 | return i; // it includes NULL terminator | ||
399 | } | ||
400 | |||
401 | |||
402 | void CItem::GetName(UString &name) const | ||
403 | { | ||
404 | if (LongName.Size() >= 2) | ||
405 | { | ||
406 | const Byte * const p = LongName; | ||
407 | const unsigned numWords = ((unsigned)LongName.Size() - 2) / 2; | ||
408 | wchar_t *dest = name.GetBuf(numWords); | ||
409 | for (unsigned i = 0; i < numWords; i++) | ||
410 | dest[i] = (wchar_t)Get16(p + (size_t)i * 2); | ||
411 | name.ReleaseBuf_SetEnd(numWords); | ||
412 | } | ||
413 | else | ||
414 | GetShortName(name); | ||
415 | if (name.IsEmpty()) // it's unexpected | ||
416 | name = '_'; | ||
417 | NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
354 | } | 418 | } |
355 | 419 | ||
356 | UString CItem::GetVolName() const | 420 | |
421 | static void GetVolName(const char dosName[11], NWindows::NCOM::CPropVariant &prop) | ||
357 | { | 422 | { |
358 | if (!UName.IsEmpty()) | ||
359 | return UName; | ||
360 | char s[12]; | 423 | char s[12]; |
361 | unsigned i = CopyAndTrim(s, DosName, 11, false); | 424 | CopyAndTrim(s, dosName, 11, false); |
362 | s[i] = 0; | 425 | UString u; |
363 | return FatStringToUnicode(s); | 426 | FatStringToUnicode(u, AString(s)); |
427 | prop = u; | ||
364 | } | 428 | } |
365 | 429 | ||
430 | |||
366 | struct CDatabase | 431 | struct CDatabase |
367 | { | 432 | { |
368 | CHeader Header; | ||
369 | CObjectVector<CItem> Items; | 433 | CObjectVector<CItem> Items; |
370 | UInt32 *Fat; | 434 | UInt32 *Fat; |
435 | CHeader Header; | ||
371 | CMyComPtr<IInStream> InStream; | 436 | CMyComPtr<IInStream> InStream; |
372 | IArchiveOpenCallback *OpenCallback; | 437 | IArchiveOpenCallback *OpenCallback; |
438 | CAlignedBuffer ByteBuf; | ||
439 | CByteBuffer LfnBuf; | ||
373 | 440 | ||
374 | UInt32 NumFreeClusters; | 441 | UInt32 NumFreeClusters; |
375 | bool VolItemDefined; | ||
376 | CItem VolItem; | ||
377 | UInt32 NumDirClusters; | 442 | UInt32 NumDirClusters; |
378 | CByteBuffer ByteBuf; | ||
379 | UInt64 NumCurUsedBytes; | 443 | UInt64 NumCurUsedBytes; |
380 | |||
381 | UInt64 PhySize; | 444 | UInt64 PhySize; |
382 | 445 | ||
446 | UInt32 Vol_MTime; | ||
447 | char VolLabel[11]; | ||
448 | bool VolItem_Defined; | ||
449 | |||
383 | CDatabase(): Fat(NULL) {} | 450 | CDatabase(): Fat(NULL) {} |
384 | ~CDatabase() { ClearAndClose(); } | 451 | ~CDatabase() { ClearAndClose(); } |
385 | 452 | ||
@@ -388,7 +455,7 @@ struct CDatabase | |||
388 | HRESULT OpenProgressFat(bool changeTotal = true); | 455 | HRESULT OpenProgressFat(bool changeTotal = true); |
389 | HRESULT OpenProgress(); | 456 | HRESULT OpenProgress(); |
390 | 457 | ||
391 | UString GetItemPath(UInt32 index) const; | 458 | void GetItemPath(UInt32 index, UString &s) const; |
392 | HRESULT Open(); | 459 | HRESULT Open(); |
393 | HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level); | 460 | HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level); |
394 | 461 | ||
@@ -400,6 +467,7 @@ struct CDatabase | |||
400 | HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); } | 467 | HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); } |
401 | }; | 468 | }; |
402 | 469 | ||
470 | |||
403 | HRESULT CDatabase::SeekToSector(UInt32 sector) | 471 | HRESULT CDatabase::SeekToSector(UInt32 sector) |
404 | { | 472 | { |
405 | return InStream_SeekSet(InStream, (UInt64)sector << Header.SectorSizeLog); | 473 | return InStream_SeekSet(InStream, (UInt64)sector << Header.SectorSizeLog); |
@@ -408,7 +476,7 @@ HRESULT CDatabase::SeekToSector(UInt32 sector) | |||
408 | void CDatabase::Clear() | 476 | void CDatabase::Clear() |
409 | { | 477 | { |
410 | PhySize = 0; | 478 | PhySize = 0; |
411 | VolItemDefined = false; | 479 | VolItem_Defined = false; |
412 | NumDirClusters = 0; | 480 | NumDirClusters = 0; |
413 | NumCurUsedBytes = 0; | 481 | NumCurUsedBytes = 0; |
414 | 482 | ||
@@ -440,49 +508,35 @@ HRESULT CDatabase::OpenProgress() | |||
440 | { | 508 | { |
441 | if (!OpenCallback) | 509 | if (!OpenCallback) |
442 | return S_OK; | 510 | return S_OK; |
443 | UInt64 numItems = Items.Size(); | 511 | const UInt64 numItems = Items.Size(); |
444 | return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes); | 512 | return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes); |
445 | } | 513 | } |
446 | 514 | ||
447 | UString CDatabase::GetItemPath(UInt32 index) const | 515 | void CDatabase::GetItemPath(UInt32 index, UString &s) const |
448 | { | 516 | { |
449 | const CItem *item = &Items[index]; | 517 | UString name; |
450 | UString name = item->GetName(); | ||
451 | for (;;) | 518 | for (;;) |
452 | { | 519 | { |
453 | index = (UInt32)item->Parent; | 520 | const CItem &item = Items[index]; |
454 | if (item->Parent < 0) | 521 | item.GetName(name); |
455 | return name; | 522 | if (item.Parent >= 0) |
456 | item = &Items[index]; | 523 | name.InsertAtFront(WCHAR_PATH_SEPARATOR); |
457 | name.InsertAtFront(WCHAR_PATH_SEPARATOR); | 524 | s.Insert(0, name); |
458 | if (item->UName.IsEmpty()) | 525 | index = (UInt32)item.Parent; |
459 | name.Insert(0, item->GetShortName()); | 526 | if (item.Parent < 0) |
460 | else | 527 | break; |
461 | name.Insert(0, item->UName); | ||
462 | } | 528 | } |
463 | } | 529 | } |
464 | 530 | ||
465 | static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, unsigned numChars) | ||
466 | { | ||
467 | for (unsigned i = 0; i < numChars; i++) | ||
468 | { | ||
469 | wchar_t c = Get16(p + i * 2); | ||
470 | if (c != 0 && c != 0xFFFF) | ||
471 | *dest++ = c; | ||
472 | } | ||
473 | *dest = 0; | ||
474 | return dest; | ||
475 | } | ||
476 | 531 | ||
477 | HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) | 532 | HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) |
478 | { | 533 | { |
479 | unsigned startIndex = Items.Size(); | 534 | const unsigned startIndex = Items.Size(); |
480 | if (startIndex >= (1 << 30) || level > 256) | 535 | if (startIndex >= (1 << 30) || level > 256) |
481 | return S_FALSE; | 536 | return S_FALSE; |
482 | 537 | ||
483 | UInt32 sectorIndex = 0; | ||
484 | UInt32 blockSize = Header.ClusterSize(); | 538 | UInt32 blockSize = Header.ClusterSize(); |
485 | bool clusterMode = (Header.IsFat32() || parent >= 0); | 539 | const bool clusterMode = (Header.IsFat32() || parent >= 0); |
486 | if (!clusterMode) | 540 | if (!clusterMode) |
487 | { | 541 | { |
488 | blockSize = Header.SectorSize(); | 542 | blockSize = Header.SectorSize(); |
@@ -490,21 +544,26 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) | |||
490 | } | 544 | } |
491 | 545 | ||
492 | ByteBuf.Alloc(blockSize); | 546 | ByteBuf.Alloc(blockSize); |
493 | UString curName; | 547 | |
494 | int checkSum = -1; | 548 | const unsigned k_NumLfnRecords_MAX = 20; // 260 symbols limit (strict limit) |
495 | int numLongRecords = -1; | 549 | // const unsigned k_NumLfnRecords_MAX = 0x40 - 1; // 1260 symbols limit (relaxed limit) |
550 | const unsigned k_NumLfnBytes_in_Record = 13 * 2; | ||
551 | // we reserve 2 additional bytes for NULL terminator | ||
552 | LfnBuf.Alloc(k_NumLfnRecords_MAX * k_NumLfnBytes_in_Record + 2 * 1); | ||
496 | 553 | ||
554 | UInt32 curDirBytes_read = 0; | ||
555 | UInt32 sectorIndex = 0; | ||
556 | unsigned num_lfn_records = 0; | ||
557 | unsigned lfn_RecordIndex = 0; | ||
558 | int checkSum = -1; | ||
559 | bool is_record_error = false; | ||
560 | |||
497 | for (UInt32 pos = blockSize;; pos += 32) | 561 | for (UInt32 pos = blockSize;; pos += 32) |
498 | { | 562 | { |
499 | if (pos == blockSize) | 563 | if (pos == blockSize) |
500 | { | 564 | { |
501 | pos = 0; | 565 | pos = 0; |
502 | 566 | ||
503 | if ((NumDirClusters & 0xFF) == 0) | ||
504 | { | ||
505 | RINOK(OpenProgress()) | ||
506 | } | ||
507 | |||
508 | if (clusterMode) | 567 | if (clusterMode) |
509 | { | 568 | { |
510 | if (Header.IsEoc(cluster)) | 569 | if (Header.IsEoc(cluster)) |
@@ -514,21 +573,37 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) | |||
514 | PRF(printf("\nCluster = %4X", cluster)); | 573 | PRF(printf("\nCluster = %4X", cluster)); |
515 | RINOK(SeekToCluster(cluster)) | 574 | RINOK(SeekToCluster(cluster)) |
516 | const UInt32 newCluster = Fat[cluster]; | 575 | const UInt32 newCluster = Fat[cluster]; |
517 | if ((newCluster & kFatItemUsedByDirMask) != 0) | 576 | if (newCluster & kFatItemUsedByDirMask) |
518 | return S_FALSE; | 577 | return S_FALSE; |
519 | Fat[cluster] |= kFatItemUsedByDirMask; | 578 | Fat[cluster] |= kFatItemUsedByDirMask; |
520 | cluster = newCluster; | 579 | cluster = newCluster; |
521 | NumDirClusters++; | 580 | NumDirClusters++; |
581 | if ((NumDirClusters & 0xFF) == 0) | ||
582 | { | ||
583 | RINOK(OpenProgress()) | ||
584 | } | ||
522 | NumCurUsedBytes += Header.ClusterSize(); | 585 | NumCurUsedBytes += Header.ClusterSize(); |
523 | } | 586 | } |
524 | else if (sectorIndex++ >= Header.NumRootDirSectors) | 587 | else if (sectorIndex++ >= Header.NumRootDirSectors) |
525 | break; | 588 | break; |
526 | 589 | ||
590 | // if (curDirBytes_read > (1u << 28)) // do we need some relaxed limit for non-MS FATs? | ||
591 | if (curDirBytes_read >= (1u << 21)) // 2MB limit from FAT specification. | ||
592 | return S_FALSE; | ||
527 | RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)) | 593 | RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)) |
594 | curDirBytes_read += blockSize; | ||
528 | } | 595 | } |
529 | 596 | ||
530 | const Byte *p = ByteBuf + pos; | 597 | if (is_record_error) |
531 | 598 | { | |
599 | Header.HeadersWarning = true; | ||
600 | num_lfn_records = 0; | ||
601 | lfn_RecordIndex = 0; | ||
602 | checkSum = -1; | ||
603 | } | ||
604 | |||
605 | const Byte * const p = ByteBuf + pos; | ||
606 | |||
532 | if (p[0] == 0) | 607 | if (p[0] == 0) |
533 | { | 608 | { |
534 | /* | 609 | /* |
@@ -538,125 +613,191 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) | |||
538 | */ | 613 | */ |
539 | break; | 614 | break; |
540 | } | 615 | } |
541 | 616 | ||
617 | is_record_error = true; | ||
618 | |||
542 | if (p[0] == 0xE5) | 619 | if (p[0] == 0xE5) |
543 | { | 620 | { |
544 | if (numLongRecords > 0) | 621 | // deleted entry |
545 | return S_FALSE; | 622 | if (num_lfn_records == 0) |
623 | is_record_error = false; | ||
546 | continue; | 624 | continue; |
547 | } | 625 | } |
548 | 626 | // else | |
549 | Byte attrib = p[11]; | ||
550 | if ((attrib & 0x3F) == 0xF) | ||
551 | { | 627 | { |
552 | if (p[0] > 0x7F || Get16(p + 26) != 0) | 628 | const Byte attrib = p[11]; |
553 | return S_FALSE; | 629 | // maybe we can use more strick check : (attrib == 0xF) ? |
554 | int longIndex = p[0] & 0x3F; | 630 | if ((attrib & 0x3F) == 0xF) |
555 | if (longIndex == 0) | ||
556 | return S_FALSE; | ||
557 | bool isLast = (p[0] & 0x40) != 0; | ||
558 | if (numLongRecords < 0) | ||
559 | { | 631 | { |
560 | if (!isLast) | 632 | // long file name (LFN) entry |
633 | const unsigned longIndex = p[0] & 0x3F; | ||
634 | if (longIndex == 0 | ||
635 | || longIndex > k_NumLfnRecords_MAX | ||
636 | || p[0] > 0x7F | ||
637 | || Get16a(p + 26) != 0 // LDIR_FstClusLO | ||
638 | ) | ||
639 | { | ||
561 | return S_FALSE; | 640 | return S_FALSE; |
562 | numLongRecords = longIndex; | 641 | // break; |
642 | } | ||
643 | const bool isLast = (p[0] & 0x40) != 0; | ||
644 | if (num_lfn_records == 0) | ||
645 | { | ||
646 | if (!isLast) | ||
647 | continue; // orphan | ||
648 | num_lfn_records = longIndex; | ||
649 | } | ||
650 | else if (isLast || longIndex != lfn_RecordIndex) | ||
651 | { | ||
652 | return S_FALSE; | ||
653 | // break; | ||
654 | } | ||
655 | |||
656 | lfn_RecordIndex = longIndex - 1; | ||
657 | |||
658 | if (p[12] == 0) | ||
659 | { | ||
660 | Byte * const dest = LfnBuf + k_NumLfnBytes_in_Record * lfn_RecordIndex; | ||
661 | memcpy(dest, p + 1, 5 * 2); | ||
662 | memcpy(dest + 5 * 2, p + 14, 6 * 2); | ||
663 | memcpy(dest + 11 * 2, p + 28, 2 * 2); | ||
664 | if (isLast) | ||
665 | checkSum = p[13]; | ||
666 | if (checkSum == p[13]) | ||
667 | is_record_error = false; | ||
668 | // else return S_FALSE; | ||
669 | continue; | ||
670 | } | ||
671 | // else | ||
672 | checkSum = -1; // we will ignore LfnBuf in this case | ||
673 | continue; | ||
563 | } | 674 | } |
564 | else if (isLast || numLongRecords != longIndex) | ||
565 | return S_FALSE; | ||
566 | |||
567 | numLongRecords--; | ||
568 | 675 | ||
569 | if (p[12] == 0) | 676 | if (lfn_RecordIndex) |
570 | { | 677 | { |
571 | wchar_t nameBuf[14]; | 678 | Header.HeadersWarning = true; |
572 | wchar_t *dest; | 679 | // return S_FALSE; |
573 | |||
574 | dest = AddSubStringToName(nameBuf, p + 1, 5); | ||
575 | dest = AddSubStringToName(dest, p + 14, 6); | ||
576 | AddSubStringToName(dest, p + 28, 2); | ||
577 | curName = nameBuf + curName; | ||
578 | if (isLast) | ||
579 | checkSum = p[13]; | ||
580 | if (checkSum != p[13]) | ||
581 | return S_FALSE; | ||
582 | } | 680 | } |
583 | } | 681 | // lfn_RecordIndex = 0; |
584 | else | ||
585 | { | ||
586 | if (numLongRecords > 0) | ||
587 | return S_FALSE; | ||
588 | CItem item; | ||
589 | memcpy(item.DosName, p, 11); | ||
590 | 682 | ||
591 | if (checkSum >= 0) | 683 | const unsigned type_in_attrib = attrib & 0x18; |
684 | if (type_in_attrib == 0x18) | ||
592 | { | 685 | { |
593 | Byte sum = 0; | 686 | // invalid directory record (both flags are set: dir_flag and volume_flag) |
594 | for (unsigned i = 0; i < 11; i++) | 687 | return S_FALSE; |
595 | sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]); | 688 | // break; |
596 | if (sum == checkSum) | 689 | // continue; |
597 | item.UName = curName; | ||
598 | } | 690 | } |
599 | 691 | if (type_in_attrib == 8) // volume_flag | |
600 | if (item.DosName[0] == 5) | ||
601 | item.DosName[0] = (char)(Byte)0xE5; | ||
602 | item.Attrib = attrib; | ||
603 | item.Flags = p[12]; | ||
604 | item.Size = Get32(p + 28); | ||
605 | item.Cluster = Get16(p + 26); | ||
606 | if (Header.NumFatBits > 16) | ||
607 | item.Cluster |= ((UInt32)Get16(p + 20) << 16); | ||
608 | else | ||
609 | { | 692 | { |
610 | // OS/2 and WinNT probably can store EA (extended atributes) in that field. | 693 | if (!VolItem_Defined && level == 0) |
694 | { | ||
695 | VolItem_Defined = true; | ||
696 | memcpy(VolLabel, p, 11); | ||
697 | Vol_MTime = Get32(p + 22); | ||
698 | is_record_error = false; | ||
699 | } | ||
611 | } | 700 | } |
612 | 701 | else if (memcmp(p, ". ", 11) == 0 | |
613 | item.CTime = Get32(p + 14); | 702 | || memcmp(p, ".. ", 11) == 0) |
614 | item.CTime2 = p[13]; | ||
615 | item.ADate = Get16(p + 18); | ||
616 | item.MTime = Get32(p + 22); | ||
617 | item.Parent = parent; | ||
618 | |||
619 | if (attrib == 8) | ||
620 | { | 703 | { |
621 | VolItem = item; | 704 | if (num_lfn_records == 0 && type_in_attrib == 0x10) // dir_flag |
622 | VolItemDefined = true; | 705 | is_record_error = false; |
623 | } | 706 | } |
624 | else | 707 | else |
625 | if (memcmp(item.DosName, ". ", 11) != 0 && | ||
626 | memcmp(item.DosName, ".. ", 11) != 0) | ||
627 | { | 708 | { |
628 | if (!item.IsDir()) | 709 | CItem &item = Items.AddNew(); |
629 | NumCurUsedBytes += Header.GetFilePackSize(item.Size); | 710 | memcpy(item.DosName, p, 11); |
630 | Items.Add(item); | 711 | if (item.DosName[0] == 5) |
631 | PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); | 712 | item.DosName[0] = (char)(Byte)0xE5; // 0xE5 is valid KANJI lead byte value. |
713 | item.Attrib = attrib; | ||
714 | item.Flags = p[12]; | ||
715 | item.Size = Get32a(p + 28); | ||
716 | item.Cluster = Get16a(p + 26); | ||
717 | if (Header.NumFatBits > 16) | ||
718 | item.Cluster |= ((UInt32)Get16a(p + 20) << 16); | ||
719 | else | ||
720 | { | ||
721 | // OS/2 and WinNT probably can store EA (extended atributes) in that field. | ||
722 | } | ||
723 | item.CTime = Get32(p + 14); | ||
724 | item.CTime2 = p[13]; | ||
725 | item.ADate = Get16a(p + 18); | ||
726 | item.MTime = Get32(p + 22); | ||
727 | item.Parent = parent; | ||
728 | { | ||
729 | if (!item.IsDir()) | ||
730 | NumCurUsedBytes += Header.GetFilePackSize(item.Size); | ||
731 | // PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1))); | ||
732 | PRF(printf("\n%7d" /* ": %S" */, Items.Size() /* , item.GetShortName() */ );) | ||
733 | } | ||
734 | if (num_lfn_records == 0) | ||
735 | is_record_error = false; | ||
736 | else if (checkSum >= 0 && lfn_RecordIndex == 0) | ||
737 | { | ||
738 | Byte sum = 0; | ||
739 | for (unsigned i = 0; i < 11; i++) | ||
740 | sum = (Byte)((sum << 7) + (sum >> 1) + (Byte)item.DosName[i]); | ||
741 | if (sum == checkSum) | ||
742 | { | ||
743 | const unsigned numWords = ParseLongName((UInt16 *)(void *)(Byte *)LfnBuf, | ||
744 | num_lfn_records * k_NumLfnBytes_in_Record / 2); | ||
745 | if (numWords > 1) | ||
746 | { | ||
747 | // numWords includes NULL terminator | ||
748 | item.LongName.CopyFrom(LfnBuf, numWords * 2); | ||
749 | is_record_error = false; | ||
750 | } | ||
751 | } | ||
752 | } | ||
753 | |||
754 | if ( | ||
755 | // item.LongName.Size() < 20 || // for debug | ||
756 | item.LongName.Size() <= 2 * 1 | ||
757 | && memcmp(p, " ", 11) == 0) | ||
758 | { | ||
759 | char s[16 + 16]; | ||
760 | const size_t numChars = (size_t)(ConvertUInt32ToString( | ||
761 | Items.Size() - 1 - startIndex, | ||
762 | MyStpCpy(s, "[NONAME]-")) - s) + 1; | ||
763 | item.LongName.Alloc(numChars * 2); | ||
764 | for (size_t i = 0; i < numChars; i++) | ||
765 | { | ||
766 | SetUi16a(item.LongName + i * 2, (Byte)s[i]) | ||
767 | } | ||
768 | Header.HeadersWarning = true; | ||
769 | } | ||
632 | } | 770 | } |
633 | numLongRecords = -1; | 771 | num_lfn_records = 0; |
634 | curName.Empty(); | ||
635 | checkSum = -1; | ||
636 | } | 772 | } |
637 | } | 773 | } |
638 | 774 | ||
639 | unsigned finishIndex = Items.Size(); | 775 | if (is_record_error) |
776 | Header.HeadersWarning = true; | ||
777 | |||
778 | const unsigned finishIndex = Items.Size(); | ||
640 | for (unsigned i = startIndex; i < finishIndex; i++) | 779 | for (unsigned i = startIndex; i < finishIndex; i++) |
641 | { | 780 | { |
642 | const CItem &item = Items[i]; | 781 | const CItem &item = Items[i]; |
643 | if (item.IsDir()) | 782 | if (item.IsDir()) |
644 | { | 783 | { |
645 | PRF(printf("\n%S", GetItemPath(i))); | 784 | PRF(printf("\n---- %c%c%c%c%c", item.DosName[0], item.DosName[1], item.DosName[2], item.DosName[3], item.DosName[4])); |
646 | RINOK(CDatabase::ReadDir((int)i, item.Cluster, level + 1)) | 785 | RINOK(ReadDir((int)i, item.Cluster, level + 1)) |
647 | } | 786 | } |
648 | } | 787 | } |
649 | return S_OK; | 788 | return S_OK; |
650 | } | 789 | } |
651 | 790 | ||
791 | |||
792 | |||
652 | HRESULT CDatabase::Open() | 793 | HRESULT CDatabase::Open() |
653 | { | 794 | { |
654 | Clear(); | 795 | Clear(); |
655 | bool numFreeClustersDefined = false; | 796 | bool numFreeClusters_Defined = false; |
656 | { | 797 | { |
657 | Byte buf[kHeaderSize]; | 798 | UInt32 buf32[kHeaderSize / 4]; |
658 | RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)) | 799 | RINOK(ReadStream_FALSE(InStream, buf32, kHeaderSize)) |
659 | if (!Header.Parse(buf)) | 800 | if (!Header.Parse((Byte *)(void *)buf32)) |
660 | return S_FALSE; | 801 | return S_FALSE; |
661 | UInt64 fileSize; | 802 | UInt64 fileSize; |
662 | RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize)) | 803 | RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize)) |
@@ -671,21 +812,21 @@ HRESULT CDatabase::Open() | |||
671 | { | 812 | { |
672 | if (((UInt32)Header.FsInfoSector << Header.SectorSizeLog) + kHeaderSize <= fileSize | 813 | if (((UInt32)Header.FsInfoSector << Header.SectorSizeLog) + kHeaderSize <= fileSize |
673 | && SeekToSector(Header.FsInfoSector) == S_OK | 814 | && SeekToSector(Header.FsInfoSector) == S_OK |
674 | && ReadStream_FALSE(InStream, buf, kHeaderSize) == S_OK | 815 | && ReadStream_FALSE(InStream, buf32, kHeaderSize) == S_OK |
675 | && 0xaa550000 == Get32(buf + 508) | 816 | && 0xaa550000 == Get32a(buf32 + 508 / 4) |
676 | && 0x41615252 == Get32(buf) | 817 | && 0x41615252 == Get32a(buf32) |
677 | && 0x61417272 == Get32(buf + 484)) | 818 | && 0x61417272 == Get32a(buf32 + 484 / 4)) |
678 | { | 819 | { |
679 | NumFreeClusters = Get32(buf + 488); | 820 | NumFreeClusters = Get32a(buf32 + 488 / 4); |
680 | numFreeClustersDefined = (NumFreeClusters <= Header.FatSize); | 821 | numFreeClusters_Defined = (NumFreeClusters <= Header.FatSize); |
681 | } | 822 | } |
682 | else | 823 | else |
683 | Header.HeadersWarning = true; | 824 | Header.HeadersWarning = true; |
684 | } | 825 | } |
685 | } | 826 | } |
686 | 827 | ||
687 | // numFreeClustersDefined = false; // to recalculate NumFreeClusters | 828 | // numFreeClusters_Defined = false; // to recalculate NumFreeClusters |
688 | if (!numFreeClustersDefined) | 829 | if (!numFreeClusters_Defined) |
689 | NumFreeClusters = 0; | 830 | NumFreeClusters = 0; |
690 | 831 | ||
691 | CByteBuffer byteBuf; | 832 | CByteBuffer byteBuf; |
@@ -695,7 +836,7 @@ HRESULT CDatabase::Open() | |||
695 | RINOK(SeekToSector(Header.GetFatSector())) | 836 | RINOK(SeekToSector(Header.GetFatSector())) |
696 | if (Header.NumFatBits == 32) | 837 | if (Header.NumFatBits == 32) |
697 | { | 838 | { |
698 | const UInt32 kBufSize = (1 << 15); | 839 | const UInt32 kBufSize = 1 << 15; |
699 | byteBuf.Alloc(kBufSize); | 840 | byteBuf.Alloc(kBufSize); |
700 | for (UInt32 i = 0;;) | 841 | for (UInt32 i = 0;;) |
701 | { | 842 | { |
@@ -712,7 +853,7 @@ HRESULT CDatabase::Open() | |||
712 | const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf; | 853 | const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf; |
713 | UInt32 *dest = Fat + i; | 854 | UInt32 *dest = Fat + i; |
714 | const UInt32 *srcLim = src + size; | 855 | const UInt32 *srcLim = src + size; |
715 | if (numFreeClustersDefined) | 856 | if (numFreeClusters_Defined) |
716 | do | 857 | do |
717 | *dest++ = Get32a(src) & 0x0FFFFFFF; | 858 | *dest++ = Get32a(src) & 0x0FFFFFFF; |
718 | while (++src != srcLim); | 859 | while (++src != srcLim); |
@@ -731,7 +872,7 @@ HRESULT CDatabase::Open() | |||
731 | i += size; | 872 | i += size; |
732 | if ((i & 0xFFFFF) == 0) | 873 | if ((i & 0xFFFFF) == 0) |
733 | { | 874 | { |
734 | RINOK(OpenProgressFat(!numFreeClustersDefined)) | 875 | RINOK(OpenProgressFat(!numFreeClusters_Defined)) |
735 | } | 876 | } |
736 | } | 877 | } |
737 | } | 878 | } |
@@ -751,7 +892,7 @@ HRESULT CDatabase::Open() | |||
751 | for (UInt32 j = 0; j < fatSize; j++) | 892 | for (UInt32 j = 0; j < fatSize; j++) |
752 | fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; | 893 | fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; |
753 | 894 | ||
754 | if (!numFreeClustersDefined) | 895 | if (!numFreeClusters_Defined) |
755 | { | 896 | { |
756 | UInt32 numFreeClusters = 0; | 897 | UInt32 numFreeClusters = 0; |
757 | for (UInt32 i = 0; i < fatSize; i++) | 898 | for (UInt32 i = 0; i < fatSize; i++) |
@@ -781,11 +922,12 @@ HRESULT CDatabase::Open() | |||
781 | 922 | ||
782 | Z7_class_CHandler_final: | 923 | Z7_class_CHandler_final: |
783 | public IInArchive, | 924 | public IInArchive, |
925 | public IArchiveGetRawProps, | ||
784 | public IInArchiveGetStream, | 926 | public IInArchiveGetStream, |
785 | public CMyUnknownImp, | 927 | public CMyUnknownImp, |
786 | CDatabase | 928 | CDatabase |
787 | { | 929 | { |
788 | Z7_IFACES_IMP_UNK_2(IInArchive, IInArchiveGetStream) | 930 | Z7_IFACES_IMP_UNK_3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream) |
789 | }; | 931 | }; |
790 | 932 | ||
791 | Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | 933 | Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) |
@@ -831,6 +973,8 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
831 | COM_TRY_END | 973 | COM_TRY_END |
832 | } | 974 | } |
833 | 975 | ||
976 | |||
977 | |||
834 | static const Byte kProps[] = | 978 | static const Byte kProps[] = |
835 | { | 979 | { |
836 | kpidPath, | 980 | kpidPath, |
@@ -842,6 +986,7 @@ static const Byte kProps[] = | |||
842 | kpidATime, | 986 | kpidATime, |
843 | kpidAttrib, | 987 | kpidAttrib, |
844 | kpidShortName | 988 | kpidShortName |
989 | // , kpidCharacts | ||
845 | }; | 990 | }; |
846 | 991 | ||
847 | enum | 992 | enum |
@@ -922,15 +1067,16 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
922 | case kpidPhySize: prop = PhySize; break; | 1067 | case kpidPhySize: prop = PhySize; break; |
923 | case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; | 1068 | case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break; |
924 | case kpidHeadersSize: prop = GetHeadersSize(); break; | 1069 | case kpidHeadersSize: prop = GetHeadersSize(); break; |
925 | case kpidMTime: if (VolItemDefined) PropVariant_SetFrom_DosTime(prop, VolItem.MTime); break; | 1070 | case kpidMTime: if (VolItem_Defined) PropVariant_SetFrom_DosTime(prop, Vol_MTime); break; |
926 | case kpidShortComment: | 1071 | case kpidShortComment: |
927 | case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break; | 1072 | case kpidVolumeName: if (VolItem_Defined) GetVolName(VolLabel, prop); break; |
928 | case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; | 1073 | case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break; |
929 | case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; | 1074 | case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; |
930 | // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; | 1075 | // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break; |
931 | // case kpidNumHeads: prop = Header.NumHeads; break; | 1076 | // case kpidNumHeads: prop = Header.NumHeads; break; |
932 | // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break; | 1077 | // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break; |
933 | case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break; | 1078 | case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break; |
1079 | case kpidIsTree: prop = true; break; | ||
934 | // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; | 1080 | // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; |
935 | // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; | 1081 | // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; |
936 | // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; | 1082 | // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; |
@@ -948,6 +1094,52 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
948 | COM_TRY_END | 1094 | COM_TRY_END |
949 | } | 1095 | } |
950 | 1096 | ||
1097 | |||
1098 | Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)) | ||
1099 | { | ||
1100 | *numProps = 0; | ||
1101 | return S_OK; | ||
1102 | } | ||
1103 | |||
1104 | Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */ , BSTR *name, PROPID *propID)) | ||
1105 | { | ||
1106 | *name = NULL; | ||
1107 | *propID = 0; | ||
1108 | return S_OK; | ||
1109 | } | ||
1110 | |||
1111 | Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)) | ||
1112 | { | ||
1113 | *parentType = NParentType::kDir; | ||
1114 | int par = -1; | ||
1115 | if (index < Items.Size()) | ||
1116 | par = Items[index].Parent; | ||
1117 | *parent = (UInt32)(Int32)par; | ||
1118 | return S_OK; | ||
1119 | } | ||
1120 | |||
1121 | Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) | ||
1122 | { | ||
1123 | *data = NULL; | ||
1124 | *dataSize = 0; | ||
1125 | *propType = 0; | ||
1126 | |||
1127 | if (index < Items.Size() | ||
1128 | && propID == kpidName) | ||
1129 | { | ||
1130 | CByteBuffer &buf = Items[index].LongName; | ||
1131 | const UInt32 size = (UInt32)buf.Size(); | ||
1132 | if (size != 0) | ||
1133 | { | ||
1134 | *dataSize = size; | ||
1135 | *propType = NPropDataType::kUtf16z; | ||
1136 | *data = (const void *)(const Byte *)buf; | ||
1137 | } | ||
1138 | } | ||
1139 | return S_OK; | ||
1140 | } | ||
1141 | |||
1142 | |||
951 | Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) | 1143 | Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) |
952 | { | 1144 | { |
953 | COM_TRY_BEGIN | 1145 | COM_TRY_BEGIN |
@@ -955,8 +1147,28 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
955 | const CItem &item = Items[index]; | 1147 | const CItem &item = Items[index]; |
956 | switch (propID) | 1148 | switch (propID) |
957 | { | 1149 | { |
958 | case kpidPath: prop = GetItemPath(index); break; | 1150 | case kpidPath: |
959 | case kpidShortName: prop = item.GetShortName(); break; | 1151 | case kpidName: |
1152 | case kpidShortName: | ||
1153 | { | ||
1154 | UString s; | ||
1155 | if (propID == kpidPath) | ||
1156 | GetItemPath(index, s); | ||
1157 | else if (propID == kpidName) | ||
1158 | item.GetName(s); | ||
1159 | else | ||
1160 | item.GetShortName(s); | ||
1161 | prop = s; | ||
1162 | break; | ||
1163 | } | ||
1164 | /* | ||
1165 | case kpidCharacts: | ||
1166 | { | ||
1167 | if (item.LongName.Size()) | ||
1168 | prop = "LFN"; | ||
1169 | break; | ||
1170 | } | ||
1171 | */ | ||
960 | case kpidIsDir: prop = item.IsDir(); break; | 1172 | case kpidIsDir: prop = item.IsDir(); break; |
961 | case kpidMTime: PropVariant_SetFrom_DosTime(prop, item.MTime); break; | 1173 | case kpidMTime: PropVariant_SetFrom_DosTime(prop, item.MTime); break; |
962 | case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; | 1174 | case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break; |
@@ -1004,34 +1216,44 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1004 | Int32 testMode, IArchiveExtractCallback *extractCallback)) | 1216 | Int32 testMode, IArchiveExtractCallback *extractCallback)) |
1005 | { | 1217 | { |
1006 | COM_TRY_BEGIN | 1218 | COM_TRY_BEGIN |
1007 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); | 1219 | if (numItems == (UInt32)(Int32)-1) |
1008 | if (allFilesMode) | 1220 | { |
1221 | indices = NULL; | ||
1009 | numItems = Items.Size(); | 1222 | numItems = Items.Size(); |
1010 | if (numItems == 0) | 1223 | if (numItems == 0) |
1011 | return S_OK; | 1224 | return S_OK; |
1012 | UInt32 i; | 1225 | } |
1226 | else | ||
1227 | { | ||
1228 | if (numItems == 0) | ||
1229 | return S_OK; | ||
1230 | if (!indices) | ||
1231 | return E_INVALIDARG; | ||
1232 | } | ||
1013 | UInt64 totalSize = 0; | 1233 | UInt64 totalSize = 0; |
1014 | for (i = 0; i < numItems; i++) | ||
1015 | { | 1234 | { |
1016 | const CItem &item = Items[allFilesMode ? i : indices[i]]; | 1235 | UInt32 i = 0; |
1017 | if (!item.IsDir()) | 1236 | do |
1018 | totalSize += item.Size; | 1237 | { |
1238 | UInt32 index = i; | ||
1239 | if (indices) | ||
1240 | index = indices[i]; | ||
1241 | const CItem &item = Items[index]; | ||
1242 | if (!item.IsDir()) | ||
1243 | totalSize += item.Size; | ||
1244 | } | ||
1245 | while (++i != numItems); | ||
1019 | } | 1246 | } |
1020 | RINOK(extractCallback->SetTotal(totalSize)) | 1247 | RINOK(extractCallback->SetTotal(totalSize)) |
1021 | 1248 | ||
1022 | UInt64 totalPackSize; | 1249 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
1023 | totalSize = totalPackSize = 0; | ||
1024 | |||
1025 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | ||
1026 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | ||
1027 | |||
1028 | CLocalProgress *lps = new CLocalProgress; | ||
1029 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
1030 | lps->Init(extractCallback, false); | 1250 | lps->Init(extractCallback, false); |
1251 | CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; | ||
1031 | 1252 | ||
1032 | CDummyOutStream *outStreamSpec = new CDummyOutStream; | 1253 | UInt64 totalPackSize; |
1033 | CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | 1254 | totalSize = totalPackSize = 0; |
1034 | 1255 | ||
1256 | UInt32 i; | ||
1035 | for (i = 0;; i++) | 1257 | for (i = 0;; i++) |
1036 | { | 1258 | { |
1037 | lps->InSize = totalPackSize; | 1259 | lps->InSize = totalPackSize; |
@@ -1039,46 +1261,45 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1039 | RINOK(lps->SetCur()) | 1261 | RINOK(lps->SetCur()) |
1040 | if (i == numItems) | 1262 | if (i == numItems) |
1041 | break; | 1263 | break; |
1042 | CMyComPtr<ISequentialOutStream> realOutStream; | 1264 | int res; |
1043 | const Int32 askMode = testMode ? | ||
1044 | NExtract::NAskMode::kTest : | ||
1045 | NExtract::NAskMode::kExtract; | ||
1046 | const UInt32 index = allFilesMode ? i : indices[i]; | ||
1047 | const CItem &item = Items[index]; | ||
1048 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | ||
1049 | |||
1050 | if (item.IsDir()) | ||
1051 | { | 1265 | { |
1266 | CMyComPtr<ISequentialOutStream> realOutStream; | ||
1267 | const Int32 askMode = testMode ? | ||
1268 | NExtract::NAskMode::kTest : | ||
1269 | NExtract::NAskMode::kExtract; | ||
1270 | UInt32 index = i; | ||
1271 | if (indices) | ||
1272 | index = indices[i]; | ||
1273 | const CItem &item = Items[index]; | ||
1274 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | ||
1275 | |||
1276 | if (item.IsDir()) | ||
1277 | { | ||
1278 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
1279 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
1280 | continue; | ||
1281 | } | ||
1282 | |||
1283 | totalPackSize += Header.GetFilePackSize(item.Size); | ||
1284 | totalSize += item.Size; | ||
1285 | |||
1286 | if (!testMode && !realOutStream) | ||
1287 | continue; | ||
1052 | RINOK(extractCallback->PrepareOperation(askMode)) | 1288 | RINOK(extractCallback->PrepareOperation(askMode)) |
1053 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | 1289 | res = NExtract::NOperationResult::kDataError; |
1054 | continue; | 1290 | CMyComPtr<ISequentialInStream> inStream; |
1055 | } | 1291 | const HRESULT hres = GetStream(index, &inStream); |
1056 | 1292 | if (hres != S_FALSE) | |
1057 | totalPackSize += Header.GetFilePackSize(item.Size); | ||
1058 | totalSize += item.Size; | ||
1059 | |||
1060 | if (!testMode && !realOutStream) | ||
1061 | continue; | ||
1062 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
1063 | |||
1064 | outStreamSpec->SetStream(realOutStream); | ||
1065 | realOutStream.Release(); | ||
1066 | outStreamSpec->Init(); | ||
1067 | |||
1068 | int res = NExtract::NOperationResult::kDataError; | ||
1069 | CMyComPtr<ISequentialInStream> inStream; | ||
1070 | HRESULT hres = GetStream(index, &inStream); | ||
1071 | if (hres != S_FALSE) | ||
1072 | { | ||
1073 | RINOK(hres) | ||
1074 | if (inStream) | ||
1075 | { | 1293 | { |
1076 | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) | 1294 | RINOK(hres) |
1077 | if (copyCoderSpec->TotalSize == item.Size) | 1295 | if (inStream) |
1078 | res = NExtract::NOperationResult::kOK; | 1296 | { |
1297 | RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps)) | ||
1298 | if (copyCoder->TotalSize == item.Size) | ||
1299 | res = NExtract::NOperationResult::kOK; | ||
1300 | } | ||
1079 | } | 1301 | } |
1080 | } | 1302 | } |
1081 | outStreamSpec->ReleaseStream(); | ||
1082 | RINOK(extractCallback->SetOperationResult(res)) | 1303 | RINOK(extractCallback->SetOperationResult(res)) |
1083 | } | 1304 | } |
1084 | return S_OK; | 1305 | return S_OK; |
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index 4049fbc..46e0239 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp | |||
@@ -25,6 +25,9 @@ | |||
25 | #define Get32(p) GetBe32(p) | 25 | #define Get32(p) GetBe32(p) |
26 | #define Get64(p) GetBe64(p) | 26 | #define Get64(p) GetBe64(p) |
27 | 27 | ||
28 | #define Get16a(p) GetBe16a(p) | ||
29 | #define Get32a(p) GetBe32a(p) | ||
30 | |||
28 | namespace NArchive { | 31 | namespace NArchive { |
29 | namespace NHfs { | 32 | namespace NHfs { |
30 | 33 | ||
@@ -104,23 +107,21 @@ UInt32 CFork::Calc_NumBlocks_from_Extents() const | |||
104 | { | 107 | { |
105 | UInt32 num = 0; | 108 | UInt32 num = 0; |
106 | FOR_VECTOR (i, Extents) | 109 | FOR_VECTOR (i, Extents) |
107 | { | ||
108 | num += Extents[i].NumBlocks; | 110 | num += Extents[i].NumBlocks; |
109 | } | ||
110 | return num; | 111 | return num; |
111 | } | 112 | } |
112 | 113 | ||
113 | bool CFork::Check_NumBlocks() const | 114 | bool CFork::Check_NumBlocks() const |
114 | { | 115 | { |
115 | UInt32 num = 0; | 116 | UInt32 num = NumBlocks; |
116 | FOR_VECTOR (i, Extents) | 117 | FOR_VECTOR (i, Extents) |
117 | { | 118 | { |
118 | UInt32 next = num + Extents[i].NumBlocks; | 119 | const UInt32 cur = Extents[i].NumBlocks; |
119 | if (next < num) | 120 | if (num < cur) |
120 | return false; | 121 | return false; |
121 | num = next; | 122 | num -= cur; |
122 | } | 123 | } |
123 | return num == NumBlocks; | 124 | return num == 0; |
124 | } | 125 | } |
125 | 126 | ||
126 | struct CIdIndexPair | 127 | struct CIdIndexPair |
@@ -175,7 +176,7 @@ static int Find_in_IdExtents(const CObjectVector<CIdExtents> &items, UInt32 id) | |||
175 | 176 | ||
176 | bool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id) | 177 | bool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id) |
177 | { | 178 | { |
178 | int index = Find_in_IdExtents(items, id); | 179 | const int index = Find_in_IdExtents(items, id); |
179 | if (index < 0) | 180 | if (index < 0) |
180 | return true; | 181 | return true; |
181 | const CIdExtents &item = items[index]; | 182 | const CIdExtents &item = items[index]; |
@@ -188,8 +189,13 @@ bool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id) | |||
188 | 189 | ||
189 | struct CVolHeader | 190 | struct CVolHeader |
190 | { | 191 | { |
191 | Byte Header[2]; | 192 | unsigned BlockSizeLog; |
192 | UInt16 Version; | 193 | UInt32 NumFiles; |
194 | UInt32 NumFolders; | ||
195 | UInt32 NumBlocks; | ||
196 | UInt32 NumFreeBlocks; | ||
197 | |||
198 | bool Is_Hsfx_ver5; | ||
193 | // UInt32 Attr; | 199 | // UInt32 Attr; |
194 | // UInt32 LastMountedVersion; | 200 | // UInt32 LastMountedVersion; |
195 | // UInt32 JournalInfoBlock; | 201 | // UInt32 JournalInfoBlock; |
@@ -199,19 +205,13 @@ struct CVolHeader | |||
199 | // UInt32 BackupTime; | 205 | // UInt32 BackupTime; |
200 | // UInt32 CheckedTime; | 206 | // UInt32 CheckedTime; |
201 | 207 | ||
202 | UInt32 NumFiles; | ||
203 | UInt32 NumFolders; | ||
204 | unsigned BlockSizeLog; | ||
205 | UInt32 NumBlocks; | ||
206 | UInt32 NumFreeBlocks; | ||
207 | |||
208 | // UInt32 WriteCount; | 208 | // UInt32 WriteCount; |
209 | // UInt32 FinderInfo[8]; | 209 | // UInt32 FinderInfo[8]; |
210 | // UInt64 VolID; | 210 | // UInt64 VolID; |
211 | 211 | ||
212 | UInt64 GetPhySize() const { return (UInt64)NumBlocks << BlockSizeLog; } | 212 | UInt64 GetPhySize() const { return (UInt64)NumBlocks << BlockSizeLog; } |
213 | UInt64 GetFreeSize() const { return (UInt64)NumFreeBlocks << BlockSizeLog; } | 213 | UInt64 GetFreeSize() const { return (UInt64)NumFreeBlocks << BlockSizeLog; } |
214 | bool IsHfsX() const { return Version > 4; } | 214 | bool IsHfsX() const { return Is_Hsfx_ver5; } |
215 | }; | 215 | }; |
216 | 216 | ||
217 | inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft) | 217 | inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft) |
@@ -463,18 +463,18 @@ public: | |||
463 | bool UnsupportedFeature; | 463 | bool UnsupportedFeature; |
464 | bool ThereAreAltStreams; | 464 | bool ThereAreAltStreams; |
465 | // bool CaseSensetive; | 465 | // bool CaseSensetive; |
466 | UInt32 MethodsMask; | ||
466 | UString ResFileName; | 467 | UString ResFileName; |
467 | 468 | ||
468 | UInt64 SpecOffset; | 469 | UInt64 SpecOffset; |
469 | UInt64 PhySize; | 470 | // UInt64 PhySize; |
470 | UInt64 PhySize2; | 471 | UInt64 PhySize2; |
471 | UInt64 ArcFileSize; | 472 | UInt64 ArcFileSize; |
472 | UInt32 MethodsMask; | ||
473 | 473 | ||
474 | void Clear() | 474 | void Clear() |
475 | { | 475 | { |
476 | SpecOffset = 0; | 476 | SpecOffset = 0; |
477 | PhySize = 0; | 477 | // PhySize = 0; |
478 | PhySize2 = 0; | 478 | PhySize2 = 0; |
479 | ArcFileSize = 0; | 479 | ArcFileSize = 0; |
480 | MethodsMask = 0; | 480 | MethodsMask = 0; |
@@ -596,7 +596,7 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt | |||
596 | { | 596 | { |
597 | if (fork.NumBlocks >= Header.NumBlocks) | 597 | if (fork.NumBlocks >= Header.NumBlocks) |
598 | return S_FALSE; | 598 | return S_FALSE; |
599 | if ((ArcFileSize >> Header.BlockSizeLog) + 1 < fork.NumBlocks) | 599 | if (((ArcFileSize - SpecOffset) >> Header.BlockSizeLog) + 1 < fork.NumBlocks) |
600 | return S_FALSE; | 600 | return S_FALSE; |
601 | 601 | ||
602 | const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; | 602 | const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; |
@@ -1328,28 +1328,26 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
1328 | return S_OK; | 1328 | return S_OK; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static const unsigned kHeaderPadSize = (1 << 10); | 1331 | static const unsigned kHeaderPadSize = 1 << 10; |
1332 | static const unsigned kMainHeaderSize = 512; | 1332 | static const unsigned kMainHeaderSize = 512; |
1333 | static const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize; | 1333 | static const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize; |
1334 | 1334 | ||
1335 | static const unsigned k_Signature_LE16_HFS_BD = 'B' + ((unsigned)'D' << 8); | ||
1336 | static const unsigned k_Signature_LE16_HPLUS = 'H' + ((unsigned)'+' << 8); | ||
1337 | static const UInt32 k_Signature_LE32_HFSP_VER4 = 'H' + ((UInt32)'+' << 8) + ((UInt32)4 << 24); | ||
1338 | static const UInt32 k_Signature_LE32_HFSX_VER5 = 'H' + ((UInt32)'X' << 8) + ((UInt32)5 << 24); | ||
1339 | |||
1335 | API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size) | 1340 | API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size) |
1336 | { | 1341 | { |
1337 | if (size < kHfsHeaderSize) | 1342 | if (size < kHfsHeaderSize) |
1338 | return k_IsArc_Res_NEED_MORE; | 1343 | return k_IsArc_Res_NEED_MORE; |
1339 | p += kHeaderPadSize; | 1344 | p += kHeaderPadSize; |
1340 | if (p[0] == 'B' && p[1] == 'D') | 1345 | const UInt32 sig = GetUi32(p); |
1341 | { | 1346 | if (sig != k_Signature_LE32_HFSP_VER4) |
1342 | if (p[0x7C] != 'H' || p[0x7C + 1] != '+') | 1347 | if (sig != k_Signature_LE32_HFSX_VER5) |
1343 | return k_IsArc_Res_NO; | 1348 | if ((UInt16)sig != k_Signature_LE16_HFS_BD |
1344 | } | 1349 | || GetUi16(p + 0x7c) != k_Signature_LE16_HPLUS) |
1345 | else | 1350 | return k_IsArc_Res_NO; |
1346 | { | ||
1347 | if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X')) | ||
1348 | return k_IsArc_Res_NO; | ||
1349 | UInt32 version = Get16(p + 2); | ||
1350 | if (version < 4 || version > 5) | ||
1351 | return k_IsArc_Res_NO; | ||
1352 | } | ||
1353 | return k_IsArc_Res_YES; | 1351 | return k_IsArc_Res_YES; |
1354 | } | 1352 | } |
1355 | } | 1353 | } |
@@ -1357,30 +1355,42 @@ API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size) | |||
1357 | HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) | 1355 | HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) |
1358 | { | 1356 | { |
1359 | Clear(); | 1357 | Clear(); |
1360 | Byte buf[kHfsHeaderSize]; | 1358 | UInt32 buf32[kHfsHeaderSize / 4]; |
1361 | RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize)) | 1359 | RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize)) |
1362 | { | 1360 | const Byte *p = (const Byte *)buf32 + kHeaderPadSize; |
1363 | for (unsigned i = 0; i < kHeaderPadSize; i++) | ||
1364 | if (buf[i] != 0) | ||
1365 | return S_FALSE; | ||
1366 | } | ||
1367 | const Byte *p = buf + kHeaderPadSize; | ||
1368 | CVolHeader &h = Header; | 1361 | CVolHeader &h = Header; |
1369 | 1362 | ||
1370 | h.Header[0] = p[0]; | 1363 | if (GetUi16a(p) == k_Signature_LE16_HFS_BD) |
1371 | h.Header[1] = p[1]; | ||
1372 | |||
1373 | if (p[0] == 'B' && p[1] == 'D') | ||
1374 | { | 1364 | { |
1375 | /* | 1365 | /* |
1376 | It's header for old HFS format. | 1366 | It's header for old HFS format. |
1377 | We don't support old HFS format, but we support | 1367 | We don't support old HFS format, but we support |
1378 | special HFS volume that contains embedded HFS+ volume | 1368 | special HFS volume that contains embedded HFS+ volume. |
1369 | HFS MDB : Master directory block | ||
1370 | HFS VIB : Volume information block | ||
1371 | some old images contain boot data with "LK" signature at start of buf32. | ||
1379 | */ | 1372 | */ |
1380 | 1373 | #if 1 | |
1381 | if (p[0x7C] != 'H' || p[0x7C + 1] != '+') | 1374 | // here we check first bytes of archive, |
1375 | // because start data can contain signature of some another | ||
1376 | // archive type that could have priority over HFS. | ||
1377 | const void *buf_ptr = (const void *)buf32; | ||
1378 | const unsigned sig = GetUi16a(buf_ptr); | ||
1379 | if (sig != 'L' + ((unsigned)'K' << 8)) | ||
1380 | { | ||
1381 | // some old HFS (non HFS+) files have no "LK" signature, | ||
1382 | // but have non-zero data after 2 first bytes in start 1 KiB. | ||
1383 | if (sig != 0) | ||
1384 | return S_FALSE; | ||
1385 | /* | ||
1386 | for (unsigned i = 0; i < kHeaderPadSize / 4; i++) | ||
1387 | if (buf32[i] != 0) | ||
1388 | return S_FALSE; | ||
1389 | */ | ||
1390 | } | ||
1391 | #endif | ||
1392 | if (GetUi16a(p + 0x7c) != k_Signature_LE16_HPLUS) // signature of embedded HFS+ volume | ||
1382 | return S_FALSE; | 1393 | return S_FALSE; |
1383 | |||
1384 | /* | 1394 | /* |
1385 | h.CTime = Get32(p + 0x2); | 1395 | h.CTime = Get32(p + 0x2); |
1386 | h.MTime = Get32(p + 0x6); | 1396 | h.MTime = Get32(p + 0x6); |
@@ -1399,80 +1409,104 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) | |||
1399 | h.NumFreeBlocks = Get16(p + 0x22); | 1409 | h.NumFreeBlocks = Get16(p + 0x22); |
1400 | */ | 1410 | */ |
1401 | 1411 | ||
1402 | UInt32 blockSize = Get32(p + 0x14); | 1412 | // v24.09: blockSize in old HFS image can be non-power of 2. |
1403 | 1413 | const UInt32 blockSize = Get32a(p + 0x14); // drAlBlkSiz | |
1404 | { | 1414 | if (blockSize == 0 || (blockSize & 0x1ff)) |
1405 | unsigned i; | 1415 | return S_FALSE; |
1406 | for (i = 9; ((UInt32)1 << i) != blockSize; i++) | 1416 | const unsigned numBlocks = Get16a(p + 0x12); // drNmAlBlks |
1407 | if (i == 31) | 1417 | // UInt16 drFreeBks = Get16a(p + 0x22); // number of unused allocation blocks |
1408 | return S_FALSE; | ||
1409 | h.BlockSizeLog = i; | ||
1410 | } | ||
1411 | |||
1412 | h.NumBlocks = Get16(p + 0x12); | ||
1413 | /* | 1418 | /* |
1414 | we suppose that it has the follwing layout | 1419 | we suppose that it has the following layout: |
1415 | { | 1420 | { |
1416 | start block with header | 1421 | start data with header |
1417 | [h.NumBlocks] | 1422 | blocks[h.NumBlocks] |
1418 | end block with header | 1423 | end data with header (probably size_of_footer <= blockSize). |
1419 | } | 1424 | } |
1420 | */ | 1425 | */ |
1421 | PhySize2 = ((UInt64)h.NumBlocks + 2) << h.BlockSizeLog; | 1426 | // PhySize2 = ((UInt64)numBlocks + 2) * blockSize; |
1422 | 1427 | const unsigned sector_of_FirstBlock = Get16a(p + 0x1c); // drAlBlSt : first allocation block in volume | |
1423 | UInt32 startBlock = Get16(p + 0x7C + 2); | 1428 | const UInt32 startBlock = Get16a(p + 0x7c + 2); |
1424 | UInt32 blockCount = Get16(p + 0x7C + 4); | 1429 | const UInt32 blockCount = Get16a(p + 0x7c + 4); |
1425 | SpecOffset = (UInt64)(1 + startBlock) << h.BlockSizeLog; | 1430 | SpecOffset = (UInt32)sector_of_FirstBlock << 9; // it's 32-bit here |
1426 | UInt64 phy = SpecOffset + ((UInt64)blockCount << h.BlockSizeLog); | 1431 | PhySize2 = SpecOffset + (UInt64)numBlocks * blockSize; |
1432 | SpecOffset += (UInt64)startBlock * blockSize; | ||
1433 | // before v24.09: // SpecOffset = (UInt64)(1 + startBlock) * blockSize; | ||
1434 | const UInt64 phy = SpecOffset + (UInt64)blockCount * blockSize; | ||
1427 | if (PhySize2 < phy) | 1435 | if (PhySize2 < phy) |
1428 | PhySize2 = phy; | 1436 | PhySize2 = phy; |
1437 | UInt32 tail = 1 << 10; // at least 1 KiB tail (for footer MDB) is expected. | ||
1438 | if (tail < blockSize) | ||
1439 | tail = blockSize; | ||
1440 | RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize)) | ||
1441 | if (ArcFileSize > PhySize2 && | ||
1442 | ArcFileSize - PhySize2 <= tail) | ||
1443 | { | ||
1444 | // data after blocks[h.NumBlocks] must contain another copy of MDB. | ||
1445 | // In example where blockSize is not power of 2, we have | ||
1446 | // (ArcFileSize - PhySize2) < blockSize. | ||
1447 | // We suppose that data after blocks[h.NumBlocks] is part of HFS archive. | ||
1448 | // Maybe we should scan for footer MDB data (in last 1 KiB)? | ||
1449 | PhySize2 = ArcFileSize; | ||
1450 | } | ||
1429 | RINOK(InStream_SeekSet(inStream, SpecOffset)) | 1451 | RINOK(InStream_SeekSet(inStream, SpecOffset)) |
1430 | RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize)) | 1452 | RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize)) |
1431 | } | 1453 | } |
1432 | 1454 | ||
1433 | if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X')) | 1455 | // HFS+ / HFSX volume header (starting from offset==1024): |
1434 | return S_FALSE; | ||
1435 | h.Version = Get16(p + 2); | ||
1436 | if (h.Version < 4 || h.Version > 5) | ||
1437 | return S_FALSE; | ||
1438 | |||
1439 | // h.Attr = Get32(p + 4); | ||
1440 | // h.LastMountedVersion = Get32(p + 8); | ||
1441 | // h.JournalInfoBlock = Get32(p + 0xC); | ||
1442 | |||
1443 | h.CTime = Get32(p + 0x10); | ||
1444 | h.MTime = Get32(p + 0x14); | ||
1445 | // h.BackupTime = Get32(p + 0x18); | ||
1446 | // h.CheckedTime = Get32(p + 0x1C); | ||
1447 | |||
1448 | h.NumFiles = Get32(p + 0x20); | ||
1449 | h.NumFolders = Get32(p + 0x24); | ||
1450 | |||
1451 | if (h.NumFolders > ((UInt32)1 << 29) || | ||
1452 | h.NumFiles > ((UInt32)1 << 30)) | ||
1453 | return S_FALSE; | ||
1454 | |||
1455 | RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize)) | ||
1456 | |||
1457 | if (progress) | ||
1458 | { | 1456 | { |
1459 | const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; | 1457 | // v24.09: we use strict condition test for pair signature(Version): |
1460 | RINOK(progress->SetTotal(&numFiles, NULL)) | 1458 | // H+(4), HX(5): |
1459 | const UInt32 sig = GetUi32a(p); | ||
1460 | // h.Version = Get16(p + 2); | ||
1461 | h.Is_Hsfx_ver5 = false; | ||
1462 | if (sig != k_Signature_LE32_HFSP_VER4) | ||
1463 | { | ||
1464 | if (sig != k_Signature_LE32_HFSX_VER5) | ||
1465 | return S_FALSE; | ||
1466 | h.Is_Hsfx_ver5 = true; | ||
1467 | } | ||
1461 | } | 1468 | } |
1462 | |||
1463 | UInt32 blockSize = Get32(p + 0x28); | ||
1464 | |||
1465 | { | 1469 | { |
1470 | const UInt32 blockSize = Get32a(p + 0x28); | ||
1466 | unsigned i; | 1471 | unsigned i; |
1467 | for (i = 9; ((UInt32)1 << i) != blockSize; i++) | 1472 | for (i = 9; ((UInt32)1 << i) != blockSize; i++) |
1468 | if (i == 31) | 1473 | if (i == 31) |
1469 | return S_FALSE; | 1474 | return S_FALSE; |
1470 | h.BlockSizeLog = i; | 1475 | h.BlockSizeLog = i; |
1471 | } | 1476 | } |
1477 | #if 1 | ||
1478 | // HFS Plus DOCs: The first 1024 bytes are reserved for use as boot blocks | ||
1479 | // v24.09: we don't check starting 1 KiB before old (HFS MDB) block ("BD" signture) . | ||
1480 | // but we still check starting 1 KiB before HFS+ / HFSX volume header. | ||
1481 | // are there HFS+ / HFSX images with non-zero data in this reserved area? | ||
1482 | { | ||
1483 | for (unsigned i = 0; i < kHeaderPadSize / 4; i++) | ||
1484 | if (buf32[i] != 0) | ||
1485 | return S_FALSE; | ||
1486 | } | ||
1487 | #endif | ||
1488 | // h.Attr = Get32a(p + 4); | ||
1489 | // h.LastMountedVersion = Get32a(p + 8); | ||
1490 | // h.JournalInfoBlock = Get32a(p + 0xC); | ||
1491 | h.CTime = Get32a(p + 0x10); | ||
1492 | h.MTime = Get32a(p + 0x14); | ||
1493 | // h.BackupTime = Get32a(p + 0x18); | ||
1494 | // h.CheckedTime = Get32a(p + 0x1C); | ||
1495 | h.NumFiles = Get32a(p + 0x20); | ||
1496 | h.NumFolders = Get32a(p + 0x24); | ||
1497 | if (h.NumFolders > ((UInt32)1 << 29) || | ||
1498 | h.NumFiles > ((UInt32)1 << 30)) | ||
1499 | return S_FALSE; | ||
1472 | 1500 | ||
1473 | h.NumBlocks = Get32(p + 0x2C); | 1501 | RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize)) |
1474 | h.NumFreeBlocks = Get32(p + 0x30); | 1502 | if (progress) |
1503 | { | ||
1504 | const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; | ||
1505 | RINOK(progress->SetTotal(&numFiles, NULL)) | ||
1506 | } | ||
1475 | 1507 | ||
1508 | h.NumBlocks = Get32a(p + 0x2C); | ||
1509 | h.NumFreeBlocks = Get32a(p + 0x30); | ||
1476 | /* | 1510 | /* |
1477 | h.NextCalatlogNodeID = Get32(p + 0x40); | 1511 | h.NextCalatlogNodeID = Get32(p + 0x40); |
1478 | h.WriteCount = Get32(p + 0x44); | 1512 | h.WriteCount = Get32(p + 0x44); |
@@ -1495,7 +1529,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) | |||
1495 | HeadersError = true; | 1529 | HeadersError = true; |
1496 | else | 1530 | else |
1497 | { | 1531 | { |
1498 | HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents); | 1532 | const HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents); |
1499 | if (res == S_FALSE) | 1533 | if (res == S_FALSE) |
1500 | HeadersError = true; | 1534 | HeadersError = true; |
1501 | else if (res != S_OK) | 1535 | else if (res != S_OK) |
@@ -1515,7 +1549,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) | |||
1515 | 1549 | ||
1516 | RINOK(LoadCatalog(catalogFork, overflowExtents, inStream, progress)) | 1550 | RINOK(LoadCatalog(catalogFork, overflowExtents, inStream, progress)) |
1517 | 1551 | ||
1518 | PhySize = Header.GetPhySize(); | 1552 | // PhySize = Header.GetPhySize(); |
1519 | return S_OK; | 1553 | return S_OK; |
1520 | } | 1554 | } |
1521 | 1555 | ||
@@ -1591,7 +1625,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
1591 | case kpidCharacts: MethodsMaskToProp(MethodsMask, prop); break; | 1625 | case kpidCharacts: MethodsMaskToProp(MethodsMask, prop); break; |
1592 | case kpidPhySize: | 1626 | case kpidPhySize: |
1593 | { | 1627 | { |
1594 | UInt64 v = SpecOffset + PhySize; | 1628 | UInt64 v = SpecOffset + Header.GetPhySize(); // PhySize; |
1595 | if (v < PhySize2) | 1629 | if (v < PhySize2) |
1596 | v = PhySize2; | 1630 | v = PhySize2; |
1597 | prop = v; | 1631 | prop = v; |
@@ -2529,7 +2563,7 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream) | |||
2529 | return S_FALSE; | 2563 | return S_FALSE; |
2530 | } | 2564 | } |
2531 | CSeekExtent se; | 2565 | CSeekExtent se; |
2532 | se.Phy = (UInt64)e.Pos << Header.BlockSizeLog; | 2566 | se.Phy = SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog); |
2533 | se.Virt = virt; | 2567 | se.Virt = virt; |
2534 | virt += cur; | 2568 | virt += cur; |
2535 | rem -= cur; | 2569 | rem -= cur; |
@@ -2540,7 +2574,7 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream) | |||
2540 | return S_FALSE; | 2574 | return S_FALSE; |
2541 | 2575 | ||
2542 | CSeekExtent se; | 2576 | CSeekExtent se; |
2543 | se.Phy = 0; | 2577 | se.Phy = 0; // = SpecOffset ? |
2544 | se.Virt = virt; | 2578 | se.Virt = virt; |
2545 | extentStream->Extents.Add(se); | 2579 | extentStream->Extents.Add(se); |
2546 | extentStream->Stream = _stream; | 2580 | extentStream->Stream = _stream; |
diff --git a/CPP/7zip/Archive/LpHandler.cpp b/CPP/7zip/Archive/LpHandler.cpp index c1a76b4..926b654 100644 --- a/CPP/7zip/Archive/LpHandler.cpp +++ b/CPP/7zip/Archive/LpHandler.cpp | |||
@@ -460,9 +460,11 @@ struct LpMetadataHeader | |||
460 | 460 | ||
461 | static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum) | 461 | static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum) |
462 | { | 462 | { |
463 | MY_ALIGN (16) | ||
463 | CSha256 sha; | 464 | CSha256 sha; |
464 | Sha256_Init(&sha); | 465 | Sha256_Init(&sha); |
465 | Sha256_Update(&sha, data, size); | 466 | Sha256_Update(&sha, data, size); |
467 | MY_ALIGN (16) | ||
466 | Byte calced[32]; | 468 | Byte calced[32]; |
467 | Sha256_Final(&sha, calced); | 469 | Sha256_Final(&sha, calced); |
468 | return memcmp(checksum, calced, 32) == 0; | 470 | return memcmp(checksum, calced, 32) == 0; |
@@ -470,6 +472,7 @@ static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum) | |||
470 | 472 | ||
471 | static bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset) | 473 | static bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset) |
472 | { | 474 | { |
475 | MY_ALIGN (4) | ||
473 | Byte checksum[32]; | 476 | Byte checksum[32]; |
474 | Byte *shaData = &data[hashOffset]; | 477 | Byte *shaData = &data[hashOffset]; |
475 | memcpy(checksum, shaData, 32); | 478 | memcpy(checksum, shaData, 32); |
@@ -528,6 +531,7 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
528 | { | 531 | { |
529 | RINOK(InStream_SeekSet(stream, LP_PARTITION_RESERVED_BYTES)) | 532 | RINOK(InStream_SeekSet(stream, LP_PARTITION_RESERVED_BYTES)) |
530 | { | 533 | { |
534 | MY_ALIGN (4) | ||
531 | Byte buf[k_Geometry_Size]; | 535 | Byte buf[k_Geometry_Size]; |
532 | RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size)) | 536 | RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size)) |
533 | if (memcmp(buf, k_Signature, k_SignatureSize) != 0) | 537 | if (memcmp(buf, k_Signature, k_SignatureSize) != 0) |
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index c9e2c01..194e5bf 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp | |||
@@ -4005,7 +4005,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
4005 | AddParam_Var(params[0]); | 4005 | AddParam_Var(params[0]); |
4006 | AString temp; | 4006 | AString temp; |
4007 | ReadString2(temp, params[1]); | 4007 | ReadString2(temp, params[1]); |
4008 | if (temp != "$TEMP") | 4008 | if (!temp.IsEqualTo("$TEMP")) |
4009 | SpaceQuStr(temp); | 4009 | SpaceQuStr(temp); |
4010 | break; | 4010 | break; |
4011 | } | 4011 | } |
@@ -4410,7 +4410,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
4410 | } | 4410 | } |
4411 | else | 4411 | else |
4412 | { | 4412 | { |
4413 | if (func == "DllUnregisterServer") | 4413 | if (func.IsEqualTo("DllUnregisterServer")) |
4414 | { | 4414 | { |
4415 | s += "UnRegDLL"; | 4415 | s += "UnRegDLL"; |
4416 | printFunc = false; | 4416 | printFunc = false; |
@@ -4418,7 +4418,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
4418 | else | 4418 | else |
4419 | { | 4419 | { |
4420 | s += "RegDLL"; | 4420 | s += "RegDLL"; |
4421 | if (func == "DllRegisterServer") | 4421 | if (func.IsEqualTo("DllRegisterServer")) |
4422 | printFunc = false; | 4422 | printFunc = false; |
4423 | } | 4423 | } |
4424 | AddParam(params[0]); | 4424 | AddParam(params[0]); |
@@ -4886,7 +4886,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
4886 | AddParam_Var(params[1]); | 4886 | AddParam_Var(params[1]); |
4887 | AddParam(params[2]); | 4887 | AddParam(params[2]); |
4888 | AddParam(params[4]); | 4888 | AddParam(params[4]); |
4889 | // if (params[2] == "0") AddCommentAndString("GetWinVer"); | 4889 | // if (params[2].IsEqualTo("0")) AddCommentAndString("GetWinVer"); |
4890 | } | 4890 | } |
4891 | else | 4891 | else |
4892 | s += "GetOsInfo"; | 4892 | s += "GetOsInfo"; |
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index d55521d..05c177f 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp | |||
@@ -1907,7 +1907,7 @@ HRESULT CDatabase::Open() | |||
1907 | for (i = 0; i < SecurityAttrs.Size(); i++) | 1907 | for (i = 0; i < SecurityAttrs.Size(); i++) |
1908 | { | 1908 | { |
1909 | const CAttr &attr = SecurityAttrs[i]; | 1909 | const CAttr &attr = SecurityAttrs[i]; |
1910 | if (attr.Name == L"$SII") | 1910 | if (attr.Name.IsEqualTo("$SII")) |
1911 | { | 1911 | { |
1912 | if (attr.Type == ATTR_TYPE_INDEX_ROOT) | 1912 | if (attr.Type == ATTR_TYPE_INDEX_ROOT) |
1913 | { | 1913 | { |
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 8a0ff05..79f89ef 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp | |||
@@ -2638,7 +2638,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
2638 | { | 2638 | { |
2639 | const CSection § = _sections[i]; | 2639 | const CSection § = _sections[i]; |
2640 | if (IsOpt()) | 2640 | if (IsOpt()) |
2641 | if (_parseResources && sect.Name == ".rsrc") | 2641 | if (_parseResources && sect.Name.IsEqualTo(".rsrc")) |
2642 | { | 2642 | { |
2643 | // 20.01: we try to parse only first copy of .rsrc section. | 2643 | // 20.01: we try to parse only first copy of .rsrc section. |
2644 | _parseResources = false; | 2644 | _parseResources = false; |
@@ -2727,7 +2727,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |||
2727 | for (i = 0; i < _mixItems.Size(); i++) | 2727 | for (i = 0; i < _mixItems.Size(); i++) |
2728 | { | 2728 | { |
2729 | const CMixItem &mixItem = _mixItems[i]; | 2729 | const CMixItem &mixItem = _mixItems[i]; |
2730 | if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_") | 2730 | if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name.IsEqualTo("_winzip_")) |
2731 | { | 2731 | { |
2732 | _mainSubfile = (Int32)(int)i; | 2732 | _mainSubfile = (Int32)(int)i; |
2733 | break; | 2733 | break; |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index 34615c2..a639d8b 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp | |||
@@ -393,6 +393,7 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) | |||
393 | if (!FindExtra_Link(link)) | 393 | if (!FindExtra_Link(link)) |
394 | return; | 394 | return; |
395 | 395 | ||
396 | bool isWindows = (HostOS == kHost_Windows); | ||
396 | if (link.Type != linkType) | 397 | if (link.Type != linkType) |
397 | { | 398 | { |
398 | if (linkType != NLinkType::kUnixSymLink) | 399 | if (linkType != NLinkType::kUnixSymLink) |
@@ -400,8 +401,11 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) | |||
400 | switch ((unsigned)link.Type) | 401 | switch ((unsigned)link.Type) |
401 | { | 402 | { |
402 | case NLinkType::kUnixSymLink: | 403 | case NLinkType::kUnixSymLink: |
404 | isWindows = false; | ||
405 | break; | ||
403 | case NLinkType::kWinSymLink: | 406 | case NLinkType::kWinSymLink: |
404 | case NLinkType::kWinJunction: | 407 | case NLinkType::kWinJunction: |
408 | isWindows = true; | ||
405 | break; | 409 | break; |
406 | default: return; | 410 | default: return; |
407 | } | 411 | } |
@@ -409,10 +413,15 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) | |||
409 | 413 | ||
410 | AString s; | 414 | AString s; |
411 | s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen); | 415 | s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen); |
412 | |||
413 | UString unicode; | 416 | UString unicode; |
414 | ConvertUTF8ToUnicode(s, unicode); | 417 | ConvertUTF8ToUnicode(s, unicode); |
415 | prop = NItemName::GetOsPath(unicode); | 418 | // rar5.0 used '\\' separator for windows symlinks and \??\ prefix for abs paths. |
419 | // rar5.1+ uses '/' separator for windows symlinks and /??/ prefix for abs paths. | ||
420 | // v25.00: we convert Windows slashes to Linux slashes: | ||
421 | if (isWindows) | ||
422 | unicode.Replace(L'\\', L'/'); | ||
423 | prop = unicode; | ||
424 | // prop = NItemName::GetOsPath(unicode); | ||
416 | } | 425 | } |
417 | 426 | ||
418 | bool CItem::GetAltStreamName(AString &name) const | 427 | bool CItem::GetAltStreamName(AString &name) const |
@@ -658,6 +667,9 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h) | |||
658 | RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2)) | 667 | RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2)) |
659 | memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE); | 668 | memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE); |
660 | RINOK(m_CryptoDecoder->Init()) | 669 | RINOK(m_CryptoDecoder->Init()) |
670 | // we call RAR5_AES_Filter with: | ||
671 | // data_ptr == aligned_ptr + 16 | ||
672 | // data_size == 16 | ||
661 | if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) | 673 | if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) |
662 | return E_FAIL; | 674 | return E_FAIL; |
663 | memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE); | 675 | memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE); |
@@ -689,10 +701,14 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h) | |||
689 | return E_OUTOFMEMORY; | 701 | return E_OUTOFMEMORY; |
690 | memcpy(_buf, buf, filled); | 702 | memcpy(_buf, buf, filled); |
691 | const size_t rem = size - filled; | 703 | const size_t rem = size - filled; |
704 | // if (m_CryptoMode), we add AES_BLOCK_SIZE here, because _iv is not included to size. | ||
692 | AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0)); | 705 | AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0)); |
693 | RINOK(ReadStream_Check(_buf + filled, rem)) | 706 | RINOK(ReadStream_Check(_buf + filled, rem)) |
694 | if (m_CryptoMode) | 707 | if (m_CryptoMode) |
695 | { | 708 | { |
709 | // we call RAR5_AES_Filter with: | ||
710 | // data_ptr == aligned_ptr + 16 | ||
711 | // (rem) can be big | ||
696 | if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem) | 712 | if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem) |
697 | return E_FAIL; | 713 | return E_FAIL; |
698 | #if 1 | 714 | #if 1 |
@@ -1065,7 +1081,8 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS | |||
1065 | 1081 | ||
1066 | CMyComPtr<ICompressSetDecoderProperties2> csdp; | 1082 | CMyComPtr<ICompressSetDecoderProperties2> csdp; |
1067 | RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp)) | 1083 | RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp)) |
1068 | 1084 | if (!csdp) | |
1085 | return E_NOTIMPL; | ||
1069 | const unsigned ver = item.Get_AlgoVersion_HuffRev(); | 1086 | const unsigned ver = item.Get_AlgoVersion_HuffRev(); |
1070 | if (ver > 1) | 1087 | if (ver > 1) |
1071 | return E_NOTIMPL; | 1088 | return E_NOTIMPL; |
@@ -3343,9 +3360,9 @@ Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVAR | |||
3343 | } | 3360 | } |
3344 | else if (name.IsPrefixedBy_Ascii_NoCase("memx")) | 3361 | else if (name.IsPrefixedBy_Ascii_NoCase("memx")) |
3345 | { | 3362 | { |
3346 | UInt64 memAvail; | 3363 | size_t memAvail; |
3347 | if (!NWindows::NSystem::GetRamSize(memAvail)) | 3364 | if (!NWindows::NSystem::GetRamSize(memAvail)) |
3348 | memAvail = (UInt64)(sizeof(size_t)) << 28; | 3365 | memAvail = (size_t)sizeof(size_t) << 28; |
3349 | UInt64 v; | 3366 | UInt64 v; |
3350 | if (!ParseSizeString(name.Ptr(4), prop, memAvail, v)) | 3367 | if (!ParseSizeString(name.Ptr(4), prop, memAvail, v)) |
3351 | return E_INVALIDARG; | 3368 | return E_INVALIDARG; |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h index 8f6581a..913ba85 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.h +++ b/CPP/7zip/Archive/Rar/Rar5Handler.h | |||
@@ -286,10 +286,10 @@ struct CItem | |||
286 | 286 | ||
287 | bool IsService() const { return RecordType == NHeaderType::kService; } | 287 | bool IsService() const { return RecordType == NHeaderType::kService; } |
288 | 288 | ||
289 | bool Is_STM() const { return IsService() && Name == "STM"; } | 289 | bool Is_STM() const { return IsService() && Name.IsEqualTo("STM"); } |
290 | bool Is_CMT() const { return IsService() && Name == "CMT"; } | 290 | bool Is_CMT() const { return IsService() && Name.IsEqualTo("CMT"); } |
291 | bool Is_ACL() const { return IsService() && Name == "ACL"; } | 291 | bool Is_ACL() const { return IsService() && Name.IsEqualTo("ACL"); } |
292 | // bool Is_QO() const { return IsService() && Name == "QO"; } | 292 | // bool Is_QO() const { return IsService() && Name.IsEqualTo("QO"); } |
293 | 293 | ||
294 | int FindExtra(unsigned extraID, unsigned &recordDataSize) const; | 294 | int FindExtra(unsigned extraID, unsigned &recordDataSize) const; |
295 | void PrintInfo(AString &s) const; | 295 | void PrintInfo(AString &s) const; |
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 9157acc..dfbad33 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp | |||
@@ -435,13 +435,13 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) | |||
435 | size -= sizeof(item.Salt); | 435 | size -= sizeof(item.Salt); |
436 | p += sizeof(item.Salt); | 436 | p += sizeof(item.Salt); |
437 | } | 437 | } |
438 | if (item.Name == "ACL" && size == 0) | 438 | if (item.Name.IsEqualTo("ACL") && size == 0) |
439 | { | 439 | { |
440 | item.IsAltStream = true; | 440 | item.IsAltStream = true; |
441 | item.Name.Empty(); | 441 | item.Name.Empty(); |
442 | item.UnicodeName.SetFromAscii(".ACL"); | 442 | item.UnicodeName.SetFromAscii(".ACL"); |
443 | } | 443 | } |
444 | else if (item.Name == "STM" && size != 0 && (size & 1) == 0) | 444 | else if (item.Name.IsEqualTo("STM") && size != 0 && (size & 1) == 0) |
445 | { | 445 | { |
446 | item.IsAltStream = true; | 446 | item.IsAltStream = true; |
447 | item.Name.Empty(); | 447 | item.Name.Empty(); |
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index da2b6ee..4f8aaaa 100644 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp | |||
@@ -330,11 +330,11 @@ void CHandler::AddSubFileExtension(AString &res) const | |||
330 | if (!_compressor.IsEmpty()) | 330 | if (!_compressor.IsEmpty()) |
331 | { | 331 | { |
332 | s = _compressor; | 332 | s = _compressor; |
333 | if (_compressor == "bzip2") | 333 | if (_compressor.IsEqualTo("bzip2")) |
334 | s = "bz2"; | 334 | s = "bz2"; |
335 | else if (_compressor == "gzip") | 335 | else if (_compressor.IsEqualTo("gzip")) |
336 | s = "gz"; | 336 | s = "gz"; |
337 | else if (_compressor == "zstd") | 337 | else if (_compressor.IsEqualTo("zstd")) |
338 | s = "zst"; | 338 | s = "zst"; |
339 | } | 339 | } |
340 | else | 340 | else |
diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp index 9c293a3..221af21 100644 --- a/CPP/7zip/Archive/VmdkHandler.cpp +++ b/CPP/7zip/Archive/VmdkHandler.cpp | |||
@@ -202,9 +202,12 @@ struct CExtentInfo | |||
202 | // PartitionUUID | 202 | // PartitionUUID |
203 | // DeviceIdentifier | 203 | // DeviceIdentifier |
204 | 204 | ||
205 | bool IsType_ZERO() const { return Type == "ZERO"; } | 205 | bool IsType_ZERO() const { return Type.IsEqualTo("ZERO"); } |
206 | // bool IsType_FLAT() const { return Type == "FLAT"; } | 206 | // bool IsType_FLAT() const { return Type.IsEqualTo("FLAT"); } |
207 | bool IsType_Flat() const { return Type == "FLAT" || Type == "VMFS" || Type == "VMFSRAW"; } | 207 | bool IsType_Flat() const |
208 | { return Type.IsEqualTo("FLAT") | ||
209 | || Type.IsEqualTo("VMFS") | ||
210 | || Type.IsEqualTo("VMFSRAW"); } | ||
208 | 211 | ||
209 | bool Parse(const char *s); | 212 | bool Parse(const char *s); |
210 | }; | 213 | }; |
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 614755a..a748e99 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp | |||
@@ -1814,7 +1814,7 @@ bool CWimXml::Parse() | |||
1814 | 1814 | ||
1815 | if (!Xml.Parse(utf)) | 1815 | if (!Xml.Parse(utf)) |
1816 | return false; | 1816 | return false; |
1817 | if (Xml.Root.Name != "WIM") | 1817 | if (!Xml.Root.Name.IsEqualTo("WIM")) |
1818 | return false; | 1818 | return false; |
1819 | 1819 | ||
1820 | FOR_VECTOR (i, Xml.Root.SubItems) | 1820 | FOR_VECTOR (i, Xml.Root.SubItems) |
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 5112a16..cba546e 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | #include "../../../C/Sha256.h" | 5 | #include "../../../C/Sha256.h" |
6 | #include "../../../C/Sha512.h" | ||
6 | #include "../../../C/CpuArch.h" | 7 | #include "../../../C/CpuArch.h" |
7 | 8 | ||
8 | #include "../../Common/ComTry.h" | 9 | #include "../../Common/ComTry.h" |
@@ -41,22 +42,33 @@ Z7_CLASS_IMP_NOQIB_1( | |||
41 | CInStreamWithSha256 | 42 | CInStreamWithSha256 |
42 | , ISequentialInStream | 43 | , ISequentialInStream |
43 | ) | 44 | ) |
45 | bool _sha512Mode; | ||
44 | CMyComPtr<ISequentialInStream> _stream; | 46 | CMyComPtr<ISequentialInStream> _stream; |
45 | CAlignedBuffer1 _sha; | 47 | CAlignedBuffer1 _sha256; |
48 | CAlignedBuffer1 _sha512; | ||
46 | UInt64 _size; | 49 | UInt64 _size; |
47 | 50 | ||
48 | CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; } | 51 | CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; } |
52 | CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; } | ||
49 | public: | 53 | public: |
50 | CInStreamWithSha256(): _sha(sizeof(CSha256)) {} | 54 | CInStreamWithSha256(): |
55 | _sha256(sizeof(CSha256)), | ||
56 | _sha512(sizeof(CSha512)) | ||
57 | {} | ||
51 | void SetStream(ISequentialInStream *stream) { _stream = stream; } | 58 | void SetStream(ISequentialInStream *stream) { _stream = stream; } |
52 | void Init() | 59 | void Init(bool sha512Mode) |
53 | { | 60 | { |
61 | _sha512Mode = sha512Mode; | ||
54 | _size = 0; | 62 | _size = 0; |
55 | Sha256_Init(Sha()); | 63 | if (sha512Mode) |
64 | Sha512_Init(Sha512(), SHA512_DIGEST_SIZE); | ||
65 | else | ||
66 | Sha256_Init(Sha256()); | ||
56 | } | 67 | } |
57 | void ReleaseStream() { _stream.Release(); } | 68 | void ReleaseStream() { _stream.Release(); } |
58 | UInt64 GetSize() const { return _size; } | 69 | UInt64 GetSize() const { return _size; } |
59 | void Final(Byte *digest) { Sha256_Final(Sha(), digest); } | 70 | void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); } |
71 | void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); } | ||
60 | }; | 72 | }; |
61 | 73 | ||
62 | Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize)) | 74 | Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize)) |
@@ -64,7 +76,10 @@ Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processe | |||
64 | UInt32 realProcessedSize; | 76 | UInt32 realProcessedSize; |
65 | const HRESULT result = _stream->Read(data, size, &realProcessedSize); | 77 | const HRESULT result = _stream->Read(data, size, &realProcessedSize); |
66 | _size += realProcessedSize; | 78 | _size += realProcessedSize; |
67 | Sha256_Update(Sha(), (const Byte *)data, realProcessedSize); | 79 | if (_sha512Mode) |
80 | Sha512_Update(Sha512(), (const Byte *)data, realProcessedSize); | ||
81 | else | ||
82 | Sha256_Update(Sha256(), (const Byte *)data, realProcessedSize); | ||
68 | if (processedSize) | 83 | if (processedSize) |
69 | *processedSize = realProcessedSize; | 84 | *processedSize = realProcessedSize; |
70 | return result; | 85 | return result; |
@@ -75,25 +90,33 @@ Z7_CLASS_IMP_NOQIB_1( | |||
75 | COutStreamWithSha256 | 90 | COutStreamWithSha256 |
76 | , ISequentialOutStream | 91 | , ISequentialOutStream |
77 | ) | 92 | ) |
78 | // bool _calculate; | 93 | bool _sha512Mode; |
79 | CMyComPtr<ISequentialOutStream> _stream; | 94 | CMyComPtr<ISequentialOutStream> _stream; |
80 | CAlignedBuffer1 _sha; | 95 | CAlignedBuffer1 _sha256; |
96 | CAlignedBuffer1 _sha512; | ||
81 | UInt64 _size; | 97 | UInt64 _size; |
82 | 98 | ||
83 | CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; } | 99 | CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; } |
100 | CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; } | ||
84 | public: | 101 | public: |
85 | COutStreamWithSha256(): _sha(sizeof(CSha256)) {} | 102 | COutStreamWithSha256(): |
103 | _sha256(sizeof(CSha256)), | ||
104 | _sha512(sizeof(CSha512)) | ||
105 | {} | ||
86 | void SetStream(ISequentialOutStream *stream) { _stream = stream; } | 106 | void SetStream(ISequentialOutStream *stream) { _stream = stream; } |
87 | void ReleaseStream() { _stream.Release(); } | 107 | void ReleaseStream() { _stream.Release(); } |
88 | void Init(/* bool calculate = true */ ) | 108 | void Init(bool sha512Mode) |
89 | { | 109 | { |
90 | // _calculate = calculate; | 110 | _sha512Mode = sha512Mode; |
91 | _size = 0; | 111 | _size = 0; |
92 | Sha256_Init(Sha()); | 112 | if (sha512Mode) |
113 | Sha512_Init(Sha512(), SHA512_DIGEST_SIZE); | ||
114 | else | ||
115 | Sha256_Init(Sha256()); | ||
93 | } | 116 | } |
94 | void InitSha256() { Sha256_Init(Sha()); } | ||
95 | UInt64 GetSize() const { return _size; } | 117 | UInt64 GetSize() const { return _size; } |
96 | void Final(Byte *digest) { Sha256_Final(Sha(), digest); } | 118 | void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); } |
119 | void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); } | ||
97 | }; | 120 | }; |
98 | 121 | ||
99 | Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize)) | 122 | Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize)) |
@@ -102,7 +125,10 @@ Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 * | |||
102 | if (_stream) | 125 | if (_stream) |
103 | result = _stream->Write(data, size, &size); | 126 | result = _stream->Write(data, size, &size); |
104 | // if (_calculate) | 127 | // if (_calculate) |
105 | Sha256_Update(Sha(), (const Byte *)data, size); | 128 | if (_sha512Mode) |
129 | Sha512_Update(Sha512(), (const Byte *)data, size); | ||
130 | else | ||
131 | Sha256_Update(Sha256(), (const Byte *)data, size); | ||
106 | _size += size; | 132 | _size += size; |
107 | if (processedSize) | 133 | if (processedSize) |
108 | *processedSize = size; | 134 | *processedSize = size; |
@@ -240,7 +266,7 @@ struct CFile | |||
240 | 266 | ||
241 | bool IsCopyMethod() const | 267 | bool IsCopyMethod() const |
242 | { | 268 | { |
243 | return Method.IsEmpty() || Method == "octet-stream"; | 269 | return Method.IsEmpty() || Method.IsEqualTo("octet-stream"); |
244 | } | 270 | } |
245 | 271 | ||
246 | void UpdateTotalPackSize(UInt64 &totalSize) const | 272 | void UpdateTotalPackSize(UInt64 &totalSize) const |
@@ -390,7 +416,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren | |||
390 | return true; | 416 | return true; |
391 | if (level >= 1024) | 417 | if (level >= 1024) |
392 | return false; | 418 | return false; |
393 | if (item.Name == "file") | 419 | if (item.Name.IsEqualTo("file")) |
394 | { | 420 | { |
395 | CFile file(parent); | 421 | CFile file(parent); |
396 | parent = (int)files.Size(); | 422 | parent = (int)files.Size(); |
@@ -409,19 +435,19 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren | |||
409 | { | 435 | { |
410 | file.Type = typeItem->GetSubString(); | 436 | file.Type = typeItem->GetSubString(); |
411 | // file.LinkFrom = typeItem->GetPropVal("link"); | 437 | // file.LinkFrom = typeItem->GetPropVal("link"); |
412 | if (file.Type == "directory") | 438 | if (file.Type.IsEqualTo("directory")) |
413 | file.IsDir = true; | 439 | file.IsDir = true; |
414 | else | 440 | else |
415 | { | 441 | { |
416 | // file.IsDir = false; | 442 | // file.IsDir = false; |
417 | /* | 443 | /* |
418 | else if (file.Type == "file") | 444 | else if (file.Type.IsEqualTo("file")) |
419 | {} | 445 | {} |
420 | else if (file.Type == "hardlink") | 446 | else if (file.Type.IsEqualTo("hardlink")) |
421 | {} | 447 | {} |
422 | else | 448 | else |
423 | */ | 449 | */ |
424 | if (file.Type == "symlink") | 450 | if (file.Type.IsEqualTo("symlink")) |
425 | file.Is_SymLink = true; | 451 | file.Is_SymLink = true; |
426 | // file.IsDir = false; | 452 | // file.IsDir = false; |
427 | } | 453 | } |
@@ -463,7 +489,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren | |||
463 | if (s.IsPrefixedBy(xx)) | 489 | if (s.IsPrefixedBy(xx)) |
464 | { | 490 | { |
465 | s.DeleteFrontal(xx.Len()); | 491 | s.DeleteFrontal(xx.Len()); |
466 | if (s == "gzip") | 492 | if (s.IsEqualTo("gzip")) |
467 | s = METHOD_NAME_ZLIB; | 493 | s = METHOD_NAME_ZLIB; |
468 | } | 494 | } |
469 | } | 495 | } |
@@ -521,10 +547,11 @@ void CInStreamWithHash::SetStreamAndInit(ISequentialInStream *stream, int algo) | |||
521 | inStreamSha1->Init(); | 547 | inStreamSha1->Init(); |
522 | stream = inStreamSha1; | 548 | stream = inStreamSha1; |
523 | } | 549 | } |
524 | else if (algo == XAR_CKSUM_SHA256) | 550 | else if (algo == XAR_CKSUM_SHA256 |
551 | || algo == XAR_CKSUM_SHA512) | ||
525 | { | 552 | { |
526 | inStreamSha256->SetStream(stream); | 553 | inStreamSha256->SetStream(stream); |
527 | inStreamSha256->Init(); | 554 | inStreamSha256->Init(algo == XAR_CKSUM_SHA512); |
528 | stream = inStreamSha256; | 555 | stream = inStreamSha256; |
529 | } | 556 | } |
530 | inStreamLim->SetStream(stream); | 557 | inStreamLim->SetStream(stream); |
@@ -542,7 +569,14 @@ bool CInStreamWithHash::CheckHash(int algo, const Byte *digest_from_arc) const | |||
542 | else if (algo == XAR_CKSUM_SHA256) | 569 | else if (algo == XAR_CKSUM_SHA256) |
543 | { | 570 | { |
544 | Byte digest[SHA256_DIGEST_SIZE]; | 571 | Byte digest[SHA256_DIGEST_SIZE]; |
545 | inStreamSha256->Final(digest); | 572 | inStreamSha256->Final256(digest); |
573 | if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) | ||
574 | return false; | ||
575 | } | ||
576 | else if (algo == XAR_CKSUM_SHA512) | ||
577 | { | ||
578 | Byte digest[SHA512_DIGEST_SIZE]; | ||
579 | inStreamSha256->Final512(digest); | ||
546 | if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) | 580 | if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) |
547 | return false; | 581 | return false; |
548 | } | 582 | } |
@@ -658,12 +692,13 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
658 | file.UpdateTotalPackSize(totalPackSize); | 692 | file.UpdateTotalPackSize(totalPackSize); |
659 | if (file.Parent == -1) | 693 | if (file.Parent == -1) |
660 | { | 694 | { |
661 | if (file.Name == "Payload" || file.Name == "Content") | 695 | if (file.Name.IsEqualTo("Payload") || |
696 | file.Name.IsEqualTo("Content")) | ||
662 | { | 697 | { |
663 | _mainSubfile = (Int32)(int)i; | 698 | _mainSubfile = (Int32)(int)i; |
664 | numMainFiles++; | 699 | numMainFiles++; |
665 | } | 700 | } |
666 | else if (file.Name == "PackageInfo") | 701 | else if (file.Name.IsEqualTo("PackageInfo")) |
667 | _is_pkg = true; | 702 | _is_pkg = true; |
668 | } | 703 | } |
669 | } | 704 | } |
@@ -1151,11 +1186,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1151 | outStreamSha1->SetStream(realOutStream); | 1186 | outStreamSha1->SetStream(realOutStream); |
1152 | outStreamSha1->Init(); | 1187 | outStreamSha1->Init(); |
1153 | } | 1188 | } |
1154 | else if (checksum_method == XAR_CKSUM_SHA256) | 1189 | else if (checksum_method == XAR_CKSUM_SHA256 |
1190 | || checksum_method == XAR_CKSUM_SHA512) | ||
1155 | { | 1191 | { |
1156 | outStreamLim->SetStream(outStreamSha256); | 1192 | outStreamLim->SetStream(outStreamSha256); |
1157 | outStreamSha256->SetStream(realOutStream); | 1193 | outStreamSha256->SetStream(realOutStream); |
1158 | outStreamSha256->Init(); | 1194 | outStreamSha256->Init(checksum_method == XAR_CKSUM_SHA512); |
1159 | } | 1195 | } |
1160 | else | 1196 | else |
1161 | outStreamLim->SetStream(realOutStream); | 1197 | outStreamLim->SetStream(realOutStream); |
@@ -1175,9 +1211,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1175 | else | 1211 | else |
1176 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | 1212 | opRes = NExtract::NOperationResult::kUnsupportedMethod; |
1177 | } | 1213 | } |
1178 | else if (item.Method == METHOD_NAME_ZLIB) | 1214 | else if (item.Method.IsEqualTo(METHOD_NAME_ZLIB)) |
1179 | coder = zlibCoder; | 1215 | coder = zlibCoder; |
1180 | else if (item.Method == "bzip2") | 1216 | else if (item.Method.IsEqualTo("bzip2")) |
1181 | coder = bzip2Coder; | 1217 | coder = bzip2Coder; |
1182 | else | 1218 | else |
1183 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | 1219 | opRes = NExtract::NOperationResult::kUnsupportedMethod; |
@@ -1209,8 +1245,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1209 | else if (checksum_method == XAR_CKSUM_SHA256) | 1245 | else if (checksum_method == XAR_CKSUM_SHA256) |
1210 | { | 1246 | { |
1211 | Byte digest[SHA256_DIGEST_SIZE]; | 1247 | Byte digest[SHA256_DIGEST_SIZE]; |
1212 | outStreamSha256->Final(digest); | 1248 | outStreamSha256->Final256(digest); |
1213 | if (memcmp(digest, item.extracted_checksum.Data, SHA256_DIGEST_SIZE) != 0) | 1249 | if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0) |
1250 | opRes = NExtract::NOperationResult::kCRCError; | ||
1251 | } | ||
1252 | else if (checksum_method == XAR_CKSUM_SHA512) | ||
1253 | { | ||
1254 | Byte digest[SHA512_DIGEST_SIZE]; | ||
1255 | outStreamSha256->Final512(digest); | ||
1256 | if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0) | ||
1214 | opRes = NExtract::NOperationResult::kCRCError; | 1257 | opRes = NExtract::NOperationResult::kCRCError; |
1215 | } | 1258 | } |
1216 | if (opRes == NExtract::NOperationResult::kOK) | 1259 | if (opRes == NExtract::NOperationResult::kOK) |
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 7ced4e1..5aaa405 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp | |||
@@ -446,7 +446,7 @@ void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) | |||
446 | struct CXzsCPP | 446 | struct CXzsCPP |
447 | { | 447 | { |
448 | CXzs p; | 448 | CXzs p; |
449 | CXzsCPP() { Xzs_Construct(&p); } | 449 | CXzsCPP() { Xzs_CONSTRUCT(&p) } |
450 | ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } | 450 | ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } |
451 | }; | 451 | }; |
452 | 452 | ||
@@ -536,6 +536,9 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal | |||
536 | 536 | ||
537 | if (res2 == SZ_ERROR_ARCHIVE) | 537 | if (res2 == SZ_ERROR_ARCHIVE) |
538 | return S_FALSE; | 538 | return S_FALSE; |
539 | // what codes are possible here ? | ||
540 | // ?? res2 == SZ_ERROR_MEM : is possible here | ||
541 | // ?? res2 == SZ_ERROR_UNSUPPORTED : is possible here | ||
539 | } | 542 | } |
540 | else if (!isIndex) | 543 | else if (!isIndex) |
541 | { | 544 | { |
@@ -967,9 +970,9 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
967 | || _maxBlocksSize != (size_t)_maxBlocksSize) | 970 | || _maxBlocksSize != (size_t)_maxBlocksSize) |
968 | return S_FALSE; | 971 | return S_FALSE; |
969 | 972 | ||
970 | UInt64 memSize; | 973 | size_t memSize; |
971 | if (!NSystem::GetRamSize(memSize)) | 974 | if (!NSystem::GetRamSize(memSize)) |
972 | memSize = (UInt64)(sizeof(size_t)) << 28; | 975 | memSize = (size_t)sizeof(size_t) << 28; |
973 | { | 976 | { |
974 | if (_maxBlocksSize > memSize / 4) | 977 | if (_maxBlocksSize > memSize / 4) |
975 | return S_FALSE; | 978 | return S_FALSE; |
@@ -1159,6 +1162,13 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1159 | */ | 1162 | */ |
1160 | 1163 | ||
1161 | #ifndef Z7_ST | 1164 | #ifndef Z7_ST |
1165 | |||
1166 | #ifdef _WIN32 | ||
1167 | // we don't use chunk multithreading inside lzma2 stream. | ||
1168 | // so we don't set xzProps.lzma2Props.numThreadGroups. | ||
1169 | if (_numThreadGroups > 1) | ||
1170 | xzProps.numThreadGroups = _numThreadGroups; | ||
1171 | #endif | ||
1162 | 1172 | ||
1163 | UInt32 numThreads = _numThreads; | 1173 | UInt32 numThreads = _numThreads; |
1164 | 1174 | ||
@@ -1183,6 +1193,8 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1183 | CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads); | 1193 | CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads); |
1184 | } | 1194 | } |
1185 | 1195 | ||
1196 | // printf("\n====== GetProcessGroupAffinity : \n"); | ||
1197 | |||
1186 | UInt64 cs = _numSolidBytes; | 1198 | UInt64 cs = _numSolidBytes; |
1187 | if (cs != XZ_PROPS_BLOCK_SIZE_AUTO) | 1199 | if (cs != XZ_PROPS_BLOCK_SIZE_AUTO) |
1188 | oneMethodInfo.AddProp_BlockSize2(cs); | 1200 | oneMethodInfo.AddProp_BlockSize2(cs); |
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index bc047b7..b2684dc 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp | |||
@@ -250,13 +250,26 @@ struct CThreadInfo | |||
250 | 250 | ||
251 | HRESULT CreateEvents() | 251 | HRESULT CreateEvents() |
252 | { | 252 | { |
253 | WRes wres = CompressEvent.CreateIfNotCreated_Reset(); | 253 | const WRes wres = CompressEvent.CreateIfNotCreated_Reset(); |
254 | return HRESULT_FROM_WIN32(wres); | 254 | return HRESULT_FROM_WIN32(wres); |
255 | } | 255 | } |
256 | 256 | ||
257 | HRESULT CreateThread() | 257 | // (group < 0) means no_group. |
258 | HRESULT CreateThread_with_group( | ||
259 | #ifdef _WIN32 | ||
260 | int group | ||
261 | #endif | ||
262 | ) | ||
258 | { | 263 | { |
259 | WRes wres = Thread.Create(CoderThread, this); | 264 | // tested in win10: If thread is created by another thread, |
265 | // child thread probably uses same group as parent thread. | ||
266 | // So we don't need to send (group) to encoder in created thread. | ||
267 | const WRes wres = | ||
268 | #ifdef _WIN32 | ||
269 | group >= 0 ? | ||
270 | Thread.Create_With_Group(CoderThread, this, (unsigned)group) : | ||
271 | #endif | ||
272 | Thread.Create(CoderThread, this); | ||
260 | return HRESULT_FROM_WIN32(wres); | 273 | return HRESULT_FROM_WIN32(wres); |
261 | } | 274 | } |
262 | 275 | ||
@@ -450,8 +463,12 @@ static HRESULT UpdateItemOldData( | |||
450 | if (ui.NewProps) | 463 | if (ui.NewProps) |
451 | { | 464 | { |
452 | if (item.HasDescriptor()) | 465 | if (item.HasDescriptor()) |
453 | return E_NOTIMPL; | 466 | { |
454 | 467 | // we know compressed / uncompressed sizes and crc. | |
468 | // so we remove descriptor here | ||
469 | item.Flags = (UInt16)(item.Flags & ~NFileHeader::NFlags::kDescriptorUsedMask); | ||
470 | // return E_NOTIMPL; | ||
471 | } | ||
455 | // we keep ExternalAttrib and some another properties from old archive | 472 | // we keep ExternalAttrib and some another properties from old archive |
456 | // item.ExternalAttrib = ui.Attrib; | 473 | // item.ExternalAttrib = ui.Attrib; |
457 | // if we don't change Comment, we keep Comment from OldProperties | 474 | // if we don't change Comment, we keep Comment from OldProperties |
@@ -1000,6 +1017,9 @@ static HRESULT Update2( | |||
1000 | #ifndef Z7_ST | 1017 | #ifndef Z7_ST |
1001 | 1018 | ||
1002 | UInt32 numThreads = options._numThreads; | 1019 | UInt32 numThreads = options._numThreads; |
1020 | #ifdef _WIN32 | ||
1021 | const UInt32 numThreadGroups = options._numThreadGroups; | ||
1022 | #endif | ||
1003 | 1023 | ||
1004 | UInt32 numZipThreads_limit = numThreads; | 1024 | UInt32 numZipThreads_limit = numThreads; |
1005 | if (numZipThreads_limit > numFilesToCompress) | 1025 | if (numZipThreads_limit > numFilesToCompress) |
@@ -1014,12 +1034,10 @@ static HRESULT Update2( | |||
1014 | } | 1034 | } |
1015 | 1035 | ||
1016 | { | 1036 | { |
1037 | // we reduce number of threads for 32-bit to reduce memory usege to 256 MB | ||
1017 | const UInt32 kNumMaxThreads = | 1038 | const UInt32 kNumMaxThreads = |
1018 | #ifdef _WIN32 | 1039 | // _WIN32 (64-bit) supports only 64 threads in one group. |
1019 | 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here | 1040 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit |
1020 | #else | ||
1021 | 128; | ||
1022 | #endif | ||
1023 | if (numThreads > kNumMaxThreads) | 1041 | if (numThreads > kNumMaxThreads) |
1024 | numThreads = kNumMaxThreads; | 1042 | numThreads = kNumMaxThreads; |
1025 | } | 1043 | } |
@@ -1264,7 +1282,14 @@ static HRESULT Update2( | |||
1264 | threadInfo.Progress = threadInfo.ProgressSpec; | 1282 | threadInfo.Progress = threadInfo.ProgressSpec; |
1265 | threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, i); | 1283 | threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, i); |
1266 | threadInfo.MtSem = &mtSem; | 1284 | threadInfo.MtSem = &mtSem; |
1267 | RINOK(threadInfo.CreateThread()) | 1285 | const HRESULT hres = |
1286 | threadInfo.CreateThread_with_group( | ||
1287 | #ifdef _WIN32 | ||
1288 | (numThreadGroups > 1 && numThreads > 1) ? | ||
1289 | (int)(i % numThreadGroups) : -1 | ||
1290 | #endif | ||
1291 | ); | ||
1292 | RINOK(hres) | ||
1268 | } | 1293 | } |
1269 | } | 1294 | } |
1270 | 1295 | ||
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index beed5a7..558c41e 100644 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp | |||
@@ -1148,26 +1148,6 @@ SOURCE=..\..\Compress\PpmdZip.cpp | |||
1148 | SOURCE=..\..\Compress\PpmdZip.h | 1148 | SOURCE=..\..\Compress\PpmdZip.h |
1149 | # End Source File | 1149 | # End Source File |
1150 | # End Group | 1150 | # End Group |
1151 | # Begin Group "RangeCoder" | ||
1152 | |||
1153 | # PROP Default_Filter "" | ||
1154 | # Begin Source File | ||
1155 | |||
1156 | SOURCE=..\..\Compress\RangeCoder.h | ||
1157 | # End Source File | ||
1158 | # Begin Source File | ||
1159 | |||
1160 | SOURCE=..\..\Compress\RangeCoderBit.h | ||
1161 | # End Source File | ||
1162 | # Begin Source File | ||
1163 | |||
1164 | SOURCE=..\..\Compress\RangeCoderBitTree.h | ||
1165 | # End Source File | ||
1166 | # Begin Source File | ||
1167 | |||
1168 | SOURCE=..\..\Compress\RangeCoderOpt.h | ||
1169 | # End Source File | ||
1170 | # End Group | ||
1171 | # Begin Group "Shrink" | 1151 | # Begin Group "Shrink" |
1172 | 1152 | ||
1173 | # PROP Default_Filter "" | 1153 | # PROP Default_Filter "" |
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 7547590..9f81f9e 100644 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile | |||
@@ -5,6 +5,7 @@ CFLAGS = $(CFLAGS) -DZ7_ZIP_LZFSE_DISABLE | |||
5 | # CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_A | 5 | # CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_A |
6 | # ZIP_FLAGS=-DZ7_ZIP_LZFSE_DISABLE | 6 | # ZIP_FLAGS=-DZ7_ZIP_LZFSE_DISABLE |
7 | 7 | ||
8 | # USE_C_SORT=1 | ||
8 | # USE_C_AES = 1 | 9 | # USE_C_AES = 1 |
9 | # USE_C_SHA = 1 | 10 | # USE_C_SHA = 1 |
10 | # USE_C_LZFINDOPT = 1 | 11 | # USE_C_LZFINDOPT = 1 |
@@ -221,7 +222,6 @@ C_OBJS = \ | |||
221 | $O\Ppmd8.obj \ | 222 | $O\Ppmd8.obj \ |
222 | $O\Ppmd8Dec.obj \ | 223 | $O\Ppmd8Dec.obj \ |
223 | $O\Ppmd8Enc.obj \ | 224 | $O\Ppmd8Enc.obj \ |
224 | $O\Sort.obj \ | ||
225 | $O\SwapBytes.obj \ | 225 | $O\SwapBytes.obj \ |
226 | $O\Threads.obj \ | 226 | $O\Threads.obj \ |
227 | $O\Xxh64.obj \ | 227 | $O\Xxh64.obj \ |
@@ -240,5 +240,6 @@ C_OBJS = \ | |||
240 | !include "../../LzmaDec.mak" | 240 | !include "../../LzmaDec.mak" |
241 | !include "../../Sha1.mak" | 241 | !include "../../Sha1.mak" |
242 | !include "../../Sha256.mak" | 242 | !include "../../Sha256.mak" |
243 | !include "../../Sort.mak" | ||
243 | 244 | ||
244 | !include "../../7zip.mak" | 245 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index 89584e1..f0a813a 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile | |||
@@ -148,7 +148,6 @@ C_OBJS = \ | |||
148 | $O\LzmaEnc.obj \ | 148 | $O\LzmaEnc.obj \ |
149 | $O\MtCoder.obj \ | 149 | $O\MtCoder.obj \ |
150 | $O\MtDec.obj \ | 150 | $O\MtDec.obj \ |
151 | $O\Sort.obj \ | ||
152 | $O\SwapBytes.obj \ | 151 | $O\SwapBytes.obj \ |
153 | $O\Threads.obj \ | 152 | $O\Threads.obj \ |
154 | $O\Xz.obj \ | 153 | $O\Xz.obj \ |
@@ -164,5 +163,6 @@ C_OBJS = \ | |||
164 | !include "../../LzFindOpt.mak" | 163 | !include "../../LzFindOpt.mak" |
165 | !include "../../LzmaDec.mak" | 164 | !include "../../LzmaDec.mak" |
166 | !include "../../Sha256.mak" | 165 | !include "../../Sha256.mak" |
166 | !include "../../Sort.mak" | ||
167 | 167 | ||
168 | !include "../../7zip.mak" | 168 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index fe6f94d..3d4754c 100644 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile | |||
@@ -135,7 +135,6 @@ C_OBJS = \ | |||
135 | $O\Ppmd7.obj \ | 135 | $O\Ppmd7.obj \ |
136 | $O\Ppmd7Dec.obj \ | 136 | $O\Ppmd7Dec.obj \ |
137 | $O\Ppmd7Enc.obj \ | 137 | $O\Ppmd7Enc.obj \ |
138 | $O\Sort.obj \ | ||
139 | $O\SwapBytes.obj \ | 138 | $O\SwapBytes.obj \ |
140 | $O\Threads.obj \ | 139 | $O\Threads.obj \ |
141 | 140 | ||
@@ -144,5 +143,6 @@ C_OBJS = \ | |||
144 | !include "../../LzFindOpt.mak" | 143 | !include "../../LzFindOpt.mak" |
145 | !include "../../LzmaDec.mak" | 144 | !include "../../LzmaDec.mak" |
146 | !include "../../Sha256.mak" | 145 | !include "../../Sha256.mak" |
146 | !include "../../Sort.mak" | ||
147 | 147 | ||
148 | !include "../../7zip.mak" | 148 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index 3d8a430..b1c6fe2 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak | |||
@@ -4,6 +4,7 @@ COMMON_OBJS = \ | |||
4 | $O\DynLimBuf.obj \ | 4 | $O\DynLimBuf.obj \ |
5 | $O\IntToString.obj \ | 5 | $O\IntToString.obj \ |
6 | $O\LzFindPrepare.obj \ | 6 | $O\LzFindPrepare.obj \ |
7 | $O\Md5Reg.obj \ | ||
7 | $O\MyMap.obj \ | 8 | $O\MyMap.obj \ |
8 | $O\MyString.obj \ | 9 | $O\MyString.obj \ |
9 | $O\MyVector.obj \ | 10 | $O\MyVector.obj \ |
@@ -11,6 +12,9 @@ COMMON_OBJS = \ | |||
11 | $O\NewHandler.obj \ | 12 | $O\NewHandler.obj \ |
12 | $O\Sha1Reg.obj \ | 13 | $O\Sha1Reg.obj \ |
13 | $O\Sha256Reg.obj \ | 14 | $O\Sha256Reg.obj \ |
15 | $O\Sha3Reg.obj \ | ||
16 | $O\Sha512Reg.obj \ | ||
17 | $O\Sha512Prepare.obj \ | ||
14 | $O\StringConvert.obj \ | 18 | $O\StringConvert.obj \ |
15 | $O\StringToInt.obj \ | 19 | $O\StringToInt.obj \ |
16 | $O\UTFConvert.obj \ | 20 | $O\UTFConvert.obj \ |
@@ -274,6 +278,7 @@ C_OBJS = \ | |||
274 | $O\Lzma2Enc.obj \ | 278 | $O\Lzma2Enc.obj \ |
275 | $O\LzmaDec.obj \ | 279 | $O\LzmaDec.obj \ |
276 | $O\LzmaEnc.obj \ | 280 | $O\LzmaEnc.obj \ |
281 | $O\Md5.obj \ | ||
277 | $O\MtCoder.obj \ | 282 | $O\MtCoder.obj \ |
278 | $O\MtDec.obj \ | 283 | $O\MtDec.obj \ |
279 | $O\Ppmd7.obj \ | 284 | $O\Ppmd7.obj \ |
@@ -283,7 +288,9 @@ C_OBJS = \ | |||
283 | $O\Ppmd8.obj \ | 288 | $O\Ppmd8.obj \ |
284 | $O\Ppmd8Dec.obj \ | 289 | $O\Ppmd8Dec.obj \ |
285 | $O\Ppmd8Enc.obj \ | 290 | $O\Ppmd8Enc.obj \ |
286 | $O\Sort.obj \ | 291 | $O\Sha3.obj \ |
292 | $O\Sha512.obj \ | ||
293 | $O\Sha512Opt.obj \ | ||
287 | $O\SwapBytes.obj \ | 294 | $O\SwapBytes.obj \ |
288 | $O\Threads.obj \ | 295 | $O\Threads.obj \ |
289 | $O\Xxh64.obj \ | 296 | $O\Xxh64.obj \ |
@@ -300,3 +307,4 @@ C_OBJS = \ | |||
300 | !include "../../LzmaDec.mak" | 307 | !include "../../LzmaDec.mak" |
301 | !include "../../Sha1.mak" | 308 | !include "../../Sha1.mak" |
302 | !include "../../Sha256.mak" | 309 | !include "../../Sha256.mak" |
310 | !include "../../Sort.mak" | ||
diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak index ff5a3f9..746aaff 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak | |||
@@ -45,6 +45,7 @@ COMMON_OBJS = \ | |||
45 | $O/DynLimBuf.o \ | 45 | $O/DynLimBuf.o \ |
46 | $O/IntToString.o \ | 46 | $O/IntToString.o \ |
47 | $O/LzFindPrepare.o \ | 47 | $O/LzFindPrepare.o \ |
48 | $O/Md5Reg.o \ | ||
48 | $O/MyMap.o \ | 49 | $O/MyMap.o \ |
49 | $O/MyString.o \ | 50 | $O/MyString.o \ |
50 | $O/MyVector.o \ | 51 | $O/MyVector.o \ |
@@ -54,6 +55,9 @@ COMMON_OBJS = \ | |||
54 | $O/Sha1Reg.o \ | 55 | $O/Sha1Reg.o \ |
55 | $O/Sha256Prepare.o \ | 56 | $O/Sha256Prepare.o \ |
56 | $O/Sha256Reg.o \ | 57 | $O/Sha256Reg.o \ |
58 | $O/Sha3Reg.o \ | ||
59 | $O/Sha512Prepare.o \ | ||
60 | $O/Sha512Reg.o \ | ||
57 | $O/StringConvert.o \ | 61 | $O/StringConvert.o \ |
58 | $O/StringToInt.o \ | 62 | $O/StringToInt.o \ |
59 | $O/UTFConvert.o \ | 63 | $O/UTFConvert.o \ |
@@ -337,6 +341,7 @@ C_OBJS = \ | |||
337 | $O/Lzma2Enc.o \ | 341 | $O/Lzma2Enc.o \ |
338 | $O/LzmaDec.o \ | 342 | $O/LzmaDec.o \ |
339 | $O/LzmaEnc.o \ | 343 | $O/LzmaEnc.o \ |
344 | $O/Md5.o \ | ||
340 | $O/MtCoder.o \ | 345 | $O/MtCoder.o \ |
341 | $O/MtDec.o \ | 346 | $O/MtDec.o \ |
342 | $O/Ppmd7.o \ | 347 | $O/Ppmd7.o \ |
@@ -350,6 +355,9 @@ C_OBJS = \ | |||
350 | $O/Sha1Opt.o \ | 355 | $O/Sha1Opt.o \ |
351 | $O/Sha256.o \ | 356 | $O/Sha256.o \ |
352 | $O/Sha256Opt.o \ | 357 | $O/Sha256Opt.o \ |
358 | $O/Sha3.o \ | ||
359 | $O/Sha512.o \ | ||
360 | $O/Sha512Opt.o \ | ||
353 | $O/Sort.o \ | 361 | $O/Sort.o \ |
354 | $O/SwapBytes.o \ | 362 | $O/SwapBytes.o \ |
355 | $O/Xxh64.o \ | 363 | $O/Xxh64.o \ |
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 6e28288..0bf976c 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp | |||
@@ -287,6 +287,10 @@ SOURCE=..\..\..\Common\LzFindPrepare.cpp | |||
287 | # End Source File | 287 | # End Source File |
288 | # Begin Source File | 288 | # Begin Source File |
289 | 289 | ||
290 | SOURCE=..\..\..\Common\Md5Reg.cpp | ||
291 | # End Source File | ||
292 | # Begin Source File | ||
293 | |||
290 | SOURCE=..\..\..\Common\MyBuffer.h | 294 | SOURCE=..\..\..\Common\MyBuffer.h |
291 | # End Source File | 295 | # End Source File |
292 | # Begin Source File | 296 | # Begin Source File |
@@ -383,6 +387,18 @@ SOURCE=..\..\..\Common\Sha256Reg.cpp | |||
383 | # End Source File | 387 | # End Source File |
384 | # Begin Source File | 388 | # Begin Source File |
385 | 389 | ||
390 | SOURCE=..\..\..\Common\Sha3Reg.cpp | ||
391 | # End Source File | ||
392 | # Begin Source File | ||
393 | |||
394 | SOURCE=..\..\..\Common\Sha512Prepare.cpp | ||
395 | # End Source File | ||
396 | # Begin Source File | ||
397 | |||
398 | SOURCE=..\..\..\Common\Sha512Reg.cpp | ||
399 | # End Source File | ||
400 | # Begin Source File | ||
401 | |||
386 | SOURCE=..\..\..\Common\StringConvert.cpp | 402 | SOURCE=..\..\..\Common\StringConvert.cpp |
387 | # End Source File | 403 | # End Source File |
388 | # Begin Source File | 404 | # Begin Source File |
@@ -2029,6 +2045,26 @@ SOURCE=..\..\..\..\C\LzmaEnc.h | |||
2029 | # End Source File | 2045 | # End Source File |
2030 | # Begin Source File | 2046 | # Begin Source File |
2031 | 2047 | ||
2048 | SOURCE=..\..\..\..\C\Md5.c | ||
2049 | |||
2050 | !IF "$(CFG)" == "7z - Win32 Release" | ||
2051 | |||
2052 | # ADD CPP /O2 | ||
2053 | # SUBTRACT CPP /YX /Yc /Yu | ||
2054 | |||
2055 | !ELSEIF "$(CFG)" == "7z - Win32 Debug" | ||
2056 | |||
2057 | # SUBTRACT CPP /YX /Yc /Yu | ||
2058 | |||
2059 | !ENDIF | ||
2060 | |||
2061 | # End Source File | ||
2062 | # Begin Source File | ||
2063 | |||
2064 | SOURCE=..\..\..\..\C\Md5.h | ||
2065 | # End Source File | ||
2066 | # Begin Source File | ||
2067 | |||
2032 | SOURCE=..\..\..\..\C\MtCoder.c | 2068 | SOURCE=..\..\..\..\C\MtCoder.c |
2033 | # SUBTRACT CPP /YX /Yc /Yu | 2069 | # SUBTRACT CPP /YX /Yc /Yu |
2034 | # End Source File | 2070 | # End Source File |
@@ -2230,6 +2266,62 @@ SOURCE=..\..\..\..\C\Sha256.h | |||
2230 | # End Source File | 2266 | # End Source File |
2231 | # Begin Source File | 2267 | # Begin Source File |
2232 | 2268 | ||
2269 | SOURCE=..\..\..\..\C\Sha3.c | ||
2270 | |||
2271 | !IF "$(CFG)" == "7z - Win32 Release" | ||
2272 | |||
2273 | # ADD CPP /O2 | ||
2274 | # SUBTRACT CPP /YX /Yc /Yu | ||
2275 | |||
2276 | !ELSEIF "$(CFG)" == "7z - Win32 Debug" | ||
2277 | |||
2278 | # SUBTRACT CPP /YX /Yc /Yu | ||
2279 | |||
2280 | !ENDIF | ||
2281 | |||
2282 | # End Source File | ||
2283 | # Begin Source File | ||
2284 | |||
2285 | SOURCE=..\..\..\..\C\Sha3.h | ||
2286 | # End Source File | ||
2287 | # Begin Source File | ||
2288 | |||
2289 | SOURCE=..\..\..\..\C\Sha512.c | ||
2290 | |||
2291 | !IF "$(CFG)" == "7z - Win32 Release" | ||
2292 | |||
2293 | # ADD CPP /O2 | ||
2294 | # SUBTRACT CPP /YX /Yc /Yu | ||
2295 | |||
2296 | !ELSEIF "$(CFG)" == "7z - Win32 Debug" | ||
2297 | |||
2298 | # SUBTRACT CPP /YX /Yc /Yu | ||
2299 | |||
2300 | !ENDIF | ||
2301 | |||
2302 | # End Source File | ||
2303 | # Begin Source File | ||
2304 | |||
2305 | SOURCE=..\..\..\..\C\Sha512.h | ||
2306 | # End Source File | ||
2307 | # Begin Source File | ||
2308 | |||
2309 | SOURCE=..\..\..\..\C\Sha512Opt.c | ||
2310 | |||
2311 | !IF "$(CFG)" == "7z - Win32 Release" | ||
2312 | |||
2313 | # ADD CPP /O2 | ||
2314 | # SUBTRACT CPP /YX /Yc /Yu | ||
2315 | |||
2316 | !ELSEIF "$(CFG)" == "7z - Win32 Debug" | ||
2317 | |||
2318 | # SUBTRACT CPP /YX /Yc /Yu | ||
2319 | |||
2320 | !ENDIF | ||
2321 | |||
2322 | # End Source File | ||
2323 | # Begin Source File | ||
2324 | |||
2233 | SOURCE=..\..\..\..\C\Sort.c | 2325 | SOURCE=..\..\..\..\C\Sort.c |
2234 | 2326 | ||
2235 | !IF "$(CFG)" == "7z - Win32 Release" | 2327 | !IF "$(CFG)" == "7z - Win32 Release" |
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index b4bd2de..e43e8b1 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | |||
@@ -59,13 +59,13 @@ static const char * const kHelpString = | |||
59 | " b : Benchmark\n" | 59 | " b : Benchmark\n" |
60 | "<switches>\n" | 60 | "<switches>\n" |
61 | " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n" | 61 | " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n" |
62 | " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n" | 62 | " -d{N} : set dictionary size : [12, 31] : default = 24 (16 MiB)\n" |
63 | " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n" | 63 | " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n" |
64 | " -mc{N} : set number of cycles for match finder\n" | 64 | " -mc{N} : set number of cycles for match finder\n" |
65 | " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n" | 65 | " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n" |
66 | " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n" | 66 | " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n" |
67 | " -pb{N} : set number of pos bits : [0, 4] : default = 2\n" | 67 | " -pb{N} : set number of pos bits : [0, 4] : default = 2\n" |
68 | " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n" | 68 | " -mf{M} : set match finder: [hc4, hc5, bt2, bt3, bt4, bt5] : default = bt4\n" |
69 | " -mt{N} : set number of CPU threads\n" | 69 | " -mt{N} : set number of CPU threads\n" |
70 | " -eos : write end of stream marker\n" | 70 | " -eos : write end of stream marker\n" |
71 | " -si : read data from stdin\n" | 71 | " -si : read data from stdin\n" |
@@ -372,8 +372,8 @@ static int main2(int numArgs, const char *args[]) | |||
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
374 | 374 | ||
375 | bool stdInMode = parser[NKey::kStdIn].ThereIs; | 375 | const bool stdInMode = parser[NKey::kStdIn].ThereIs; |
376 | bool stdOutMode = parser[NKey::kStdOut].ThereIs; | 376 | const bool stdOutMode = parser[NKey::kStdOut].ThereIs; |
377 | 377 | ||
378 | if (!stdOutMode) | 378 | if (!stdOutMode) |
379 | PrintTitle(); | 379 | PrintTitle(); |
@@ -394,7 +394,16 @@ static int main2(int numArgs, const char *args[]) | |||
394 | UInt32 dictLog; | 394 | UInt32 dictLog; |
395 | const UString &s = parser[NKey::kDict].PostStrings[0]; | 395 | const UString &s = parser[NKey::kDict].PostStrings[0]; |
396 | dictLog = GetNumber(s); | 396 | dictLog = GetNumber(s); |
397 | dict = 1 << dictLog; | 397 | if (dictLog >= 32) |
398 | throw "unsupported dictionary size"; | ||
399 | // we only want to use dictionary sizes that are powers of 2, | ||
400 | // because 7-zip only recognizes such dictionary sizes in the lzma header.#if 0 | ||
401 | #if 0 | ||
402 | if (dictLog == 32) | ||
403 | dict = (UInt32)3840 << 20; | ||
404 | else | ||
405 | #endif | ||
406 | dict = (UInt32)1 << dictLog; | ||
398 | dictDefined = true; | 407 | dictDefined = true; |
399 | AddProp(props2, "d", s); | 408 | AddProp(props2, "d", s); |
400 | } | 409 | } |
@@ -522,7 +531,7 @@ static int main2(int numArgs, const char *args[]) | |||
522 | 531 | ||
523 | if (encodeMode && !dictDefined) | 532 | if (encodeMode && !dictDefined) |
524 | { | 533 | { |
525 | dict = 1 << kDictSizeLog; | 534 | dict = (UInt32)1 << kDictSizeLog; |
526 | if (fileSizeDefined) | 535 | if (fileSizeDefined) |
527 | { | 536 | { |
528 | unsigned i; | 537 | unsigned i; |
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index eb28f5d..0c09807 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | |||
@@ -229,7 +229,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, | |||
229 | } | 229 | } |
230 | 230 | ||
231 | const FString tempDirPath = tempDir.GetPath(); | 231 | const FString tempDirPath = tempDir.GetPath(); |
232 | // tempDirPath = L"M:\\1\\"; // to test low disk space | 232 | // tempDirPath = "M:\\1\\"; // to test low disk space |
233 | { | 233 | { |
234 | bool isCorrupt = false; | 234 | bool isCorrupt = false; |
235 | UString errorMessage; | 235 | UString errorMessage; |
@@ -308,7 +308,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, | |||
308 | { | 308 | { |
309 | if (appLaunched.IsEmpty()) | 309 | if (appLaunched.IsEmpty()) |
310 | { | 310 | { |
311 | appLaunched = L"setup.exe"; | 311 | appLaunched = "setup.exe"; |
312 | if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) | 312 | if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) |
313 | { | 313 | { |
314 | if (!assumeYes) | 314 | if (!assumeYes) |
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index bf7b04e..93113a0 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp | |||
@@ -35,7 +35,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw() | |||
35 | g_Codecs[g_NumCodecs++] = codecInfo; | 35 | g_Codecs[g_NumCodecs++] = codecInfo; |
36 | } | 36 | } |
37 | 37 | ||
38 | static const unsigned kNumHashersMax = 16; | 38 | static const unsigned kNumHashersMax = 32; |
39 | extern | 39 | extern |
40 | unsigned g_NumHashers; | 40 | unsigned g_NumHashers; |
41 | unsigned g_NumHashers = 0; | 41 | unsigned g_NumHashers = 0; |
diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h index a8ccb40..13ec088 100644 --- a/CPP/7zip/Common/InBuffer.h +++ b/CPP/7zip/Common/InBuffer.h | |||
@@ -97,6 +97,16 @@ public: | |||
97 | 97 | ||
98 | size_t ReadBytesPart(Byte *buf, size_t size); | 98 | size_t ReadBytesPart(Byte *buf, size_t size); |
99 | size_t ReadBytes(Byte *buf, size_t size); | 99 | size_t ReadBytes(Byte *buf, size_t size); |
100 | const Byte *Lookahead(size_t &rem) | ||
101 | { | ||
102 | rem = (size_t)(_bufLim - _buf); | ||
103 | if (!rem) | ||
104 | { | ||
105 | ReadBlock(); | ||
106 | rem = (size_t)(_bufLim - _buf); | ||
107 | } | ||
108 | return _buf; | ||
109 | } | ||
100 | size_t Skip(size_t size); | 110 | size_t Skip(size_t size); |
101 | }; | 111 | }; |
102 | 112 | ||
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index d87884c..a5d90cf 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp | |||
@@ -324,15 +324,22 @@ void CCoderProps::AddProp(const CProp &prop) | |||
324 | 324 | ||
325 | HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const | 325 | HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const |
326 | { | 326 | { |
327 | return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL); | 327 | return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL, NULL, NULL); |
328 | } | 328 | } |
329 | 329 | ||
330 | HRESULT CProps::SetCoderProps_DSReduce_Aff( | 330 | HRESULT CProps::SetCoderProps_DSReduce_Aff( |
331 | ICompressSetCoderProperties *scp, | 331 | ICompressSetCoderProperties *scp, |
332 | const UInt64 *dataSizeReduce, | 332 | const UInt64 *dataSizeReduce, |
333 | const UInt64 *affinity) const | 333 | const UInt64 *affinity, |
334 | { | 334 | const UInt32 *affinityGroup, |
335 | CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) ); | 335 | const UInt64 *affinityInGroup) const |
336 | { | ||
337 | CCoderProps coderProps(Props.Size() | ||
338 | + (dataSizeReduce ? 1 : 0) | ||
339 | + (affinity ? 1 : 0) | ||
340 | + (affinityGroup ? 1 : 0) | ||
341 | + (affinityInGroup ? 1 : 0) | ||
342 | ); | ||
336 | FOR_VECTOR (i, Props) | 343 | FOR_VECTOR (i, Props) |
337 | coderProps.AddProp(Props[i]); | 344 | coderProps.AddProp(Props[i]); |
338 | if (dataSizeReduce) | 345 | if (dataSizeReduce) |
@@ -349,6 +356,20 @@ HRESULT CProps::SetCoderProps_DSReduce_Aff( | |||
349 | prop.Value = *affinity; | 356 | prop.Value = *affinity; |
350 | coderProps.AddProp(prop); | 357 | coderProps.AddProp(prop); |
351 | } | 358 | } |
359 | if (affinityGroup) | ||
360 | { | ||
361 | CProp prop; | ||
362 | prop.Id = NCoderPropID::kThreadGroup; | ||
363 | prop.Value = *affinityGroup; | ||
364 | coderProps.AddProp(prop); | ||
365 | } | ||
366 | if (affinityInGroup) | ||
367 | { | ||
368 | CProp prop; | ||
369 | prop.Id = NCoderPropID::kAffinityInGroup; | ||
370 | prop.Value = *affinityInGroup; | ||
371 | coderProps.AddProp(prop); | ||
372 | } | ||
352 | return coderProps.SetProps(scp); | 373 | return coderProps.SetProps(scp); |
353 | } | 374 | } |
354 | 375 | ||
@@ -409,6 +430,11 @@ static const CNameToPropID g_NameToPropID[] = | |||
409 | { VT_UI4, "offset" }, | 430 | { VT_UI4, "offset" }, |
410 | { VT_UI4, "zhb" } | 431 | { VT_UI4, "zhb" } |
411 | /* | 432 | /* |
433 | , { VT_UI4, "tgn" }, // kNumThreadGroups | ||
434 | , { VT_UI4, "tgi" }, // kThreadGroup | ||
435 | , { VT_UI8, "tga" }, // kAffinityInGroup | ||
436 | */ | ||
437 | /* | ||
412 | , | 438 | , |
413 | // { VT_UI4, "zhc" }, | 439 | // { VT_UI4, "zhc" }, |
414 | // { VT_UI4, "zhd" }, | 440 | // { VT_UI4, "zhd" }, |
diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 3c332d6..be108fa 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h | |||
@@ -80,7 +80,11 @@ struct CProps | |||
80 | } | 80 | } |
81 | 81 | ||
82 | HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; | 82 | HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; |
83 | HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; | 83 | HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, |
84 | const UInt64 *dataSizeReduce, | ||
85 | const UInt64 *affinity, | ||
86 | const UInt32 *affinityGroup, | ||
87 | const UInt64 *affinityInGroup) const; | ||
84 | }; | 88 | }; |
85 | 89 | ||
86 | class CMethodProps: public CProps | 90 | class CMethodProps: public CProps |
@@ -125,7 +129,7 @@ public: | |||
125 | 129 | ||
126 | UInt32 Get_Lzma_Algo() const | 130 | UInt32 Get_Lzma_Algo() const |
127 | { | 131 | { |
128 | int i = FindProp(NCoderPropID::kAlgorithm); | 132 | const int i = FindProp(NCoderPropID::kAlgorithm); |
129 | if (i >= 0) | 133 | if (i >= 0) |
130 | { | 134 | { |
131 | const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; | 135 | const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; |
@@ -141,11 +145,11 @@ public: | |||
141 | if (Get_DicSize(v)) | 145 | if (Get_DicSize(v)) |
142 | return v; | 146 | return v; |
143 | const unsigned level = GetLevel(); | 147 | const unsigned level = GetLevel(); |
144 | const UInt32 dictSize = | 148 | const UInt32 dictSize = level <= 4 ? |
145 | ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : | 149 | (UInt32)1 << (level * 2 + 16) : |
146 | ( level <= 6 ? ((UInt32)1 << (level + 19)) : | 150 | level <= sizeof(size_t) / 2 + 4 ? |
147 | ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) | 151 | (UInt32)1 << (level + 20) : |
148 | ))); | 152 | (UInt32)1 << (sizeof(size_t) / 2 + 24); |
149 | return dictSize; | 153 | return dictSize; |
150 | } | 154 | } |
151 | 155 | ||
diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h index 88f5787..af78c4f 100644 --- a/CPP/7zip/Common/OutBuffer.h +++ b/CPP/7zip/Common/OutBuffer.h | |||
@@ -45,6 +45,7 @@ public: | |||
45 | HRESULT Flush() throw(); | 45 | HRESULT Flush() throw(); |
46 | void FlushWithCheck(); | 46 | void FlushWithCheck(); |
47 | 47 | ||
48 | Z7_FORCE_INLINE | ||
48 | void WriteByte(Byte b) | 49 | void WriteByte(Byte b) |
49 | { | 50 | { |
50 | UInt32 pos = _pos; | 51 | UInt32 pos = _pos; |
@@ -54,10 +55,34 @@ public: | |||
54 | if (pos == _limitPos) | 55 | if (pos == _limitPos) |
55 | FlushWithCheck(); | 56 | FlushWithCheck(); |
56 | } | 57 | } |
58 | |||
57 | void WriteBytes(const void *data, size_t size) | 59 | void WriteBytes(const void *data, size_t size) |
58 | { | 60 | { |
59 | for (size_t i = 0; i < size; i++) | 61 | while (size) |
60 | WriteByte(((const Byte *)data)[i]); | 62 | { |
63 | UInt32 pos = _pos; | ||
64 | size_t cur = (size_t)(_limitPos - pos); | ||
65 | if (cur >= size) | ||
66 | cur = size; | ||
67 | size -= cur; | ||
68 | Byte *dest = _buf + pos; | ||
69 | pos += (UInt32)cur; | ||
70 | _pos = pos; | ||
71 | #if 0 | ||
72 | memcpy(dest, data, cur); | ||
73 | data = (const void *)((const Byte *)data + cur); | ||
74 | #else | ||
75 | const Byte * const lim = (const Byte *)data + cur; | ||
76 | do | ||
77 | { | ||
78 | *dest++ = *(const Byte *)data; | ||
79 | data = (const void *)((const Byte *)data + 1); | ||
80 | } | ||
81 | while (data != lim); | ||
82 | #endif | ||
83 | if (pos == _limitPos) | ||
84 | FlushWithCheck(); | ||
85 | } | ||
61 | } | 86 | } |
62 | 87 | ||
63 | Byte *GetOutBuffer(size_t &avail) | 88 | Byte *GetOutBuffer(size_t &avail) |
diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h index 0dfcfe5..3380aaf 100644 --- a/CPP/7zip/Compress/BZip2Const.h +++ b/CPP/7zip/Compress/BZip2Const.h | |||
@@ -46,7 +46,7 @@ const UInt32 kBlockSizeStep = 100000; | |||
46 | const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep; | 46 | const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep; |
47 | 47 | ||
48 | const unsigned kNumSelectorsBits = 15; | 48 | const unsigned kNumSelectorsBits = 15; |
49 | const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize)); | 49 | const unsigned kNumSelectorsMax = 2 + kBlockSizeMax / kGroupSize; |
50 | 50 | ||
51 | const unsigned kRleModeRepSize = 4; | 51 | const unsigned kRleModeRepSize = 4; |
52 | 52 | ||
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index ef2555a..af0b312 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp | |||
@@ -6,18 +6,20 @@ | |||
6 | #include "../../../C/BwtSort.h" | 6 | #include "../../../C/BwtSort.h" |
7 | #include "../../../C/HuffEnc.h" | 7 | #include "../../../C/HuffEnc.h" |
8 | 8 | ||
9 | #include "BZip2Crc.h" | ||
10 | #include "BZip2Encoder.h" | 9 | #include "BZip2Encoder.h" |
11 | #include "Mtf8.h" | ||
12 | 10 | ||
13 | namespace NCompress { | 11 | namespace NCompress { |
14 | namespace NBZip2 { | 12 | namespace NBZip2 { |
15 | 13 | ||
16 | const unsigned kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20 | 14 | #define HUFFMAN_LEN 16 |
17 | 15 | #if HUFFMAN_LEN > Z7_HUFFMAN_LEN_MAX | |
18 | static const UInt32 kBufferSize = (1 << 17); | 16 | #error Stop_Compiling_Bad_HUFFMAN_LEN_BZip2Encoder |
17 | #endif | ||
18 | |||
19 | static const size_t kBufferSize = 1 << 17; | ||
19 | static const unsigned kNumHuffPasses = 4; | 20 | static const unsigned kNumHuffPasses = 4; |
20 | 21 | ||
22 | |||
21 | bool CThreadInfo::Alloc() | 23 | bool CThreadInfo::Alloc() |
22 | { | 24 | { |
23 | if (!m_BlockSorterIndex) | 25 | if (!m_BlockSorterIndex) |
@@ -27,11 +29,15 @@ bool CThreadInfo::Alloc() | |||
27 | return false; | 29 | return false; |
28 | } | 30 | } |
29 | 31 | ||
30 | if (!m_Block) | 32 | if (!m_Block_Base) |
31 | { | 33 | { |
32 | m_Block = (Byte *)::MidAlloc(kBlockSizeMax * 5 + kBlockSizeMax / 10 + (20 << 10)); | 34 | const unsigned kPadSize = 1 << 7; // we need at least 1 byte backward padding, becuase we use (m_Block - 1) pointer; |
33 | if (!m_Block) | 35 | m_Block_Base = (Byte *)::MidAlloc(kBlockSizeMax * 5 |
36 | + kBlockSizeMax / 10 + (20 << 10) | ||
37 | + kPadSize); | ||
38 | if (!m_Block_Base) | ||
34 | return false; | 39 | return false; |
40 | m_Block = m_Block_Base + kPadSize; | ||
35 | m_MtfArray = m_Block + kBlockSizeMax; | 41 | m_MtfArray = m_Block + kBlockSizeMax; |
36 | m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2; | 42 | m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2; |
37 | } | 43 | } |
@@ -42,8 +48,8 @@ void CThreadInfo::Free() | |||
42 | { | 48 | { |
43 | ::BigFree(m_BlockSorterIndex); | 49 | ::BigFree(m_BlockSorterIndex); |
44 | m_BlockSorterIndex = NULL; | 50 | m_BlockSorterIndex = NULL; |
45 | ::MidFree(m_Block); | 51 | ::MidFree(m_Block_Base); |
46 | m_Block = NULL; | 52 | m_Block_Base = NULL; |
47 | } | 53 | } |
48 | 54 | ||
49 | #ifndef Z7_ST | 55 | #ifndef Z7_ST |
@@ -60,10 +66,14 @@ HRESULT CThreadInfo::Create() | |||
60 | if (wres == 0) { wres = CanWriteEvent.Create(); | 66 | if (wres == 0) { wres = CanWriteEvent.Create(); |
61 | if (wres == 0) | 67 | if (wres == 0) |
62 | { | 68 | { |
63 | if (Encoder->_props.Affinity != 0) | 69 | wres = |
64 | wres = Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity); | 70 | #ifdef _WIN32 |
65 | else | 71 | Encoder->_props.NumThreadGroups > 1 ? |
66 | wres = Thread.Create(MFThread, this); | 72 | Thread.Create_With_Group(MFThread, this, ThreadNextGroup_GetNext(&Encoder->ThreadNextGroup), 0) : // affinity |
73 | #endif | ||
74 | Encoder->_props.Affinity != 0 ? | ||
75 | Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity) : | ||
76 | Thread.Create(MFThread, this); | ||
67 | }}} | 77 | }}} |
68 | return HRESULT_FROM_WIN32(wres); | 78 | return HRESULT_FROM_WIN32(wres); |
69 | } | 79 | } |
@@ -216,94 +226,251 @@ void CEncoder::Free() | |||
216 | } | 226 | } |
217 | #endif | 227 | #endif |
218 | 228 | ||
229 | struct CRleEncoder | ||
230 | { | ||
231 | const Byte *_src; | ||
232 | const Byte *_srcLim; | ||
233 | Byte *_dest; | ||
234 | const Byte *_destLim; | ||
235 | Byte _prevByte; | ||
236 | unsigned _numReps; | ||
237 | |||
238 | void Encode(); | ||
239 | }; | ||
240 | |||
241 | Z7_NO_INLINE | ||
242 | void CRleEncoder::Encode() | ||
243 | { | ||
244 | const Byte *src = _src; | ||
245 | const Byte * const srcLim = _srcLim; | ||
246 | Byte *dest = _dest; | ||
247 | const Byte * const destLim = _destLim; | ||
248 | Byte prev = _prevByte; | ||
249 | unsigned numReps = _numReps; | ||
250 | // (dest < destLim) | ||
251 | // src = srcLim; // for debug | ||
252 | while (dest < destLim) | ||
253 | { | ||
254 | if (src == srcLim) | ||
255 | break; | ||
256 | const Byte b = *src++; | ||
257 | if (b != prev) | ||
258 | { | ||
259 | if (numReps >= kRleModeRepSize) | ||
260 | *dest++ = (Byte)(numReps - kRleModeRepSize); | ||
261 | *dest++ = b; | ||
262 | numReps = 1; | ||
263 | prev = b; | ||
264 | /* | ||
265 | { // speed optimization code: | ||
266 | if (dest >= destLim || src == srcLim) | ||
267 | break; | ||
268 | const Byte b2 = *src++; | ||
269 | *dest++ = b2; | ||
270 | numReps += (prev == b2); | ||
271 | prev = b2; | ||
272 | } | ||
273 | */ | ||
274 | continue; | ||
275 | } | ||
276 | numReps++; | ||
277 | if (numReps <= kRleModeRepSize) | ||
278 | *dest++ = b; | ||
279 | else if (numReps == kRleModeRepSize + 255) | ||
280 | { | ||
281 | *dest++ = (Byte)(numReps - kRleModeRepSize); | ||
282 | numReps = 0; | ||
283 | } | ||
284 | } | ||
285 | _src = src; | ||
286 | _dest = dest; | ||
287 | _prevByte = prev; | ||
288 | _numReps = numReps; | ||
289 | // (dest <= destLim + 1) | ||
290 | } | ||
291 | |||
292 | |||
293 | // out: return value is blockSize: size of data filled in buffer[]: | ||
294 | // (returned_blockSize <= _props.BlockSizeMult * kBlockSizeStep) | ||
219 | UInt32 CEncoder::ReadRleBlock(Byte *buffer) | 295 | UInt32 CEncoder::ReadRleBlock(Byte *buffer) |
220 | { | 296 | { |
297 | CRleEncoder rle; | ||
221 | UInt32 i = 0; | 298 | UInt32 i = 0; |
222 | Byte prevByte; | 299 | if (m_InStream.ReadByte(rle._prevByte)) |
223 | if (m_InStream.ReadByte(prevByte)) | ||
224 | { | 300 | { |
225 | NumBlocks++; | 301 | NumBlocks++; |
226 | const UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; | 302 | const UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; // -1 for RLE |
227 | unsigned numReps = 1; | 303 | rle._destLim = buffer + blockSize; |
228 | buffer[i++] = prevByte; | 304 | rle._numReps = 1; |
229 | while (i < blockSize) // "- 1" to support RLE | 305 | buffer[i++] = rle._prevByte; |
306 | while (i < blockSize) | ||
230 | { | 307 | { |
231 | Byte b; | 308 | rle._dest = buffer + i; |
232 | if (!m_InStream.ReadByte(b)) | 309 | size_t rem; |
310 | const Byte * const ptr = m_InStream.Lookahead(rem); | ||
311 | if (rem == 0) | ||
233 | break; | 312 | break; |
234 | if (b != prevByte) | 313 | rle._src = ptr; |
235 | { | 314 | rle._srcLim = ptr + rem; |
236 | if (numReps >= kRleModeRepSize) | 315 | rle.Encode(); |
237 | buffer[i++] = (Byte)(numReps - kRleModeRepSize); | 316 | m_InStream.Skip((size_t)(rle._src - ptr)); |
238 | buffer[i++] = b; | 317 | i = (UInt32)(size_t)(rle._dest - buffer); |
239 | numReps = 1; | 318 | // (i <= blockSize + 1) |
240 | prevByte = b; | ||
241 | continue; | ||
242 | } | ||
243 | numReps++; | ||
244 | if (numReps <= kRleModeRepSize) | ||
245 | buffer[i++] = b; | ||
246 | else if (numReps == kRleModeRepSize + 255) | ||
247 | { | ||
248 | buffer[i++] = (Byte)(numReps - kRleModeRepSize); | ||
249 | numReps = 0; | ||
250 | } | ||
251 | } | 319 | } |
252 | // it's to support original BZip2 decoder | 320 | const int n = (int)rle._numReps - (int)kRleModeRepSize; |
253 | if (numReps >= kRleModeRepSize) | 321 | if (n >= 0) |
254 | buffer[i++] = (Byte)(numReps - kRleModeRepSize); | 322 | buffer[i++] = (Byte)n; |
255 | } | 323 | } |
256 | return i; | 324 | return i; |
257 | } | 325 | } |
258 | 326 | ||
259 | void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) { m_OutStreamCurrent->WriteBits(value, numBits); } | 327 | |
260 | void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b, 8); } | 328 | |
261 | void CThreadInfo::WriteBit2(Byte v) { WriteBits2(v, 1); } | 329 | Z7_NO_INLINE |
262 | void CThreadInfo::WriteCrc2(UInt32 v) | 330 | void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) |
263 | { | 331 | { m_OutStreamCurrent.WriteBits(value, numBits); } |
264 | for (unsigned i = 0; i < 4; i++) | 332 | /* |
265 | WriteByte2(((Byte)(v >> (24 - i * 8)))); | 333 | Z7_NO_INLINE |
334 | void CThreadInfo::WriteByte2(unsigned b) | ||
335 | { m_OutStreamCurrent.WriteByte(b); } | ||
336 | */ | ||
337 | // void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); } | ||
338 | Z7_NO_INLINE | ||
339 | void CEncoder::WriteByte(Byte b) { m_OutStream.WriteByte(b); } | ||
340 | |||
341 | |||
342 | #define WRITE_BITS_UPDATE(value, numBits) \ | ||
343 | { \ | ||
344 | numBits -= _bitPos; \ | ||
345 | const UInt32 hi = value >> numBits; \ | ||
346 | *_buf++ = (Byte)(_curByte | hi); \ | ||
347 | value -= hi << numBits; \ | ||
348 | _bitPos = 8; \ | ||
349 | _curByte = 0; \ | ||
266 | } | 350 | } |
267 | 351 | ||
268 | void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); } | 352 | #if HUFFMAN_LEN > 16 |
269 | void CEncoder::WriteByte(Byte b) { WriteBits(b, 8); } | 353 | |
270 | // void CEncoder::WriteBit(Byte v) { WriteBits(v, 1); } | 354 | #define WRITE_BITS_HUFF(value2, numBits2) \ |
271 | void CEncoder::WriteCrc(UInt32 v) | 355 | { \ |
272 | { | 356 | UInt32 value = value2; \ |
273 | for (unsigned i = 0; i < 4; i++) | 357 | unsigned numBits = numBits2; \ |
274 | WriteByte(((Byte)(v >> (24 - i * 8)))); | 358 | while (numBits >= _bitPos) { \ |
359 | WRITE_BITS_UPDATE(value, numBits) \ | ||
360 | } \ | ||
361 | _bitPos -= numBits; \ | ||
362 | _curByte |= (value << _bitPos); \ | ||
363 | } | ||
364 | |||
365 | #else // HUFFMAN_LEN <= 16 | ||
366 | |||
367 | // numBits2 <= 16 is supported | ||
368 | #define WRITE_BITS_HUFF(value2, numBits2) \ | ||
369 | { \ | ||
370 | UInt32 value = value2; \ | ||
371 | unsigned numBits = numBits2; \ | ||
372 | if (numBits >= _bitPos) \ | ||
373 | { \ | ||
374 | WRITE_BITS_UPDATE(value, numBits) \ | ||
375 | if (numBits >= _bitPos) \ | ||
376 | { \ | ||
377 | numBits -= _bitPos; \ | ||
378 | const UInt32 hi = value >> numBits; \ | ||
379 | *_buf++ = (Byte)hi; \ | ||
380 | value -= hi << numBits; \ | ||
381 | } \ | ||
382 | } \ | ||
383 | _bitPos -= numBits; \ | ||
384 | _curByte |= (value << _bitPos); \ | ||
385 | } | ||
386 | |||
387 | #endif | ||
388 | |||
389 | #define WRITE_BITS_8(value2, numBits2) \ | ||
390 | { \ | ||
391 | UInt32 value = value2; \ | ||
392 | unsigned numBits = numBits2; \ | ||
393 | if (numBits >= _bitPos) \ | ||
394 | { \ | ||
395 | WRITE_BITS_UPDATE(value, numBits) \ | ||
396 | } \ | ||
397 | _bitPos -= numBits; \ | ||
398 | _curByte |= (value << _bitPos); \ | ||
399 | } | ||
400 | |||
401 | #define WRITE_BIT_PRE \ | ||
402 | { _bitPos--; } | ||
403 | |||
404 | #define WRITE_BIT_POST \ | ||
405 | { \ | ||
406 | if (_bitPos == 0) \ | ||
407 | { \ | ||
408 | *_buf++ = (Byte)_curByte; \ | ||
409 | _curByte = 0; \ | ||
410 | _bitPos = 8; \ | ||
411 | } \ | ||
412 | } | ||
413 | |||
414 | #define WRITE_BIT_0 \ | ||
415 | { \ | ||
416 | WRITE_BIT_PRE \ | ||
417 | WRITE_BIT_POST \ | ||
418 | } | ||
419 | |||
420 | #define WRITE_BIT_1 \ | ||
421 | { \ | ||
422 | WRITE_BIT_PRE \ | ||
423 | _curByte |= 1u << _bitPos; \ | ||
424 | WRITE_BIT_POST \ | ||
275 | } | 425 | } |
276 | 426 | ||
277 | 427 | ||
278 | // blockSize > 0 | 428 | // blockSize > 0 |
279 | void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | 429 | void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) |
280 | { | 430 | { |
281 | WriteBit2(0); // Randomised = false | 431 | // WriteBit2(0); // Randomised = false |
282 | |||
283 | { | 432 | { |
284 | UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize); | 433 | const UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize); |
285 | // if (m_BlockSorterIndex[origPtr] != 0) throw 1; | 434 | // if (m_BlockSorterIndex[origPtr] != 0) throw 1; |
286 | m_BlockSorterIndex[origPtr] = blockSize; | 435 | m_BlockSorterIndex[origPtr] = blockSize; |
287 | WriteBits2(origPtr, kNumOrigBits); | 436 | WriteBits2(origPtr, kNumOrigBits + 1); // + 1 for additional high bit flag (Randomised = false) |
288 | } | 437 | } |
289 | 438 | Byte mtfBuf[256]; | |
290 | CMtf8Encoder mtf; | 439 | // memset(mtfBuf, 0, sizeof(mtfBuf)); // to disable MSVC warning |
291 | unsigned numInUse = 0; | 440 | unsigned numInUse; |
292 | { | 441 | { |
293 | Byte inUse[256]; | 442 | Byte inUse[256]; |
294 | Byte inUse16[16]; | 443 | Byte inUse16[16]; |
295 | UInt32 i; | 444 | unsigned i; |
296 | for (i = 0; i < 256; i++) | 445 | for (i = 0; i < 256; i++) |
297 | inUse[i] = 0; | 446 | inUse[i] = 0; |
298 | for (i = 0; i < 16; i++) | 447 | for (i = 0; i < 16; i++) |
299 | inUse16[i] = 0; | 448 | inUse16[i] = 0; |
300 | for (i = 0; i < blockSize; i++) | 449 | { |
301 | inUse[block[i]] = 1; | 450 | const Byte * cur = block; |
451 | block = block + (size_t)blockSize - 1; | ||
452 | if (cur != block) | ||
453 | { | ||
454 | do | ||
455 | { | ||
456 | const unsigned b0 = cur[0]; | ||
457 | const unsigned b1 = cur[1]; | ||
458 | cur += 2; | ||
459 | inUse[b0] = 1; | ||
460 | inUse[b1] = 1; | ||
461 | } | ||
462 | while (cur < block); | ||
463 | } | ||
464 | if (cur == block) | ||
465 | inUse[cur[0]] = 1; | ||
466 | block -= blockSize; // block pointer is (original_block - 1) | ||
467 | } | ||
468 | numInUse = 0; | ||
302 | for (i = 0; i < 256; i++) | 469 | for (i = 0; i < 256; i++) |
303 | if (inUse[i]) | 470 | if (inUse[i]) |
304 | { | 471 | { |
305 | inUse16[i >> 4] = 1; | 472 | inUse16[i >> 4] = 1; |
306 | mtf.Buf[numInUse++] = (Byte)i; | 473 | mtfBuf[numInUse++] = (Byte)i; |
307 | } | 474 | } |
308 | for (i = 0; i < 16; i++) | 475 | for (i = 0; i < 16; i++) |
309 | WriteBit2(inUse16[i]); | 476 | WriteBit2(inUse16[i]); |
@@ -311,65 +478,88 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
311 | if (inUse16[i >> 4]) | 478 | if (inUse16[i >> 4]) |
312 | WriteBit2(inUse[i]); | 479 | WriteBit2(inUse[i]); |
313 | } | 480 | } |
314 | unsigned alphaSize = numInUse + 2; | 481 | const unsigned alphaSize = numInUse + 2; |
315 | 482 | ||
316 | Byte *mtfs = m_MtfArray; | ||
317 | UInt32 mtfArraySize = 0; | ||
318 | UInt32 symbolCounts[kMaxAlphaSize]; | 483 | UInt32 symbolCounts[kMaxAlphaSize]; |
319 | { | 484 | { |
320 | for (unsigned i = 0; i < kMaxAlphaSize; i++) | 485 | for (unsigned i = 0; i < kMaxAlphaSize; i++) |
321 | symbolCounts[i] = 0; | 486 | symbolCounts[i] = 0; |
487 | symbolCounts[(size_t)alphaSize - 1] = 1; | ||
322 | } | 488 | } |
323 | 489 | ||
490 | Byte *mtfs = m_MtfArray; | ||
324 | { | 491 | { |
325 | UInt32 rleSize = 0; | ||
326 | UInt32 i = 0; | ||
327 | const UInt32 *bsIndex = m_BlockSorterIndex; | 492 | const UInt32 *bsIndex = m_BlockSorterIndex; |
328 | block--; | 493 | const UInt32 *bsIndex_rle = bsIndex; |
494 | const UInt32 * const bsIndex_end = bsIndex + blockSize; | ||
495 | // block--; // backward fix | ||
496 | // block pointer is (original_block - 1) | ||
329 | do | 497 | do |
330 | { | 498 | { |
331 | unsigned pos = mtf.FindAndMove(block[bsIndex[i]]); | 499 | const Byte v = block[*bsIndex++]; |
332 | if (pos == 0) | 500 | Byte a = mtfBuf[0]; |
333 | rleSize++; | 501 | if (v != a) |
334 | else | ||
335 | { | 502 | { |
336 | while (rleSize != 0) | 503 | mtfBuf[0] = v; |
337 | { | 504 | { |
338 | rleSize--; | 505 | UInt32 rleSize = (UInt32)(size_t)(bsIndex - bsIndex_rle) - 1; |
339 | mtfs[mtfArraySize++] = (Byte)(rleSize & 1); | 506 | bsIndex_rle = bsIndex; |
340 | symbolCounts[rleSize & 1]++; | 507 | while (rleSize) |
341 | rleSize >>= 1; | 508 | { |
509 | const unsigned sym = (unsigned)(--rleSize & 1); | ||
510 | *mtfs++ = (Byte)sym; | ||
511 | symbolCounts[sym]++; | ||
512 | rleSize >>= 1; | ||
513 | } | ||
342 | } | 514 | } |
343 | if (pos >= 0xFE) | 515 | unsigned pos1 = 2; // = real_pos + 1 |
516 | Byte b; | ||
517 | b = mtfBuf[1]; mtfBuf[1] = a; if (v != b) | ||
518 | { a = mtfBuf[2]; mtfBuf[2] = b; if (v == a) pos1 = 3; | ||
519 | else { b = mtfBuf[3]; mtfBuf[3] = a; if (v == b) pos1 = 4; | ||
520 | else | ||
521 | { | ||
522 | Byte *m = mtfBuf + 7; | ||
523 | for (;;) | ||
524 | { | ||
525 | a = m[-3]; m[-3] = b; if (v == a) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 2)); break; } | ||
526 | b = m[-2]; m[-2] = a; if (v == b) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 1)); break; } | ||
527 | a = m[-1]; m[-1] = b; if (v == a) { pos1 = (unsigned)(size_t)(m - (mtfBuf )); break; } | ||
528 | b = m[ 0]; m[ 0] = a; m += 4; if (v == b) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 3)); break; } | ||
529 | } | ||
530 | }}} | ||
531 | symbolCounts[pos1]++; | ||
532 | if (pos1 >= 0xff) | ||
344 | { | 533 | { |
345 | mtfs[mtfArraySize++] = 0xFF; | 534 | *mtfs++ = 0xff; |
346 | mtfs[mtfArraySize++] = (Byte)(pos - 0xFE); | 535 | // pos1 -= 0xff; |
536 | pos1++; // we need only low byte | ||
347 | } | 537 | } |
348 | else | 538 | *mtfs++ = (Byte)pos1; |
349 | mtfs[mtfArraySize++] = (Byte)(pos + 1); | ||
350 | symbolCounts[(size_t)pos + 1]++; | ||
351 | } | 539 | } |
352 | } | 540 | } |
353 | while (++i < blockSize); | 541 | while (bsIndex < bsIndex_end); |
354 | 542 | ||
355 | while (rleSize != 0) | 543 | UInt32 rleSize = (UInt32)(size_t)(bsIndex - bsIndex_rle); |
544 | while (rleSize) | ||
356 | { | 545 | { |
357 | rleSize--; | 546 | const unsigned sym = (unsigned)(--rleSize & 1); |
358 | mtfs[mtfArraySize++] = (Byte)(rleSize & 1); | 547 | *mtfs++ = (Byte)sym; |
359 | symbolCounts[rleSize & 1]++; | 548 | symbolCounts[sym]++; |
360 | rleSize >>= 1; | 549 | rleSize >>= 1; |
361 | } | 550 | } |
362 | 551 | ||
363 | if (alphaSize < 256) | 552 | unsigned d = alphaSize - 1; |
364 | mtfs[mtfArraySize++] = (Byte)(alphaSize - 1); | 553 | if (alphaSize >= 256) |
365 | else | ||
366 | { | 554 | { |
367 | mtfs[mtfArraySize++] = 0xFF; | 555 | *mtfs++ = 0xff; |
368 | mtfs[mtfArraySize++] = (Byte)(alphaSize - 256); | 556 | d = alphaSize; // (-256) |
369 | } | 557 | } |
370 | symbolCounts[(size_t)alphaSize - 1]++; | 558 | *mtfs++ = (Byte)d; |
371 | } | 559 | } |
372 | 560 | ||
561 | const Byte * const mtf_lim = mtfs; | ||
562 | |||
373 | UInt32 numSymbols = 0; | 563 | UInt32 numSymbols = 0; |
374 | { | 564 | { |
375 | for (unsigned i = 0; i < kMaxAlphaSize; i++) | 565 | for (unsigned i = 0; i < kMaxAlphaSize; i++) |
@@ -378,34 +568,30 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
378 | 568 | ||
379 | unsigned bestNumTables = kNumTablesMin; | 569 | unsigned bestNumTables = kNumTablesMin; |
380 | UInt32 bestPrice = 0xFFFFFFFF; | 570 | UInt32 bestPrice = 0xFFFFFFFF; |
381 | UInt32 startPos = m_OutStreamCurrent->GetPos(); | 571 | const UInt32 startPos = m_OutStreamCurrent.GetPos(); |
382 | Byte startCurByte = m_OutStreamCurrent->GetCurByte(); | 572 | const unsigned startCurByte = m_OutStreamCurrent.GetCurByte(); |
383 | for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++) | 573 | for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++) |
384 | { | 574 | { |
385 | unsigned numTables; | 575 | unsigned numTables; |
386 | 576 | ||
387 | if (m_OptimizeNumTables) | 577 | if (m_OptimizeNumTables) |
388 | { | 578 | { |
389 | m_OutStreamCurrent->SetPos(startPos); | 579 | m_OutStreamCurrent.SetPos(startPos); |
390 | m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); | 580 | m_OutStreamCurrent.SetCurState(startPos & 7, startCurByte); |
391 | if (nt <= kNumTablesMax) | 581 | numTables = (nt <= kNumTablesMax ? nt : bestNumTables); |
392 | numTables = nt; | ||
393 | else | ||
394 | numTables = bestNumTables; | ||
395 | } | 582 | } |
396 | else | 583 | else |
397 | { | 584 | { |
398 | if (numSymbols < 200) numTables = 2; | 585 | if (numSymbols < 200) numTables = 2; |
399 | else if (numSymbols < 600) numTables = 3; | 586 | else if (numSymbols < 600) numTables = 3; |
400 | else if (numSymbols < 1200) numTables = 4; | 587 | else if (numSymbols < 1200) numTables = 4; |
401 | else if (numSymbols < 2400) numTables = 5; | 588 | else if (numSymbols < 2400) numTables = 5; |
402 | else numTables = 6; | 589 | else numTables = 6; |
403 | } | 590 | } |
404 | 591 | ||
405 | WriteBits2(numTables, kNumTablesBits); | 592 | WriteBits2(numTables, kNumTablesBits); |
406 | 593 | const unsigned numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize; | |
407 | UInt32 numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize; | 594 | WriteBits2((UInt32)numSelectors, kNumSelectorsBits); |
408 | WriteBits2(numSelectors, kNumSelectorsBits); | ||
409 | 595 | ||
410 | { | 596 | { |
411 | UInt32 remFreq = numSymbols; | 597 | UInt32 remFreq = numSymbols; |
@@ -436,28 +622,23 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
436 | 622 | ||
437 | for (unsigned pass = 0; pass < kNumHuffPasses; pass++) | 623 | for (unsigned pass = 0; pass < kNumHuffPasses; pass++) |
438 | { | 624 | { |
625 | memset(Freqs, 0, sizeof(Freqs[0]) * numTables); | ||
626 | // memset(Freqs, 0, sizeof(Freqs)); | ||
439 | { | 627 | { |
440 | unsigned t = 0; | 628 | mtfs = m_MtfArray; |
441 | do | ||
442 | memset(Freqs[t], 0, sizeof(Freqs[t])); | ||
443 | while (++t < numTables); | ||
444 | } | ||
445 | |||
446 | { | ||
447 | UInt32 mtfPos = 0; | ||
448 | UInt32 g = 0; | 629 | UInt32 g = 0; |
449 | do | 630 | do |
450 | { | 631 | { |
451 | UInt32 symbols[kGroupSize]; | 632 | unsigned symbols[kGroupSize]; |
452 | unsigned i = 0; | 633 | unsigned i = 0; |
453 | do | 634 | do |
454 | { | 635 | { |
455 | UInt32 symbol = mtfs[mtfPos++]; | 636 | UInt32 symbol = *mtfs++; |
456 | if (symbol >= 0xFF) | 637 | if (symbol >= 0xFF) |
457 | symbol += mtfs[mtfPos++]; | 638 | symbol += *mtfs++; |
458 | symbols[i] = symbol; | 639 | symbols[i] = symbol; |
459 | } | 640 | } |
460 | while (++i < kGroupSize && mtfPos < mtfArraySize); | 641 | while (++i < kGroupSize && mtfs < mtf_lim); |
461 | 642 | ||
462 | UInt32 bestPrice2 = 0xFFFFFFFF; | 643 | UInt32 bestPrice2 = 0xFFFFFFFF; |
463 | unsigned t = 0; | 644 | unsigned t = 0; |
@@ -482,7 +663,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
482 | freqs[symbols[j]]++; | 663 | freqs[symbols[j]]++; |
483 | while (++j < i); | 664 | while (++j < i); |
484 | } | 665 | } |
485 | while (mtfPos < mtfArraySize); | 666 | while (mtfs < mtf_lim); |
486 | } | 667 | } |
487 | 668 | ||
488 | unsigned t = 0; | 669 | unsigned t = 0; |
@@ -494,11 +675,15 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
494 | if (freqs[i] == 0) | 675 | if (freqs[i] == 0) |
495 | freqs[i] = 1; | 676 | freqs[i] = 1; |
496 | while (++i < alphaSize); | 677 | while (++i < alphaSize); |
497 | Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding); | 678 | Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, HUFFMAN_LEN); |
498 | } | 679 | } |
499 | while (++t < numTables); | 680 | while (++t < numTables); |
500 | } | 681 | } |
501 | 682 | ||
683 | unsigned _bitPos; // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte | ||
684 | unsigned _curByte; // low (_bitPos) bits are zeros | ||
685 | // high (8 - _bitPos) bits are filled | ||
686 | Byte *_buf; | ||
502 | { | 687 | { |
503 | Byte mtfSel[kNumTablesMax]; | 688 | Byte mtfSel[kNumTablesMax]; |
504 | { | 689 | { |
@@ -507,81 +692,97 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
507 | mtfSel[t] = (Byte)t; | 692 | mtfSel[t] = (Byte)t; |
508 | while (++t < numTables); | 693 | while (++t < numTables); |
509 | } | 694 | } |
695 | |||
696 | _bitPos = m_OutStreamCurrent._bitPos; | ||
697 | _curByte = m_OutStreamCurrent._curByte; | ||
698 | _buf = m_OutStreamCurrent._buf; | ||
699 | // stream.Init_from_Global(m_OutStreamCurrent); | ||
510 | 700 | ||
511 | UInt32 i = 0; | 701 | const Byte *selectors = m_Selectors; |
702 | const Byte * const selectors_lim = selectors + numSelectors; | ||
703 | Byte prev = 0; // mtfSel[0]; | ||
512 | do | 704 | do |
513 | { | 705 | { |
514 | Byte sel = m_Selectors[i]; | 706 | const Byte sel = *selectors++; |
515 | unsigned pos; | 707 | if (prev != sel) |
516 | for (pos = 0; mtfSel[pos] != sel; pos++) | 708 | { |
517 | WriteBit2(1); | 709 | Byte *mtfSel_cur = &mtfSel[1]; |
518 | WriteBit2(0); | 710 | for (;;) |
519 | for (; pos > 0; pos--) | 711 | { |
520 | mtfSel[pos] = mtfSel[(size_t)pos - 1]; | 712 | WRITE_BIT_1 |
521 | mtfSel[0] = sel; | 713 | const Byte next = *mtfSel_cur; |
714 | *mtfSel_cur++ = prev; | ||
715 | prev = next; | ||
716 | if (next == sel) | ||
717 | break; | ||
718 | } | ||
719 | // mtfSel[0] = sel; | ||
720 | } | ||
721 | WRITE_BIT_0 | ||
522 | } | 722 | } |
523 | while (++i < numSelectors); | 723 | while (selectors != selectors_lim); |
524 | } | 724 | } |
525 | |||
526 | { | 725 | { |
527 | unsigned t = 0; | 726 | unsigned t = 0; |
528 | do | 727 | do |
529 | { | 728 | { |
530 | const Byte *lens = Lens[t]; | 729 | const Byte *lens = Lens[t]; |
531 | UInt32 len = lens[0]; | 730 | unsigned len = lens[0]; |
532 | WriteBits2(len, kNumLevelsBits); | 731 | WRITE_BITS_8(len, kNumLevelsBits) |
533 | unsigned i = 0; | 732 | unsigned i = 0; |
534 | do | 733 | do |
535 | { | 734 | { |
536 | UInt32 level = lens[i]; | 735 | const unsigned level = lens[i]; |
537 | while (len != level) | 736 | while (len != level) |
538 | { | 737 | { |
539 | WriteBit2(1); | 738 | WRITE_BIT_1 |
540 | if (len < level) | 739 | if (len < level) |
541 | { | 740 | { |
542 | WriteBit2(0); | ||
543 | len++; | 741 | len++; |
742 | WRITE_BIT_0 | ||
544 | } | 743 | } |
545 | else | 744 | else |
546 | { | 745 | { |
547 | WriteBit2(1); | ||
548 | len--; | 746 | len--; |
747 | WRITE_BIT_1 | ||
549 | } | 748 | } |
550 | } | 749 | } |
551 | WriteBit2(0); | 750 | WRITE_BIT_0 |
552 | } | 751 | } |
553 | while (++i < alphaSize); | 752 | while (++i < alphaSize); |
554 | } | 753 | } |
555 | while (++t < numTables); | 754 | while (++t < numTables); |
556 | } | 755 | } |
557 | |||
558 | { | 756 | { |
559 | UInt32 groupSize = 0; | 757 | UInt32 groupSize = 1; |
560 | UInt32 groupIndex = 0; | 758 | const Byte *selectors = m_Selectors; |
561 | const Byte *lens = NULL; | 759 | const Byte *lens = NULL; |
562 | const UInt32 *codes = NULL; | 760 | const UInt32 *codes = NULL; |
563 | UInt32 mtfPos = 0; | 761 | mtfs = m_MtfArray; |
564 | do | 762 | do |
565 | { | 763 | { |
566 | UInt32 symbol = mtfs[mtfPos++]; | 764 | unsigned symbol = *mtfs++; |
567 | if (symbol >= 0xFF) | 765 | if (symbol >= 0xFF) |
568 | symbol += mtfs[mtfPos++]; | 766 | symbol += *mtfs++; |
569 | if (groupSize == 0) | 767 | if (--groupSize == 0) |
570 | { | 768 | { |
571 | groupSize = kGroupSize; | 769 | groupSize = kGroupSize; |
572 | unsigned t = m_Selectors[groupIndex++]; | 770 | const unsigned t = *selectors++; |
573 | lens = Lens[t]; | 771 | lens = Lens[t]; |
574 | codes = Codes[t]; | 772 | codes = Codes[t]; |
575 | } | 773 | } |
576 | groupSize--; | 774 | WRITE_BITS_HUFF(codes[symbol], lens[symbol]) |
577 | m_OutStreamCurrent->WriteBits(codes[symbol], lens[symbol]); | ||
578 | } | 775 | } |
579 | while (mtfPos < mtfArraySize); | 776 | while (mtfs < mtf_lim); |
580 | } | 777 | } |
778 | // Restore_from_Local: | ||
779 | m_OutStreamCurrent._bitPos = _bitPos; | ||
780 | m_OutStreamCurrent._curByte = _curByte; | ||
781 | m_OutStreamCurrent._buf = _buf; | ||
581 | 782 | ||
582 | if (!m_OptimizeNumTables) | 783 | if (!m_OptimizeNumTables) |
583 | break; | 784 | break; |
584 | UInt32 price = m_OutStreamCurrent->GetPos() - startPos; | 785 | const UInt32 price = m_OutStreamCurrent.GetPos() - startPos; |
585 | if (price <= bestPrice) | 786 | if (price <= bestPrice) |
586 | { | 787 | { |
587 | if (nt == kNumTablesMax) | 788 | if (nt == kNumTablesMax) |
@@ -592,6 +793,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
592 | } | 793 | } |
593 | } | 794 | } |
594 | 795 | ||
796 | |||
595 | // blockSize > 0 | 797 | // blockSize > 0 |
596 | UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize) | 798 | UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize) |
597 | { | 799 | { |
@@ -603,142 +805,126 @@ UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize) | |||
603 | WriteByte2(kBlockSig5); | 805 | WriteByte2(kBlockSig5); |
604 | 806 | ||
605 | CBZip2Crc crc; | 807 | CBZip2Crc crc; |
606 | unsigned numReps = 0; | 808 | const Byte * const lim = block + blockSize; |
607 | Byte prevByte = block[0]; | 809 | unsigned b = *block++; |
608 | UInt32 i = 0; | 810 | crc.UpdateByte(b); |
609 | do | 811 | for (;;) |
610 | { | 812 | { |
611 | Byte b = block[i]; | 813 | const unsigned prev = b; |
612 | if (numReps == kRleModeRepSize) | 814 | if (block >= lim) { break; } b = *block++; crc.UpdateByte(b); if (prev != b) continue; |
613 | { | 815 | if (block >= lim) { break; } b = *block++; crc.UpdateByte(b); if (prev != b) continue; |
614 | for (; b > 0; b--) | 816 | if (block >= lim) { break; } b = *block++; crc.UpdateByte(b); if (prev != b) continue; |
615 | crc.UpdateByte(prevByte); | 817 | if (block >= lim) { break; } b = *block++; if (b) do crc.UpdateByte(prev); while (--b); |
616 | numReps = 0; | 818 | if (block >= lim) { break; } b = *block++; crc.UpdateByte(b); |
617 | continue; | ||
618 | } | ||
619 | if (prevByte == b) | ||
620 | numReps++; | ||
621 | else | ||
622 | { | ||
623 | numReps = 1; | ||
624 | prevByte = b; | ||
625 | } | ||
626 | crc.UpdateByte(b); | ||
627 | } | 819 | } |
628 | while (++i < blockSize); | 820 | const UInt32 crcRes = crc.GetDigest(); |
629 | UInt32 crcRes = crc.GetDigest(); | 821 | for (int i = 24; i >= 0; i -= 8) |
630 | WriteCrc2(crcRes); | 822 | WriteByte2((Byte)(crcRes >> i)); |
631 | EncodeBlock(block, blockSize); | 823 | EncodeBlock(lim - blockSize, blockSize); |
632 | return crcRes; | 824 | return crcRes; |
633 | } | 825 | } |
634 | 826 | ||
827 | |||
635 | void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses) | 828 | void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses) |
636 | { | 829 | { |
637 | UInt32 numCrcs = m_NumCrcs; | 830 | const UInt32 numCrcs = m_NumCrcs; |
638 | bool needCompare = false; | 831 | |
639 | 832 | const UInt32 startBytePos = m_OutStreamCurrent.GetBytePos(); | |
640 | UInt32 startBytePos = m_OutStreamCurrent->GetBytePos(); | 833 | const UInt32 startPos = m_OutStreamCurrent.GetPos(); |
641 | UInt32 startPos = m_OutStreamCurrent->GetPos(); | 834 | const unsigned startCurByte = m_OutStreamCurrent.GetCurByte(); |
642 | Byte startCurByte = m_OutStreamCurrent->GetCurByte(); | 835 | unsigned endCurByte = 0; |
643 | Byte endCurByte = 0; | 836 | UInt32 endPos = 0; // 0 means no no additional passes |
644 | UInt32 endPos = 0; | ||
645 | if (numPasses > 1 && blockSize >= (1 << 10)) | 837 | if (numPasses > 1 && blockSize >= (1 << 10)) |
646 | { | 838 | { |
647 | UInt32 blockSize0 = blockSize / 2; // ???? | 839 | UInt32 bs0 = blockSize / 2; |
648 | 840 | for (; bs0 < blockSize && | |
649 | for (; (block[blockSize0] == block[(size_t)blockSize0 - 1] | 841 | (block[ bs0 ] == |
650 | || block[(size_t)blockSize0 - 1] == block[(size_t)blockSize0 - 2]) | 842 | block[(size_t)bs0 - 1] || |
651 | && blockSize0 < blockSize; | 843 | block[(size_t)bs0 - 1] == |
652 | blockSize0++); | 844 | block[(size_t)bs0 - 2]); |
845 | bs0++) | ||
846 | {} | ||
653 | 847 | ||
654 | if (blockSize0 < blockSize) | 848 | if (bs0 < blockSize) |
655 | { | 849 | { |
656 | EncodeBlock2(block, blockSize0, numPasses - 1); | 850 | EncodeBlock2(block, bs0, numPasses - 1); |
657 | EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1); | 851 | EncodeBlock2(block + bs0, blockSize - bs0, numPasses - 1); |
658 | endPos = m_OutStreamCurrent->GetPos(); | 852 | endPos = m_OutStreamCurrent.GetPos(); |
659 | endCurByte = m_OutStreamCurrent->GetCurByte(); | 853 | endCurByte = m_OutStreamCurrent.GetCurByte(); |
660 | if ((endPos & 7) > 0) | 854 | // we prepare next byte as identical byte to starting byte for main encoding attempt: |
855 | if (endPos & 7) | ||
661 | WriteBits2(0, 8 - (endPos & 7)); | 856 | WriteBits2(0, 8 - (endPos & 7)); |
662 | m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); | 857 | m_OutStreamCurrent.SetCurState((startPos & 7), startCurByte); |
663 | needCompare = true; | ||
664 | } | 858 | } |
665 | } | 859 | } |
666 | 860 | ||
667 | UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos(); | 861 | const UInt32 startBytePos2 = m_OutStreamCurrent.GetBytePos(); |
668 | UInt32 startPos2 = m_OutStreamCurrent->GetPos(); | 862 | const UInt32 startPos2 = m_OutStreamCurrent.GetPos(); |
669 | UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize); | 863 | const UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize); |
670 | UInt32 endPos2 = m_OutStreamCurrent->GetPos(); | ||
671 | 864 | ||
672 | if (needCompare) | 865 | if (endPos) |
673 | { | 866 | { |
674 | UInt32 size2 = endPos2 - startPos2; | 867 | const UInt32 size2 = m_OutStreamCurrent.GetPos() - startPos2; |
675 | if (size2 < endPos - startPos) | 868 | if (size2 >= endPos - startPos) |
676 | { | ||
677 | UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2; | ||
678 | Byte *buffer = m_OutStreamCurrent->GetStream(); | ||
679 | for (UInt32 i = 0; i < numBytes; i++) | ||
680 | buffer[startBytePos + i] = buffer[startBytePos2 + i]; | ||
681 | m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2); | ||
682 | m_NumCrcs = numCrcs; | ||
683 | m_CRCs[m_NumCrcs++] = crcVal; | ||
684 | } | ||
685 | else | ||
686 | { | 869 | { |
687 | m_OutStreamCurrent->SetPos(endPos); | 870 | m_OutStreamCurrent.SetPos(endPos); |
688 | m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte); | 871 | m_OutStreamCurrent.SetCurState((endPos & 7), endCurByte); |
872 | return; | ||
689 | } | 873 | } |
874 | const UInt32 numBytes = m_OutStreamCurrent.GetBytePos() - startBytePos2; | ||
875 | Byte * const buffer = m_OutStreamCurrent.GetStream(); | ||
876 | memmove(buffer + startBytePos, buffer + startBytePos2, numBytes); | ||
877 | m_OutStreamCurrent.SetPos(startPos + size2); | ||
878 | // we don't call m_OutStreamCurrent.SetCurState() here because | ||
879 | // m_OutStreamCurrent._curByte is correct already | ||
690 | } | 880 | } |
691 | else | 881 | m_CRCs[numCrcs] = crcVal; |
692 | { | 882 | m_NumCrcs = numCrcs + 1; |
693 | m_NumCrcs = numCrcs; | ||
694 | m_CRCs[m_NumCrcs++] = crcVal; | ||
695 | } | ||
696 | } | 883 | } |
697 | 884 | ||
885 | |||
698 | HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) | 886 | HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) |
699 | { | 887 | { |
700 | CMsbfEncoderTemp outStreamTemp; | 888 | CMsbfEncoderTemp &outStreamTemp = m_OutStreamCurrent; |
701 | outStreamTemp.SetStream(m_TempArray); | 889 | outStreamTemp.SetStream(m_TempArray); |
702 | outStreamTemp.Init(); | 890 | outStreamTemp.Init(); |
703 | m_OutStreamCurrent = &outStreamTemp; | ||
704 | |||
705 | m_NumCrcs = 0; | 891 | m_NumCrcs = 0; |
706 | 892 | ||
707 | EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses); | 893 | EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses); |
708 | 894 | ||
709 | #ifndef Z7_ST | 895 | #ifndef Z7_ST |
710 | if (Encoder->MtMode) | 896 | if (Encoder->MtMode) |
711 | Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock(); | 897 | Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock(); |
712 | #endif | 898 | #endif |
899 | |||
713 | for (UInt32 i = 0; i < m_NumCrcs; i++) | 900 | for (UInt32 i = 0; i < m_NumCrcs; i++) |
714 | Encoder->CombinedCrc.Update(m_CRCs[i]); | 901 | Encoder->CombinedCrc.Update(m_CRCs[i]); |
715 | Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte()); | 902 | Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetNonFlushedByteBits()); |
716 | HRESULT res = S_OK; | 903 | HRESULT res = S_OK; |
717 | #ifndef Z7_ST | 904 | |
905 | #ifndef Z7_ST | ||
718 | if (Encoder->MtMode) | 906 | if (Encoder->MtMode) |
719 | { | 907 | { |
720 | UInt32 blockIndex = m_BlockIndex + 1; | 908 | UInt32 blockIndex = m_BlockIndex + 1; |
721 | if (blockIndex == Encoder->NumThreads) | 909 | if (blockIndex == Encoder->NumThreads) |
722 | blockIndex = 0; | 910 | blockIndex = 0; |
723 | |||
724 | if (Encoder->Progress) | 911 | if (Encoder->Progress) |
725 | { | 912 | { |
726 | const UInt64 packSize = Encoder->m_OutStream.GetProcessedSize(); | 913 | const UInt64 packSize = Encoder->m_OutStream.GetProcessedSize(); |
727 | res = Encoder->Progress->SetRatioInfo(&m_UnpackSize, &packSize); | 914 | res = Encoder->Progress->SetRatioInfo(&m_UnpackSize, &packSize); |
728 | } | 915 | } |
729 | |||
730 | Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); | 916 | Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); |
731 | } | 917 | } |
732 | #endif | 918 | #endif |
733 | return res; | 919 | return res; |
734 | } | 920 | } |
735 | 921 | ||
736 | void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte) | 922 | void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByteBits) |
737 | { | 923 | { |
738 | UInt32 bytesSize = (sizeInBits >> 3); | 924 | m_OutStream.WriteBytes(data, sizeInBits >> 3); |
739 | for (UInt32 i = 0; i < bytesSize; i++) | 925 | sizeInBits &= 7; |
740 | m_OutStream.WriteBits(data[i], 8); | 926 | if (sizeInBits) |
741 | WriteBits(lastByte, (sizeInBits & 7)); | 927 | m_OutStream.WriteBits(lastByteBits, sizeInBits); |
742 | } | 928 | } |
743 | 929 | ||
744 | 930 | ||
@@ -746,11 +932,12 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * | |||
746 | const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) | 932 | const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) |
747 | { | 933 | { |
748 | NumBlocks = 0; | 934 | NumBlocks = 0; |
749 | #ifndef Z7_ST | 935 | #ifndef Z7_ST |
750 | Progress = progress; | 936 | Progress = progress; |
937 | ThreadNextGroup_Init(&ThreadNextGroup, _props.NumThreadGroups, 0); // startGroup | ||
751 | RINOK(Create()) | 938 | RINOK(Create()) |
752 | for (UInt32 t = 0; t < NumThreads; t++) | 939 | for (UInt32 t = 0; t < NumThreads; t++) |
753 | #endif | 940 | #endif |
754 | { | 941 | { |
755 | #ifndef Z7_ST | 942 | #ifndef Z7_ST |
756 | CThreadInfo &ti = ThreadsInfo[t]; | 943 | CThreadInfo &ti = ThreadsInfo[t]; |
@@ -823,11 +1010,11 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * | |||
823 | { | 1010 | { |
824 | CThreadInfo &ti = | 1011 | CThreadInfo &ti = |
825 | #ifndef Z7_ST | 1012 | #ifndef Z7_ST |
826 | ThreadsInfo[0]; | 1013 | ThreadsInfo[0]; |
827 | #else | 1014 | #else |
828 | ThreadsInfo; | 1015 | ThreadsInfo; |
829 | #endif | 1016 | #endif |
830 | UInt32 blockSize = ReadRleBlock(ti.m_Block); | 1017 | const UInt32 blockSize = ReadRleBlock(ti.m_Block); |
831 | if (blockSize == 0) | 1018 | if (blockSize == 0) |
832 | break; | 1019 | break; |
833 | RINOK(ti.EncodeBlock3(blockSize)) | 1020 | RINOK(ti.EncodeBlock3(blockSize)) |
@@ -845,8 +1032,11 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * | |||
845 | WriteByte(kFinSig3); | 1032 | WriteByte(kFinSig3); |
846 | WriteByte(kFinSig4); | 1033 | WriteByte(kFinSig4); |
847 | WriteByte(kFinSig5); | 1034 | WriteByte(kFinSig5); |
848 | 1035 | { | |
849 | WriteCrc(CombinedCrc.GetDigest()); | 1036 | const UInt32 v = CombinedCrc.GetDigest(); |
1037 | for (int i = 24; i >= 0; i -= 8) | ||
1038 | WriteByte((Byte)(v >> i)); | ||
1039 | } | ||
850 | RINOK(Flush()) | 1040 | RINOK(Flush()) |
851 | if (!m_InStream.WasFinished()) | 1041 | if (!m_InStream.WasFinished()) |
852 | return E_FAIL; | 1042 | return E_FAIL; |
@@ -869,14 +1059,21 @@ Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA | |||
869 | for (UInt32 i = 0; i < numProps; i++) | 1059 | for (UInt32 i = 0; i < numProps; i++) |
870 | { | 1060 | { |
871 | const PROPVARIANT &prop = coderProps[i]; | 1061 | const PROPVARIANT &prop = coderProps[i]; |
872 | PROPID propID = propIDs[i]; | 1062 | const PROPID propID = propIDs[i]; |
873 | 1063 | ||
874 | if (propID == NCoderPropID::kAffinity) | 1064 | if (propID == NCoderPropID::kAffinity) |
875 | { | 1065 | { |
876 | if (prop.vt == VT_UI8) | 1066 | if (prop.vt != VT_UI8) |
877 | props.Affinity = prop.uhVal.QuadPart; | 1067 | return E_INVALIDARG; |
878 | else | 1068 | props.Affinity = prop.uhVal.QuadPart; |
1069 | continue; | ||
1070 | } | ||
1071 | |||
1072 | if (propID == NCoderPropID::kNumThreadGroups) | ||
1073 | { | ||
1074 | if (prop.vt != VT_UI4) | ||
879 | return E_INVALIDARG; | 1075 | return E_INVALIDARG; |
1076 | props.NumThreadGroups = (UInt32)prop.ulVal; | ||
880 | continue; | 1077 | continue; |
881 | } | 1078 | } |
882 | 1079 | ||
@@ -884,7 +1081,7 @@ Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA | |||
884 | continue; | 1081 | continue; |
885 | if (prop.vt != VT_UI4) | 1082 | if (prop.vt != VT_UI4) |
886 | return E_INVALIDARG; | 1083 | return E_INVALIDARG; |
887 | UInt32 v = (UInt32)prop.ulVal; | 1084 | const UInt32 v = (UInt32)prop.ulVal; |
888 | switch (propID) | 1085 | switch (propID) |
889 | { | 1086 | { |
890 | case NCoderPropID::kNumPasses: props.NumPasses = v; break; | 1087 | case NCoderPropID::kNumPasses: props.NumPasses = v; break; |
diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index 4a04fbd..bcb4025 100644 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h | |||
@@ -3,7 +3,6 @@ | |||
3 | #ifndef ZIP7_INC_COMPRESS_BZIP2_ENCODER_H | 3 | #ifndef ZIP7_INC_COMPRESS_BZIP2_ENCODER_H |
4 | #define ZIP7_INC_COMPRESS_BZIP2_ENCODER_H | 4 | #define ZIP7_INC_COMPRESS_BZIP2_ENCODER_H |
5 | 5 | ||
6 | #include "../../Common/Defs.h" | ||
7 | #include "../../Common/MyCom.h" | 6 | #include "../../Common/MyCom.h" |
8 | 7 | ||
9 | #ifndef Z7_ST | 8 | #ifndef Z7_ST |
@@ -23,80 +22,114 @@ | |||
23 | namespace NCompress { | 22 | namespace NCompress { |
24 | namespace NBZip2 { | 23 | namespace NBZip2 { |
25 | 24 | ||
26 | class CMsbfEncoderTemp | 25 | const unsigned kNumPassesMax = 10; |
26 | |||
27 | struct CMsbfEncoderTemp | ||
27 | { | 28 | { |
28 | UInt32 _pos; | 29 | unsigned _bitPos; // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte |
29 | unsigned _bitPos; | 30 | unsigned _curByte; // low (_bitPos) bits are zeros |
30 | Byte _curByte; | 31 | // high (8 - _bitPos) bits are filled |
31 | Byte *_buf; | 32 | Byte *_buf; |
32 | public: | 33 | Byte *_buf_base; |
33 | void SetStream(Byte *buf) { _buf = buf; } | 34 | void SetStream(Byte *buf) { _buf_base = _buf = buf; } |
34 | Byte *GetStream() const { return _buf; } | 35 | Byte *GetStream() const { return _buf_base; } |
35 | 36 | ||
36 | void Init() | 37 | void Init() |
37 | { | 38 | { |
38 | _pos = 0; | ||
39 | _bitPos = 8; | 39 | _bitPos = 8; |
40 | _curByte = 0; | 40 | _curByte = 0; |
41 | _buf = _buf_base; | ||
41 | } | 42 | } |
42 | 43 | ||
43 | void Flush() | 44 | // required condition: (value >> numBits) == 0 |
44 | { | 45 | // numBits == 0 is allowed |
45 | if (_bitPos < 8) | ||
46 | WriteBits(0, _bitPos); | ||
47 | } | ||
48 | |||
49 | void WriteBits(UInt32 value, unsigned numBits) | 46 | void WriteBits(UInt32 value, unsigned numBits) |
50 | { | 47 | { |
51 | while (numBits > 0) | 48 | do |
52 | { | 49 | { |
53 | unsigned numNewBits = MyMin(numBits, _bitPos); | 50 | unsigned bp = _bitPos; |
54 | numBits -= numNewBits; | 51 | unsigned curByte = _curByte; |
55 | 52 | if (numBits < bp) | |
56 | _curByte = (Byte)(_curByte << numNewBits); | ||
57 | UInt32 newBits = value >> numBits; | ||
58 | _curByte |= Byte(newBits); | ||
59 | value -= (newBits << numBits); | ||
60 | |||
61 | _bitPos -= numNewBits; | ||
62 | |||
63 | if (_bitPos == 0) | ||
64 | { | 53 | { |
65 | _buf[_pos++] = _curByte; | 54 | bp -= numBits; |
66 | _bitPos = 8; | 55 | _curByte = curByte | (value << bp); |
56 | _bitPos = bp; | ||
57 | return; | ||
67 | } | 58 | } |
59 | numBits -= bp; | ||
60 | const UInt32 hi = value >> numBits; | ||
61 | value -= (hi << numBits); | ||
62 | Byte *buf = _buf; | ||
63 | _bitPos = 8; | ||
64 | _curByte = 0; | ||
65 | *buf++ = (Byte)(curByte | hi); | ||
66 | _buf = buf; | ||
68 | } | 67 | } |
68 | while (numBits); | ||
69 | } | 69 | } |
70 | 70 | ||
71 | UInt32 GetBytePos() const { return _pos ; } | 71 | void WriteBit(unsigned value) |
72 | UInt32 GetPos() const { return _pos * 8 + (8 - _bitPos); } | 72 | { |
73 | Byte GetCurByte() const { return _curByte; } | 73 | const unsigned bp = _bitPos - 1; |
74 | const unsigned curByte = _curByte | (value << bp); | ||
75 | _curByte = curByte; | ||
76 | _bitPos = bp; | ||
77 | if (bp == 0) | ||
78 | { | ||
79 | *_buf++ = (Byte)curByte; | ||
80 | _curByte = 0; | ||
81 | _bitPos = 8; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void WriteByte(unsigned b) | ||
86 | { | ||
87 | const unsigned bp = _bitPos; | ||
88 | const unsigned a = _curByte | (b >> (8 - bp)); | ||
89 | _curByte = b << bp; | ||
90 | Byte *buf = _buf; | ||
91 | *buf++ = (Byte)a; | ||
92 | _buf = buf; | ||
93 | } | ||
94 | |||
95 | UInt32 GetBytePos() const { return (UInt32)(size_t)(_buf - _buf_base); } | ||
96 | UInt32 GetPos() const { return GetBytePos() * 8 + 8 - _bitPos; } | ||
97 | unsigned GetCurByte() const { return _curByte; } | ||
98 | unsigned GetNonFlushedByteBits() const { return _curByte >> _bitPos; } | ||
74 | void SetPos(UInt32 bitPos) | 99 | void SetPos(UInt32 bitPos) |
75 | { | 100 | { |
76 | _pos = bitPos >> 3; | 101 | _buf = _buf_base + (bitPos >> 3); |
77 | _bitPos = 8 - ((unsigned)bitPos & 7); | 102 | _bitPos = 8 - ((unsigned)bitPos & 7); |
78 | } | 103 | } |
79 | void SetCurState(unsigned bitPos, Byte curByte) | 104 | void SetCurState(unsigned bitPos, unsigned curByte) |
80 | { | 105 | { |
81 | _bitPos = 8 - bitPos; | 106 | _bitPos = 8 - bitPos; |
82 | _curByte = curByte; | 107 | _curByte = curByte; |
83 | } | 108 | } |
84 | }; | 109 | }; |
85 | 110 | ||
86 | class CEncoder; | ||
87 | 111 | ||
88 | const unsigned kNumPassesMax = 10; | 112 | class CEncoder; |
89 | 113 | ||
90 | class CThreadInfo | 114 | class CThreadInfo |
91 | { | 115 | { |
116 | private: | ||
117 | CMsbfEncoderTemp m_OutStreamCurrent; | ||
92 | public: | 118 | public: |
119 | CEncoder *Encoder; | ||
93 | Byte *m_Block; | 120 | Byte *m_Block; |
94 | private: | 121 | private: |
95 | Byte *m_MtfArray; | 122 | Byte *m_MtfArray; |
96 | Byte *m_TempArray; | 123 | Byte *m_TempArray; |
97 | UInt32 *m_BlockSorterIndex; | 124 | UInt32 *m_BlockSorterIndex; |
98 | 125 | ||
99 | CMsbfEncoderTemp *m_OutStreamCurrent; | 126 | public: |
127 | bool m_OptimizeNumTables; | ||
128 | UInt32 m_NumCrcs; | ||
129 | UInt32 m_BlockIndex; | ||
130 | UInt64 m_UnpackSize; | ||
131 | |||
132 | Byte *m_Block_Base; | ||
100 | 133 | ||
101 | Byte Lens[kNumTablesMax][kMaxAlphaSize]; | 134 | Byte Lens[kNumTablesMax][kMaxAlphaSize]; |
102 | UInt32 Freqs[kNumTablesMax][kMaxAlphaSize]; | 135 | UInt32 Freqs[kNumTablesMax][kMaxAlphaSize]; |
@@ -105,20 +138,16 @@ private: | |||
105 | Byte m_Selectors[kNumSelectorsMax]; | 138 | Byte m_Selectors[kNumSelectorsMax]; |
106 | 139 | ||
107 | UInt32 m_CRCs[1 << kNumPassesMax]; | 140 | UInt32 m_CRCs[1 << kNumPassesMax]; |
108 | UInt32 m_NumCrcs; | ||
109 | 141 | ||
110 | void WriteBits2(UInt32 value, unsigned numBits); | 142 | void WriteBits2(UInt32 value, unsigned numBits); |
111 | void WriteByte2(Byte b); | 143 | void WriteByte2(unsigned b) { WriteBits2(b, 8); } |
112 | void WriteBit2(Byte v); | 144 | void WriteBit2(unsigned v) { m_OutStreamCurrent.WriteBit(v); } |
113 | void WriteCrc2(UInt32 v); | ||
114 | 145 | ||
115 | void EncodeBlock(const Byte *block, UInt32 blockSize); | 146 | void EncodeBlock(const Byte *block, UInt32 blockSize); |
116 | UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); | 147 | UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); |
117 | void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); | 148 | void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); |
118 | public: | 149 | public: |
119 | bool m_OptimizeNumTables; | 150 | #ifndef Z7_ST |
120 | CEncoder *Encoder; | ||
121 | #ifndef Z7_ST | ||
122 | NWindows::CThread Thread; | 151 | NWindows::CThread Thread; |
123 | 152 | ||
124 | NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; | 153 | NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; |
@@ -127,17 +156,14 @@ public: | |||
127 | // it's not member of this thread. We just need one event per thread | 156 | // it's not member of this thread. We just need one event per thread |
128 | NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; | 157 | NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; |
129 | 158 | ||
130 | private: | ||
131 | UInt32 m_BlockIndex; | ||
132 | UInt64 m_UnpackSize; | ||
133 | public: | 159 | public: |
134 | Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. | 160 | Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. |
135 | HRESULT Create(); | 161 | HRESULT Create(); |
136 | void FinishStream(bool needLeave); | 162 | void FinishStream(bool needLeave); |
137 | THREAD_FUNC_RET_TYPE ThreadFunc(); | 163 | THREAD_FUNC_RET_TYPE ThreadFunc(); |
138 | #endif | 164 | #endif |
139 | 165 | ||
140 | CThreadInfo(): m_Block(NULL), m_BlockSorterIndex(NULL) {} | 166 | CThreadInfo(): m_BlockSorterIndex(NULL), m_Block_Base(NULL) {} |
141 | ~CThreadInfo() { Free(); } | 167 | ~CThreadInfo() { Free(); } |
142 | bool Alloc(); | 168 | bool Alloc(); |
143 | void Free(); | 169 | void Free(); |
@@ -145,16 +171,19 @@ public: | |||
145 | HRESULT EncodeBlock3(UInt32 blockSize); | 171 | HRESULT EncodeBlock3(UInt32 blockSize); |
146 | }; | 172 | }; |
147 | 173 | ||
174 | |||
148 | struct CEncProps | 175 | struct CEncProps |
149 | { | 176 | { |
150 | UInt32 BlockSizeMult; | 177 | UInt32 BlockSizeMult; |
151 | UInt32 NumPasses; | 178 | UInt32 NumPasses; |
179 | UInt32 NumThreadGroups; | ||
152 | UInt64 Affinity; | 180 | UInt64 Affinity; |
153 | 181 | ||
154 | CEncProps() | 182 | CEncProps() |
155 | { | 183 | { |
156 | BlockSizeMult = (UInt32)(Int32)-1; | 184 | BlockSizeMult = (UInt32)(Int32)-1; |
157 | NumPasses = (UInt32)(Int32)-1; | 185 | NumPasses = (UInt32)(Int32)-1; |
186 | NumThreadGroups = 0; | ||
158 | Affinity = 0; | 187 | Affinity = 0; |
159 | } | 188 | } |
160 | void Normalize(int level); | 189 | void Normalize(int level); |
@@ -206,6 +235,7 @@ public: | |||
206 | bool CloseThreads; | 235 | bool CloseThreads; |
207 | bool StreamWasFinished; | 236 | bool StreamWasFinished; |
208 | NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; | 237 | NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; |
238 | CThreadNextGroup ThreadNextGroup; | ||
209 | 239 | ||
210 | HRESULT Result; | 240 | HRESULT Result; |
211 | ICompressProgressInfo *Progress; | 241 | ICompressProgressInfo *Progress; |
@@ -218,12 +248,8 @@ public: | |||
218 | UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); } | 248 | UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); } |
219 | 249 | ||
220 | UInt32 ReadRleBlock(Byte *buf); | 250 | UInt32 ReadRleBlock(Byte *buf); |
221 | void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); | 251 | void WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByteBits); |
222 | |||
223 | void WriteBits(UInt32 value, unsigned numBits); | ||
224 | void WriteByte(Byte b); | 252 | void WriteByte(Byte b); |
225 | // void WriteBit(Byte v); | ||
226 | void WriteCrc(UInt32 v); | ||
227 | 253 | ||
228 | #ifndef Z7_ST | 254 | #ifndef Z7_ST |
229 | HRESULT Create(); | 255 | HRESULT Create(); |
diff --git a/CPP/7zip/Compress/BitlEncoder.h b/CPP/7zip/Compress/BitlEncoder.h index 67b1428..364f84d 100644 --- a/CPP/7zip/Compress/BitlEncoder.h +++ b/CPP/7zip/Compress/BitlEncoder.h | |||
@@ -33,6 +33,7 @@ public: | |||
33 | _bitPos = 8; | 33 | _bitPos = 8; |
34 | _curByte = 0; | 34 | _curByte = 0; |
35 | } | 35 | } |
36 | Z7_FORCE_INLINE | ||
36 | void WriteBits(UInt32 value, unsigned numBits) | 37 | void WriteBits(UInt32 value, unsigned numBits) |
37 | { | 38 | { |
38 | while (numBits > 0) | 39 | while (numBits > 0) |
diff --git a/CPP/7zip/Compress/BitmEncoder.h b/CPP/7zip/Compress/BitmEncoder.h index 978ee1c..f7448cd 100644 --- a/CPP/7zip/Compress/BitmEncoder.h +++ b/CPP/7zip/Compress/BitmEncoder.h | |||
@@ -8,8 +8,9 @@ | |||
8 | template<class TOutByte> | 8 | template<class TOutByte> |
9 | class CBitmEncoder | 9 | class CBitmEncoder |
10 | { | 10 | { |
11 | unsigned _bitPos; | 11 | unsigned _bitPos; // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte |
12 | Byte _curByte; | 12 | unsigned _curByte; // low (_bitPos) bits are zeros |
13 | // high (8 - _bitPos) bits are filled | ||
13 | TOutByte _stream; | 14 | TOutByte _stream; |
14 | public: | 15 | public: |
15 | bool Create(UInt32 bufferSize) { return _stream.Create(bufferSize); } | 16 | bool Create(UInt32 bufferSize) { return _stream.Create(bufferSize); } |
@@ -24,25 +25,65 @@ public: | |||
24 | HRESULT Flush() | 25 | HRESULT Flush() |
25 | { | 26 | { |
26 | if (_bitPos < 8) | 27 | if (_bitPos < 8) |
27 | WriteBits(0, _bitPos); | 28 | { |
29 | _stream.WriteByte((Byte)_curByte); | ||
30 | _bitPos = 8; | ||
31 | _curByte = 0; | ||
32 | } | ||
28 | return _stream.Flush(); | 33 | return _stream.Flush(); |
29 | } | 34 | } |
35 | |||
36 | // required condition: (value >> numBits) == 0 | ||
37 | // numBits == 0 is allowed | ||
30 | void WriteBits(UInt32 value, unsigned numBits) | 38 | void WriteBits(UInt32 value, unsigned numBits) |
31 | { | 39 | { |
32 | while (numBits > 0) | 40 | do |
33 | { | 41 | { |
34 | if (numBits < _bitPos) | 42 | unsigned bp = _bitPos; |
43 | unsigned curByte = _curByte; | ||
44 | if (numBits < bp) | ||
35 | { | 45 | { |
36 | _curByte = (Byte)(_curByte | (value << (_bitPos -= numBits))); | 46 | bp -= numBits; |
47 | _curByte = curByte | (value << bp); | ||
48 | _bitPos = bp; | ||
37 | return; | 49 | return; |
38 | } | 50 | } |
39 | numBits -= _bitPos; | 51 | numBits -= bp; |
40 | UInt32 newBits = (value >> numBits); | 52 | const UInt32 hi = (value >> numBits); |
41 | value -= (newBits << numBits); | 53 | value -= (hi << numBits); |
42 | _stream.WriteByte((Byte)(_curByte | newBits)); | 54 | _stream.WriteByte((Byte)(curByte | hi)); |
43 | _bitPos = 8; | 55 | _bitPos = 8; |
44 | _curByte = 0; | 56 | _curByte = 0; |
45 | } | 57 | } |
58 | while (numBits); | ||
59 | } | ||
60 | void WriteByte(unsigned b) | ||
61 | { | ||
62 | const unsigned bp = _bitPos; | ||
63 | const unsigned a = _curByte | (b >> (8 - bp)); | ||
64 | _curByte = b << bp; | ||
65 | _stream.WriteByte((Byte)a); | ||
66 | } | ||
67 | |||
68 | void WriteBytes(const Byte *data, size_t num) | ||
69 | { | ||
70 | const unsigned bp = _bitPos; | ||
71 | #if 1 // 1 for optional speed-optimized code branch | ||
72 | if (bp == 8) | ||
73 | { | ||
74 | _stream.WriteBytes(data, num); | ||
75 | return; | ||
76 | } | ||
77 | #endif | ||
78 | unsigned c = _curByte; | ||
79 | const unsigned bp_rev = 8 - bp; | ||
80 | for (size_t i = 0; i < num; i++) | ||
81 | { | ||
82 | const unsigned b = data[i]; | ||
83 | _stream.WriteByte((Byte)(c | (b >> bp_rev))); | ||
84 | c = b << bp; | ||
85 | } | ||
86 | _curByte = c; | ||
46 | } | 87 | } |
47 | }; | 88 | }; |
48 | 89 | ||
diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index 73895fe..7993176 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp | |||
@@ -117,15 +117,13 @@ bool CCoder::ReadTables(void) | |||
117 | if (_numDistLevels > kDistTableSize32) | 117 | if (_numDistLevels > kDistTableSize32) |
118 | return false; | 118 | return false; |
119 | 119 | ||
120 | Byte levelLevels[kLevelTableSize]; | 120 | const unsigned kLevelTableSize_aligned4 = kLevelTableSize + 1; |
121 | for (unsigned i = 0; i < kLevelTableSize; i++) | 121 | Byte levelLevels[kLevelTableSize_aligned4]; |
122 | { | 122 | memset (levelLevels, 0, sizeof(levelLevels)); |
123 | const unsigned position = kCodeLengthAlphabetOrder[i]; | 123 | unsigned i = 0; |
124 | if (i < numLevelCodes) | 124 | do |
125 | levelLevels[position] = (Byte)ReadBits(kLevelFieldSize); | 125 | levelLevels[kCodeLengthAlphabetOrder[i++]] = (Byte)ReadBits(kLevelFieldSize); |
126 | else | 126 | while (i != numLevelCodes); |
127 | levelLevels[position] = 0; | ||
128 | } | ||
129 | 127 | ||
130 | if (m_InBitStream.ExtraBitsWereRead()) | 128 | if (m_InBitStream.ExtraBitsWereRead()) |
131 | return false; | 129 | return false; |
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 87b4f83..afc5f12 100644 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp | |||
@@ -19,12 +19,16 @@ | |||
19 | #define NO_INLINE | 19 | #define NO_INLINE |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define MAX_HUF_LEN_12 12 | ||
23 | |||
22 | namespace NCompress { | 24 | namespace NCompress { |
23 | namespace NDeflate { | 25 | namespace NDeflate { |
24 | namespace NEncoder { | 26 | namespace NEncoder { |
25 | 27 | ||
28 | static const unsigned k_CodeValue_Len_Is_Literal_Flag = 1u << 15; | ||
29 | |||
26 | static const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. | 30 | static const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. |
27 | static const UInt32 kNumTables = (1 << kNumDivPassesMax); | 31 | static const unsigned kNumTables = 1u << kNumDivPassesMax; |
28 | 32 | ||
29 | static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. | 33 | static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. |
30 | static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. | 34 | static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. |
@@ -77,7 +81,7 @@ public: | |||
77 | 81 | ||
78 | static CFastPosInit g_FastPosInit; | 82 | static CFastPosInit g_FastPosInit; |
79 | 83 | ||
80 | inline UInt32 GetPosSlot(UInt32 pos) | 84 | inline unsigned GetPosSlot(UInt32 pos) |
81 | { | 85 | { |
82 | /* | 86 | /* |
83 | if (pos < 0x200) | 87 | if (pos < 0x200) |
@@ -162,13 +166,13 @@ HRESULT CCoder::Create() | |||
162 | // COM_TRY_BEGIN | 166 | // COM_TRY_BEGIN |
163 | if (!m_Values) | 167 | if (!m_Values) |
164 | { | 168 | { |
165 | m_Values = (CCodeValue *)MyAlloc((kMaxUncompressedBlockSize) * sizeof(CCodeValue)); | 169 | m_Values = (CCodeValue *)MyAlloc(kMaxUncompressedBlockSize * sizeof(CCodeValue)); |
166 | if (!m_Values) | 170 | if (!m_Values) |
167 | return E_OUTOFMEMORY; | 171 | return E_OUTOFMEMORY; |
168 | } | 172 | } |
169 | if (!m_Tables) | 173 | if (!m_Tables) |
170 | { | 174 | { |
171 | m_Tables = (CTables *)MyAlloc((kNumTables) * sizeof(CTables)); | 175 | m_Tables = (CTables *)MyAlloc(kNumTables * sizeof(CTables)); |
172 | if (!m_Tables) | 176 | if (!m_Tables) |
173 | return E_OUTOFMEMORY; | 177 | return E_OUTOFMEMORY; |
174 | } | 178 | } |
@@ -268,19 +272,21 @@ NO_INLINE void CCoder::GetMatches() | |||
268 | 272 | ||
269 | UInt32 distanceTmp[kMatchMaxLen * 2 + 3]; | 273 | UInt32 distanceTmp[kMatchMaxLen * 2 + 3]; |
270 | 274 | ||
271 | const UInt32 numPairs = (UInt32)((_btMode ? | 275 | const size_t numPairs = (size_t)((_btMode ? |
272 | Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp): | 276 | Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp): |
273 | Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp)) - distanceTmp); | 277 | Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp)) - distanceTmp); |
274 | 278 | ||
275 | *m_MatchDistances = (UInt16)numPairs; | 279 | UInt16 *matchDistances = m_MatchDistances; |
280 | *matchDistances++ = (UInt16)numPairs; | ||
276 | 281 | ||
277 | if (numPairs != 0) | 282 | if (numPairs != 0) |
278 | { | 283 | { |
279 | UInt32 i; | 284 | size_t i; |
280 | for (i = 0; i < numPairs; i += 2) | 285 | for (i = 0; i < numPairs; i += 2) |
281 | { | 286 | { |
282 | m_MatchDistances[(size_t)i + 1] = (UInt16)distanceTmp[i]; | 287 | matchDistances[0] = (UInt16)distanceTmp[i]; |
283 | m_MatchDistances[(size_t)i + 2] = (UInt16)distanceTmp[(size_t)i + 1]; | 288 | matchDistances[1] = (UInt16)distanceTmp[(size_t)i + 1]; |
289 | matchDistances += 2; | ||
284 | } | 290 | } |
285 | UInt32 len = distanceTmp[(size_t)numPairs - 2]; | 291 | UInt32 len = distanceTmp[(size_t)numPairs - 2]; |
286 | if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen) | 292 | if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen) |
@@ -291,11 +297,11 @@ NO_INLINE void CCoder::GetMatches() | |||
291 | if (numAvail > m_MatchMaxLen) | 297 | if (numAvail > m_MatchMaxLen) |
292 | numAvail = m_MatchMaxLen; | 298 | numAvail = m_MatchMaxLen; |
293 | for (; len < numAvail && pby[len] == pby2[len]; len++); | 299 | for (; len < numAvail && pby[len] == pby2[len]; len++); |
294 | m_MatchDistances[(size_t)i - 1] = (UInt16)len; | 300 | matchDistances[-2] = (UInt16)len; |
295 | } | 301 | } |
296 | } | 302 | } |
297 | if (m_IsMultiPass) | 303 | if (m_IsMultiPass) |
298 | m_Pos += numPairs + 1; | 304 | m_Pos += (UInt32)numPairs + 1; |
299 | if (!m_SecondPass) | 305 | if (!m_SecondPass) |
300 | m_AdditionalOffset++; | 306 | m_AdditionalOffset++; |
301 | } | 307 | } |
@@ -535,6 +541,7 @@ NO_INLINE void CCoder::WriteBits(UInt32 value, unsigned numBits) | |||
535 | } | 541 | } |
536 | 542 | ||
537 | #define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i]) | 543 | #define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i]) |
544 | #define WRITE_HF2_NO_INLINE(codes, lens, i) WriteBits(codes[i], lens[i]) | ||
538 | #define WRITE_HF(i) WriteBits(codes[i], lens[i]) | 545 | #define WRITE_HF(i) WriteBits(codes[i], lens[i]) |
539 | 546 | ||
540 | NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes) | 547 | NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes) |
@@ -619,17 +626,22 @@ static NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, | |||
619 | return price; | 626 | return price; |
620 | } | 627 | } |
621 | 628 | ||
622 | static NO_INLINE UInt32 Huffman_GetPrice_Spec(const UInt32 *freqs, const Byte *lens, UInt32 num, const Byte *extraBits, UInt32 extraBase) | 629 | static NO_INLINE UInt32 Huffman_GetPrice_Spec( |
630 | const UInt32 *freqs, const Byte *lens, UInt32 num, | ||
631 | const Byte *extraBits, UInt32 extraBase) | ||
623 | { | 632 | { |
624 | return Huffman_GetPrice(freqs, lens, num) + | 633 | return |
634 | Huffman_GetPrice(freqs, lens, num) + | ||
625 | Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase); | 635 | Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase); |
626 | } | 636 | } |
627 | 637 | ||
628 | NO_INLINE UInt32 CCoder::GetLzBlockPrice() const | 638 | NO_INLINE UInt32 CCoder::GetLzBlockPrice() const |
629 | { | 639 | { |
630 | return | 640 | return |
631 | Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) + | 641 | Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels, |
632 | Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, kDistTableSize64, kDistDirectBits, 0); | 642 | kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) + |
643 | Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels, | ||
644 | kDistTableSize64, kDistDirectBits, 0); | ||
633 | } | 645 | } |
634 | 646 | ||
635 | NO_INLINE void CCoder::TryBlock() | 647 | NO_INLINE void CCoder::TryBlock() |
@@ -658,7 +670,7 @@ NO_INLINE void CCoder::TryBlock() | |||
658 | CCodeValue &codeValue = m_Values[m_ValueIndex++]; | 670 | CCodeValue &codeValue = m_Values[m_ValueIndex++]; |
659 | if (len >= kMatchMinLen) | 671 | if (len >= kMatchMinLen) |
660 | { | 672 | { |
661 | UInt32 newLen = len - kMatchMinLen; | 673 | const UInt32 newLen = len - kMatchMinLen; |
662 | codeValue.Len = (UInt16)newLen; | 674 | codeValue.Len = (UInt16)newLen; |
663 | mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++; | 675 | mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++; |
664 | codeValue.Pos = (UInt16)pos; | 676 | codeValue.Pos = (UInt16)pos; |
@@ -666,10 +678,10 @@ NO_INLINE void CCoder::TryBlock() | |||
666 | } | 678 | } |
667 | else | 679 | else |
668 | { | 680 | { |
669 | Byte b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset); | 681 | const unsigned b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset); |
670 | mainFreqs[b]++; | 682 | mainFreqs[b]++; |
671 | codeValue.SetAsLiteral(); | 683 | codeValue.Len = k_CodeValue_Len_Is_Literal_Flag; |
672 | codeValue.Pos = b; | 684 | codeValue.Pos = (UInt16)b; |
673 | } | 685 | } |
674 | m_AdditionalOffset -= len; | 686 | m_AdditionalOffset -= len; |
675 | BlockSizeRes += len; | 687 | BlockSizeRes += len; |
@@ -704,16 +716,24 @@ NO_INLINE void CCoder::SetPrices(const CLevels &levels) | |||
704 | } | 716 | } |
705 | } | 717 | } |
706 | 718 | ||
719 | #if MAX_HUF_LEN_12 > 12 | ||
720 | // Huffman_ReverseBits() now supports 12-bits values only. | ||
721 | #error Stop_Compiling_Bad_MAX_HUF_LEN_12 | ||
722 | #endif | ||
707 | static NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num) | 723 | static NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num) |
708 | { | 724 | { |
709 | for (UInt32 i = 0; i < num; i++) | 725 | const Byte * const lens_lim = lens + num; |
726 | do | ||
710 | { | 727 | { |
711 | UInt32 x = codes[i]; | 728 | // we should change constants, if lens[*] can be larger than 12. |
712 | x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1); | 729 | UInt32 x = *codes; |
713 | x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2); | 730 | x = ((x & (0x555 )) << 2) + (x & (0xAAA )); |
714 | x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4); | 731 | x = ((x & (0x333 << 1)) << 4) | (x & (0xCCC << 1)); |
715 | codes[i] = (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - lens[i]); | 732 | x = ((x & (0xF0F << 3)) << 8) | (x & (0x0F0 << 3)); |
733 | // we can use (x) instead of (x & (0xFF << 7)), if we support garabage data after (*lens) bits. | ||
734 | *codes++ = (((x & (0xFF << 7)) << 16) | x) >> (*lens ^ 31); | ||
716 | } | 735 | } |
736 | while (++lens != lens_lim); | ||
717 | } | 737 | } |
718 | 738 | ||
719 | NO_INLINE void CCoder::WriteBlock() | 739 | NO_INLINE void CCoder::WriteBlock() |
@@ -721,24 +741,28 @@ NO_INLINE void CCoder::WriteBlock() | |||
721 | Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize); | 741 | Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize); |
722 | Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64); | 742 | Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64); |
723 | 743 | ||
724 | for (UInt32 i = 0; i < m_ValueIndex; i++) | 744 | CCodeValue *values = m_Values; |
745 | const CCodeValue * const values_lim = values + m_ValueIndex; | ||
746 | |||
747 | if (values != values_lim) | ||
748 | do | ||
725 | { | 749 | { |
726 | const CCodeValue &codeValue = m_Values[i]; | 750 | const UInt32 len = values->Len; |
727 | if (codeValue.IsLiteral()) | 751 | const UInt32 dist = values->Pos; |
728 | WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, codeValue.Pos); | 752 | if (len == k_CodeValue_Len_Is_Literal_Flag) |
753 | WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, dist); | ||
729 | else | 754 | else |
730 | { | 755 | { |
731 | UInt32 len = codeValue.Len; | 756 | const unsigned lenSlot = g_LenSlots[len]; |
732 | UInt32 lenSlot = g_LenSlots[len]; | ||
733 | WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot); | 757 | WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot); |
734 | m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]); | 758 | m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]); |
735 | UInt32 dist = codeValue.Pos; | 759 | const unsigned posSlot = GetPosSlot(dist); |
736 | UInt32 posSlot = GetPosSlot(dist); | ||
737 | WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot); | 760 | WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot); |
738 | m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]); | 761 | m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]); |
739 | } | 762 | } |
740 | } | 763 | } |
741 | WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock); | 764 | while (++values != values_lim); |
765 | WRITE_HF2_NO_INLINE(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock); | ||
742 | } | 766 | } |
743 | 767 | ||
744 | static UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition) | 768 | static UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition) |
@@ -787,10 +811,10 @@ NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses) | |||
787 | { | 811 | { |
788 | m_Pos = posTemp; | 812 | m_Pos = posTemp; |
789 | TryBlock(); | 813 | TryBlock(); |
790 | unsigned numHuffBits = | 814 | const unsigned numHuffBits = |
791 | (m_ValueIndex > 18000 ? 12 : | 815 | m_ValueIndex > 18000 ? MAX_HUF_LEN_12 : |
792 | (m_ValueIndex > 7000 ? 11 : | 816 | m_ValueIndex > 7000 ? 11 : |
793 | (m_ValueIndex > 2000 ? 10 : 9))); | 817 | m_ValueIndex > 2000 ? 10 : 9; |
794 | MakeTables(numHuffBits); | 818 | MakeTables(numHuffBits); |
795 | SetPrices(m_NewLevels); | 819 | SetPrices(m_NewLevels); |
796 | } | 820 | } |
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp index 0dc7e23..ffe1152 100644 --- a/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp | |||
@@ -52,7 +52,15 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm | |||
52 | case NCoderPropID::kNumThreads: | 52 | case NCoderPropID::kNumThreads: |
53 | if (prop.vt != VT_UI4) | 53 | if (prop.vt != VT_UI4) |
54 | return E_INVALIDARG; | 54 | return E_INVALIDARG; |
55 | lzma2Props.numTotalThreads = (int)(prop.ulVal); | 55 | lzma2Props.numTotalThreads = (int)prop.ulVal; |
56 | break; | ||
57 | case NCoderPropID::kNumThreadGroups: | ||
58 | if (prop.vt != VT_UI4) | ||
59 | return E_INVALIDARG; | ||
60 | // 16-bit value supported by Windows | ||
61 | if (prop.ulVal >= (1u << 16)) | ||
62 | return E_INVALIDARG; | ||
63 | lzma2Props.numThreadGroups = (unsigned)prop.ulVal; | ||
56 | break; | 64 | break; |
57 | default: | 65 | default: |
58 | RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)) | 66 | RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)) |
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 08e3ba5..bca2eee 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp | |||
@@ -101,6 +101,24 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) | |||
101 | return S_OK; | 101 | return S_OK; |
102 | } | 102 | } |
103 | 103 | ||
104 | if (propID == NCoderPropID::kAffinityInGroup) | ||
105 | { | ||
106 | if (prop.vt == VT_UI8) | ||
107 | ep.affinityInGroup = prop.uhVal.QuadPart; | ||
108 | else | ||
109 | return E_INVALIDARG; | ||
110 | return S_OK; | ||
111 | } | ||
112 | |||
113 | if (propID == NCoderPropID::kThreadGroup) | ||
114 | { | ||
115 | if (prop.vt == VT_UI4) | ||
116 | ep.affinityGroup = (Int32)(UInt32)prop.ulVal; | ||
117 | else | ||
118 | return E_INVALIDARG; | ||
119 | return S_OK; | ||
120 | } | ||
121 | |||
104 | if (propID == NCoderPropID::kHashBits) | 122 | if (propID == NCoderPropID::kHashBits) |
105 | { | 123 | { |
106 | if (prop.vt == VT_UI4) | 124 | if (prop.vt == VT_UI4) |
diff --git a/CPP/7zip/Compress/Mtf8.h b/CPP/7zip/Compress/Mtf8.h index 1b44d00..5fce30e 100644 --- a/CPP/7zip/Compress/Mtf8.h +++ b/CPP/7zip/Compress/Mtf8.h | |||
@@ -13,6 +13,18 @@ struct CMtf8Encoder | |||
13 | 13 | ||
14 | unsigned FindAndMove(Byte v) throw() | 14 | unsigned FindAndMove(Byte v) throw() |
15 | { | 15 | { |
16 | #if 1 | ||
17 | Byte b = Buf[0]; | ||
18 | if (v == b) | ||
19 | return 0; | ||
20 | Buf[0] = v; | ||
21 | for (unsigned pos = 0;;) | ||
22 | { | ||
23 | Byte a; | ||
24 | a = Buf[++pos]; Buf[pos] = b; if (v == a) return pos; | ||
25 | b = Buf[++pos]; Buf[pos] = a; if (v == b) return pos; | ||
26 | } | ||
27 | #else | ||
16 | size_t pos; | 28 | size_t pos; |
17 | for (pos = 0; Buf[pos] != v; pos++); | 29 | for (pos = 0; Buf[pos] != v; pos++); |
18 | const unsigned resPos = (unsigned)pos; | 30 | const unsigned resPos = (unsigned)pos; |
@@ -31,6 +43,7 @@ struct CMtf8Encoder | |||
31 | Buf[pos] = Buf[pos - 1]; | 43 | Buf[pos] = Buf[pos - 1]; |
32 | Buf[0] = v; | 44 | Buf[0] = v; |
33 | return resPos; | 45 | return resPos; |
46 | #endif | ||
34 | } | 47 | } |
35 | }; | 48 | }; |
36 | 49 | ||
diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp index 8be24e2..7279b5a 100644 --- a/CPP/7zip/Compress/Rar5Decoder.cpp +++ b/CPP/7zip/Compress/Rar5Decoder.cpp | |||
@@ -936,31 +936,30 @@ HRESULT CDecoder::ExecuteFilter(const CFilter &f) | |||
936 | HRESULT CDecoder::WriteBuf() | 936 | HRESULT CDecoder::WriteBuf() |
937 | { | 937 | { |
938 | DeleteUnusedFilters(); | 938 | DeleteUnusedFilters(); |
939 | |||
940 | const UInt64 lzSize = _lzSize + _winPos; | 939 | const UInt64 lzSize = _lzSize + _winPos; |
941 | 940 | ||
942 | for (unsigned i = 0; i < _numFilters;) | 941 | for (unsigned i = 0; i < _numFilters;) |
943 | { | 942 | { |
944 | const CFilter &f = _filters[i]; | ||
945 | const UInt64 blockStart = f.Start; | ||
946 | const size_t lzAvail = (size_t)(lzSize - _lzWritten); | 943 | const size_t lzAvail = (size_t)(lzSize - _lzWritten); |
947 | if (lzAvail == 0) | 944 | if (lzAvail == 0) |
948 | break; | 945 | break; |
949 | 946 | // (lzAvail != 0) | |
947 | const CFilter &f = _filters[i]; | ||
948 | const UInt64 blockStart = f.Start; | ||
950 | if (blockStart > _lzWritten) | 949 | if (blockStart > _lzWritten) |
951 | { | 950 | { |
952 | const UInt64 rem = blockStart - _lzWritten; | 951 | const UInt64 rem = blockStart - _lzWritten; |
952 | // (rem != 0) | ||
953 | size_t size = lzAvail; | 953 | size_t size = lzAvail; |
954 | if (size > rem) | 954 | if (size > rem) |
955 | size = (size_t)rem; | 955 | size = (size_t)rem; |
956 | if (size != 0) // is it true always ? | 956 | // (size != 0) |
957 | { | 957 | RINOK(WriteData(_window + _winPos - lzAvail, size)) |
958 | RINOK(WriteData(_window + _winPos - lzAvail, size)) | 958 | _lzWritten += size; |
959 | _lzWritten += size; | ||
960 | } | ||
961 | continue; | 959 | continue; |
962 | } | 960 | } |
963 | 961 | ||
962 | // (blockStart <= _lzWritten) | ||
964 | const UInt32 blockSize = f.Size; | 963 | const UInt32 blockSize = f.Size; |
965 | size_t offset = (size_t)(_lzWritten - blockStart); | 964 | size_t offset = (size_t)(_lzWritten - blockStart); |
966 | if (offset == 0) | 965 | if (offset == 0) |
@@ -987,10 +986,8 @@ HRESULT CDecoder::WriteBuf() | |||
987 | } | 986 | } |
988 | 987 | ||
989 | DeleteUnusedFilters(); | 988 | DeleteUnusedFilters(); |
990 | |||
991 | if (_numFilters) | 989 | if (_numFilters) |
992 | return S_OK; | 990 | return S_OK; |
993 | |||
994 | const size_t lzAvail = (size_t)(lzSize - _lzWritten); | 991 | const size_t lzAvail = (size_t)(lzSize - _lzWritten); |
995 | RINOK(WriteData(_window + _winPos - lzAvail, lzAvail)) | 992 | RINOK(WriteData(_window + _winPos - lzAvail, lzAvail)) |
996 | _lzWritten += lzAvail; | 993 | _lzWritten += lzAvail; |
@@ -1367,6 +1364,12 @@ enum enum_exit_type | |||
1367 | Z7_HUFF_DECODE_CHECK(sym, huf, kNumHufBits, kNumTableBits, bitStream, { LZ_LOOP_BREAK_ERROR }) | 1364 | Z7_HUFF_DECODE_CHECK(sym, huf, kNumHufBits, kNumTableBits, bitStream, { LZ_LOOP_BREAK_ERROR }) |
1368 | 1365 | ||
1369 | 1366 | ||
1367 | /* | ||
1368 | DecodeLZ2() will stop decoding if it reaches limit when (_winPos >= _limit) | ||
1369 | at return: | ||
1370 | (_winPos < _limit + kMaxMatchLen) | ||
1371 | also it can write up to (COPY_CHUNK_SIZE - 1) additional junk bytes after (_winPos). | ||
1372 | */ | ||
1370 | HRESULT CDecoder::DecodeLZ2(const CBitDecoder &bitStream) throw() | 1373 | HRESULT CDecoder::DecodeLZ2(const CBitDecoder &bitStream) throw() |
1371 | { | 1374 | { |
1372 | #if 0 | 1375 | #if 0 |
@@ -1656,6 +1659,13 @@ decode_error: | |||
1656 | 1659 | ||
1657 | 1660 | ||
1658 | 1661 | ||
1662 | /* | ||
1663 | input conditions: | ||
1664 | _winPos < _winSize | ||
1665 | return: | ||
1666 | _winPos < _winSize is expected, if (return_res == S_OK) | ||
1667 | _winPos >= _winSize is possible in (return_res != S_OK) | ||
1668 | */ | ||
1659 | HRESULT CDecoder::DecodeLZ() | 1669 | HRESULT CDecoder::DecodeLZ() |
1660 | { | 1670 | { |
1661 | CBitDecoder _bitStream; | 1671 | CBitDecoder _bitStream; |
@@ -1679,6 +1689,8 @@ HRESULT CDecoder::DecodeLZ() | |||
1679 | if (winPos >= limit) | 1689 | if (winPos >= limit) |
1680 | { | 1690 | { |
1681 | _winPos = winPos < _winSize ? winPos : _winSize; | 1691 | _winPos = winPos < _winSize ? winPos : _winSize; |
1692 | // _winPos == min(winPos, _winSize) | ||
1693 | // we will not write data after _winSize | ||
1682 | RINOK(WriteBuf()) | 1694 | RINOK(WriteBuf()) |
1683 | if (_unpackSize_Defined && _writtenFileSize > _unpackSize) | 1695 | if (_unpackSize_Defined && _writtenFileSize > _unpackSize) |
1684 | break; // return S_FALSE; | 1696 | break; // return S_FALSE; |
@@ -1854,7 +1866,15 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream | |||
1854 | { | 1866 | { |
1855 | // if (_winPos > 100) _winPos -= 100; // for debug: corruption | 1867 | // if (_winPos > 100) _winPos -= 100; // for debug: corruption |
1856 | const UInt64 lzSize = _lzSize + _winPos; | 1868 | const UInt64 lzSize = _lzSize + _winPos; |
1857 | if (!_isSolid || !_wasInit | 1869 | /* |
1870 | if previous file was decoded with error or for some another cases, then | ||
1871 | (lzSize > _lzEnd) is possible | ||
1872 | (_winPos > _winSize) is possible | ||
1873 | (_winPos < _winSize + kMaxMatchLen) | ||
1874 | */ | ||
1875 | if (!_window | ||
1876 | || !_isSolid | ||
1877 | || !_wasInit | ||
1858 | || (lzSize < _lzEnd | 1878 | || (lzSize < _lzEnd |
1859 | #if Z7_RAR_RECOVER_SOLID_LIMIT != 0 | 1879 | #if Z7_RAR_RECOVER_SOLID_LIMIT != 0 |
1860 | && lzSize + Z7_RAR_RECOVER_SOLID_LIMIT < _lzEnd | 1880 | && lzSize + Z7_RAR_RECOVER_SOLID_LIMIT < _lzEnd |
@@ -1863,9 +1883,9 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream | |||
1863 | { | 1883 | { |
1864 | if (_isSolid) | 1884 | if (_isSolid) |
1865 | _lzError = LZ_ERROR_TYPE_HEADER; | 1885 | _lzError = LZ_ERROR_TYPE_HEADER; |
1866 | _lzEnd = 0; | ||
1867 | _lzSize = 0; | 1886 | _lzSize = 0; |
1868 | _lzWritten = 0; | 1887 | // _lzEnd = 0; // it will be set later |
1888 | // _lzWritten = 0; // it will be set later | ||
1869 | _winPos = 0; | 1889 | _winPos = 0; |
1870 | for (unsigned i = 0; i < kNumReps; i++) | 1890 | for (unsigned i = 0; i < kNumReps; i++) |
1871 | _reps[i] = (size_t)0 - 1; | 1891 | _reps[i] = (size_t)0 - 1; |
@@ -1873,51 +1893,67 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream | |||
1873 | _tableWasFilled = false; | 1893 | _tableWasFilled = false; |
1874 | _wasInit = true; | 1894 | _wasInit = true; |
1875 | } | 1895 | } |
1876 | #if Z7_RAR_RECOVER_SOLID_LIMIT != 0 | 1896 | else |
1877 | else if (lzSize < _lzEnd) | ||
1878 | { | 1897 | { |
1898 | const size_t ws = _winSize; | ||
1899 | if (_winPos >= ws) | ||
1900 | { | ||
1901 | // we must normalize (_winPos) and data in _window, | ||
1902 | _winPos -= ws; | ||
1903 | _lzSize += ws; | ||
1904 | // (_winPos < kMaxMatchLen < _winSize) | ||
1905 | // if (_window) | ||
1906 | memcpy(_window, _window + ws, _winPos); // memmove is not required here | ||
1907 | } | ||
1908 | |||
1909 | #if Z7_RAR_RECOVER_SOLID_LIMIT != 0 | ||
1910 | if (lzSize < _lzEnd) | ||
1911 | { | ||
1879 | #if 0 | 1912 | #if 0 |
1880 | return S_FALSE; | 1913 | return S_FALSE; |
1881 | #else | 1914 | #else |
1882 | // we can report that recovering was made: | 1915 | // we can report that recovering was made: |
1883 | // _lzError = LZ_ERROR_TYPE_HEADER; | 1916 | // _lzError = LZ_ERROR_TYPE_HEADER; |
1884 | // We write zeros to area after corruption: | 1917 | // We write zeros to area after corruption: |
1885 | if (_window) | 1918 | // if (_window) |
1886 | { | ||
1887 | UInt64 rem = _lzEnd - lzSize; | ||
1888 | const size_t ws = _winSize; | ||
1889 | if (rem >= ws) | ||
1890 | { | 1919 | { |
1891 | My_ZeroMemory(_window, ws); | 1920 | UInt64 rem = _lzEnd - lzSize; |
1892 | _lzSize = ws; | 1921 | if (rem >= ws) |
1893 | _winPos = 0; | ||
1894 | } | ||
1895 | else | ||
1896 | { | ||
1897 | const size_t cur = ws - _winPos; | ||
1898 | if (cur <= rem) | ||
1899 | { | 1922 | { |
1900 | rem -= cur; | 1923 | My_ZeroMemory(_window, ws); |
1901 | My_ZeroMemory(_window + _winPos, cur); | 1924 | _lzSize = ws; |
1902 | _lzSize += _winPos; | ||
1903 | _winPos = 0; | 1925 | _winPos = 0; |
1904 | } | 1926 | } |
1905 | My_ZeroMemory(_window + _winPos, (size_t)rem); | 1927 | else |
1906 | _winPos += (size_t)rem; | 1928 | { |
1929 | // rem < _winSize | ||
1930 | // _winPos <= ws | ||
1931 | const size_t cur = ws - _winPos; | ||
1932 | if (cur <= rem) | ||
1933 | { | ||
1934 | rem -= cur; | ||
1935 | My_ZeroMemory(_window + _winPos, cur); | ||
1936 | _lzSize = ws; | ||
1937 | _winPos = 0; | ||
1938 | } | ||
1939 | My_ZeroMemory(_window + _winPos, (size_t)rem); | ||
1940 | _winPos += (size_t)rem; | ||
1941 | } | ||
1907 | } | 1942 | } |
1908 | } | 1943 | // else return S_FALSE; |
1909 | // else return S_FALSE; | ||
1910 | #endif | 1944 | #endif |
1945 | } | ||
1911 | } | 1946 | } |
1912 | #endif | 1947 | #endif |
1913 | } | 1948 | } |
1914 | 1949 | ||
1950 | // _winPos < _winSize | ||
1915 | // we don't want _lzSize overflow | 1951 | // we don't want _lzSize overflow |
1916 | if (_lzSize >= DICT_SIZE_MAX) | 1952 | if (_lzSize >= DICT_SIZE_MAX) |
1917 | _lzSize = DICT_SIZE_MAX; | 1953 | _lzSize = DICT_SIZE_MAX; |
1918 | _lzEnd = _lzSize + _winPos; | 1954 | _lzEnd = _lzSize + _winPos; |
1919 | // _lzSize <= DICT_SIZE_MAX | 1955 | // _lzSize <= DICT_SIZE_MAX |
1920 | // _lzEnd <= DICT_SIZE_MAX * 2 | 1956 | // _lzEnd < DICT_SIZE_MAX + _winSize |
1921 | 1957 | ||
1922 | size_t newSize = _dictSize; | 1958 | size_t newSize = _dictSize; |
1923 | if (newSize < kWinSize_Min) | 1959 | if (newSize < kWinSize_Min) |
@@ -1941,10 +1977,11 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream | |||
1941 | // If dictionary was increased in solid, we don't want grow. | 1977 | // If dictionary was increased in solid, we don't want grow. |
1942 | return S_FALSE; // E_OUTOFMEMORY | 1978 | return S_FALSE; // E_OUTOFMEMORY |
1943 | } | 1979 | } |
1944 | // (newSize <= _winSize) | 1980 | // (newSize <= _dictSize_forCheck) |
1945 | } | 1981 | } |
1946 | else | 1982 | else |
1947 | { | 1983 | { |
1984 | // !_isSolid || !_window | ||
1948 | _dictSize_forCheck = newSize; | 1985 | _dictSize_forCheck = newSize; |
1949 | { | 1986 | { |
1950 | size_t newSize_small = newSize; | 1987 | size_t newSize_small = newSize; |
@@ -1964,7 +2001,7 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream | |||
1964 | if (!_window || allocSize > _winSize_Allocated) | 2001 | if (!_window || allocSize > _winSize_Allocated) |
1965 | { | 2002 | { |
1966 | Z7_RAR_FREE_WINDOW | 2003 | Z7_RAR_FREE_WINDOW |
1967 | _window = NULL; | 2004 | _window = NULL; |
1968 | _winSize_Allocated = 0; | 2005 | _winSize_Allocated = 0; |
1969 | Byte *win = (Byte *)::BigAlloc(allocSize); | 2006 | Byte *win = (Byte *)::BigAlloc(allocSize); |
1970 | if (!win) | 2007 | if (!win) |
diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp index f84bca8..0ae0e16 100644 --- a/CPP/7zip/Crypto/MyAes.cpp +++ b/CPP/7zip/Crypto/MyAes.cpp | |||
@@ -153,7 +153,26 @@ Z7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size)) | |||
153 | #ifndef Z7_EXTRACT_ONLY | 153 | #ifndef Z7_EXTRACT_ONLY |
154 | 154 | ||
155 | #ifdef MY_CPU_X86_OR_AMD64 | 155 | #ifdef MY_CPU_X86_OR_AMD64 |
156 | #define USE_HW_AES | 156 | |
157 | #if defined(__INTEL_COMPILER) | ||
158 | #if (__INTEL_COMPILER >= 1110) | ||
159 | #define USE_HW_AES | ||
160 | #if (__INTEL_COMPILER >= 1900) | ||
161 | #define USE_HW_VAES | ||
162 | #endif | ||
163 | #endif | ||
164 | #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \ | ||
165 | || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) | ||
166 | #define USE_HW_AES | ||
167 | #if defined(__clang__) && (__clang_major__ >= 8) \ | ||
168 | || defined(__GNUC__) && (__GNUC__ >= 8) | ||
169 | #define USE_HW_VAES | ||
170 | #endif | ||
171 | #elif defined(_MSC_VER) | ||
172 | #define USE_HW_AES | ||
173 | #define USE_HW_VAES | ||
174 | #endif | ||
175 | |||
157 | #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) | 176 | #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) |
158 | 177 | ||
159 | #if defined(__ARM_FEATURE_AES) \ | 178 | #if defined(__ARM_FEATURE_AES) \ |
@@ -186,15 +205,15 @@ Z7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size)) | |||
186 | #define SET_AES_FUNC_2(f2) \ | 205 | #define SET_AES_FUNC_2(f2) \ |
187 | if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \ | 206 | if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \ |
188 | { f = f2; } | 207 | { f = f2; } |
189 | #ifdef MY_CPU_X86_OR_AMD64 | 208 | #ifdef USE_HW_VAES |
190 | #define SET_AES_FUNC_23(f2, f3) \ | 209 | #define SET_AES_FUNC_23(f2, f3) \ |
191 | SET_AES_FUNC_2(f2) \ | 210 | SET_AES_FUNC_2(f2) \ |
192 | if (algo == 3) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) \ | 211 | if (algo == 3) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) \ |
193 | { f = f3; } | 212 | { f = f3; } |
194 | #else // MY_CPU_X86_OR_AMD64 | 213 | #else // USE_HW_VAES |
195 | #define SET_AES_FUNC_23(f2, f3) \ | 214 | #define SET_AES_FUNC_23(f2, f3) \ |
196 | SET_AES_FUNC_2(f2) | 215 | SET_AES_FUNC_2(f2) |
197 | #endif // MY_CPU_X86_OR_AMD64 | 216 | #endif // USE_HW_VAES |
198 | #else // USE_HW_AES | 217 | #else // USE_HW_AES |
199 | #define SET_AES_FUNC_23(f2, f3) | 218 | #define SET_AES_FUNC_23(f2, f3) |
200 | #endif // USE_HW_AES | 219 | #endif // USE_HW_AES |
diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp index 26c6100..34ea4ff 100644 --- a/CPP/7zip/Crypto/Rar5Aes.cpp +++ b/CPP/7zip/Crypto/Rar5Aes.cpp | |||
@@ -8,16 +8,17 @@ | |||
8 | #include "../../Windows/Synchronization.h" | 8 | #include "../../Windows/Synchronization.h" |
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | #include "Rar5Aes.h" | ||
12 | #include "HmacSha256.h" | 11 | #include "HmacSha256.h" |
12 | #include "Rar5Aes.h" | ||
13 | |||
14 | #define MY_ALIGN_FOR_SHA256 MY_ALIGN(16) | ||
13 | 15 | ||
14 | namespace NCrypto { | 16 | namespace NCrypto { |
15 | namespace NRar5 { | 17 | namespace NRar5 { |
16 | 18 | ||
17 | static const unsigned kNumIterationsLog_Max = 24; | 19 | static const unsigned kNumIterationsLog_Max = 24; |
18 | 20 | static const unsigned kPswCheckCsumSize32 = 1; | |
19 | static const unsigned kPswCheckCsumSize = 4; | 21 | static const unsigned kCheckSize32 = kPswCheckSize32 + kPswCheckCsumSize32; |
20 | static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize; | ||
21 | 22 | ||
22 | CKey::CKey(): | 23 | CKey::CKey(): |
23 | _needCalc(true), | 24 | _needCalc(true), |
@@ -27,15 +28,29 @@ CKey::CKey(): | |||
27 | _salt[i] = 0; | 28 | _salt[i] = 0; |
28 | } | 29 | } |
29 | 30 | ||
31 | CKey::~CKey() | ||
32 | { | ||
33 | Wipe(); | ||
34 | } | ||
35 | |||
36 | void CKey::Wipe() | ||
37 | { | ||
38 | _password.Wipe(); | ||
39 | Z7_memset_0_ARRAY(_salt); | ||
40 | // Z7_memset_0_ARRAY(_key32); | ||
41 | // Z7_memset_0_ARRAY(_check_Calced32); | ||
42 | // Z7_memset_0_ARRAY(_hashKey32); | ||
43 | CKeyBase::Wipe(); | ||
44 | } | ||
45 | |||
30 | CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {} | 46 | CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {} |
31 | 47 | ||
32 | static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val) | 48 | static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val) |
33 | { | 49 | { |
34 | *val = 0; | 50 | *val = 0; |
35 | |||
36 | for (unsigned i = 0; i < maxSize && i < 10;) | 51 | for (unsigned i = 0; i < maxSize && i < 10;) |
37 | { | 52 | { |
38 | Byte b = p[i]; | 53 | const Byte b = p[i]; |
39 | *val |= (UInt64)(b & 0x7F) << (7 * i); | 54 | *val |= (UInt64)(b & 0x7F) << (7 * i); |
40 | i++; | 55 | i++; |
41 | if ((b & 0x80) == 0) | 56 | if ((b & 0x80) == 0) |
@@ -64,7 +79,7 @@ HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, | |||
64 | size -= num; | 79 | size -= num; |
65 | 80 | ||
66 | bool isCheck = IsThereCheck(); | 81 | bool isCheck = IsThereCheck(); |
67 | if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0)) | 82 | if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize32 * 4 : 0)) |
68 | return E_NOTIMPL; | 83 | return E_NOTIMPL; |
69 | 84 | ||
70 | if (_numIterationsLog != p[0]) | 85 | if (_numIterationsLog != p[0]) |
@@ -93,19 +108,21 @@ HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, | |||
93 | 108 | ||
94 | if (isCheck) | 109 | if (isCheck) |
95 | { | 110 | { |
96 | memcpy(_check, p, kPswCheckSize); | 111 | memcpy(_check32, p, sizeof(_check32)); |
112 | MY_ALIGN_FOR_SHA256 | ||
97 | CSha256 sha; | 113 | CSha256 sha; |
114 | MY_ALIGN_FOR_SHA256 | ||
98 | Byte digest[SHA256_DIGEST_SIZE]; | 115 | Byte digest[SHA256_DIGEST_SIZE]; |
99 | Sha256_Init(&sha); | 116 | Sha256_Init(&sha); |
100 | Sha256_Update(&sha, _check, kPswCheckSize); | 117 | Sha256_Update(&sha, (const Byte *)_check32, sizeof(_check32)); |
101 | Sha256_Final(&sha, digest); | 118 | Sha256_Final(&sha, digest); |
102 | _canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0); | 119 | _canCheck = (memcmp(digest, p + sizeof(_check32), kPswCheckCsumSize32 * 4) == 0); |
103 | if (_canCheck && isService) | 120 | if (_canCheck && isService) |
104 | { | 121 | { |
105 | // There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros. | 122 | // There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros. |
106 | // so we disable password checking for such bad records. | 123 | // so we disable password checking for such bad records. |
107 | _canCheck = false; | 124 | _canCheck = false; |
108 | for (unsigned i = 0; i < kPswCheckSize; i++) | 125 | for (unsigned i = 0; i < kPswCheckSize32 * 4; i++) |
109 | if (p[i] != 0) | 126 | if (p[i] != 0) |
110 | { | 127 | { |
111 | _canCheck = true; | 128 | _canCheck = true; |
@@ -132,7 +149,7 @@ void CDecoder::SetPassword(const Byte *data, size_t size) | |||
132 | Z7_COM7F_IMF(CDecoder::Init()) | 149 | Z7_COM7F_IMF(CDecoder::Init()) |
133 | { | 150 | { |
134 | CalcKey_and_CheckPassword(); | 151 | CalcKey_and_CheckPassword(); |
135 | RINOK(SetKey(_key, kAesKeySize)) | 152 | RINOK(SetKey((const Byte *)_key32, kAesKeySize)) |
136 | RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)) | 153 | RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)) |
137 | return CAesCoder::Init(); | 154 | return CAesCoder::Init(); |
138 | } | 155 | } |
@@ -140,27 +157,27 @@ Z7_COM7F_IMF(CDecoder::Init()) | |||
140 | 157 | ||
141 | UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const | 158 | UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const |
142 | { | 159 | { |
143 | MY_ALIGN (16) | 160 | MY_ALIGN_FOR_SHA256 |
144 | NSha256::CHmac ctx; | 161 | NSha256::CHmac ctx; |
145 | ctx.SetKey(_hashKey, NSha256::kDigestSize); | 162 | ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize); |
146 | UInt32 v; | 163 | UInt32 v; |
147 | SetUi32(&v, crc) | 164 | SetUi32a(&v, crc) |
148 | ctx.Update((const Byte *)&v, 4); | 165 | ctx.Update((const Byte *)&v, 4); |
149 | MY_ALIGN (16) | 166 | MY_ALIGN_FOR_SHA256 |
150 | UInt32 h[SHA256_NUM_DIGEST_WORDS]; | 167 | UInt32 h[SHA256_NUM_DIGEST_WORDS]; |
151 | ctx.Final((Byte *)h); | 168 | ctx.Final((Byte *)h); |
152 | crc = 0; | 169 | crc = 0; |
153 | for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++) | 170 | for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++) |
154 | crc ^= (UInt32)GetUi32(h + i); | 171 | crc ^= (UInt32)GetUi32a(h + i); |
155 | return crc; | 172 | return crc; |
156 | } | 173 | } |
157 | 174 | ||
158 | 175 | ||
159 | void CDecoder::Hmac_Convert_32Bytes(Byte *data) const | 176 | void CDecoder::Hmac_Convert_32Bytes(Byte *data) const |
160 | { | 177 | { |
161 | MY_ALIGN (16) | 178 | MY_ALIGN_FOR_SHA256 |
162 | NSha256::CHmac ctx; | 179 | NSha256::CHmac ctx; |
163 | ctx.SetKey(_hashKey, NSha256::kDigestSize); | 180 | ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize); |
164 | ctx.Update(data, NSha256::kDigestSize); | 181 | ctx.Update(data, NSha256::kDigestSize); |
165 | ctx.Final(data); | 182 | ctx.Final(data); |
166 | } | 183 | } |
@@ -190,30 +207,31 @@ bool CDecoder::CalcKey_and_CheckPassword() | |||
190 | 207 | ||
191 | if (_needCalc) | 208 | if (_needCalc) |
192 | { | 209 | { |
193 | Byte pswCheck[SHA256_DIGEST_SIZE]; | 210 | MY_ALIGN_FOR_SHA256 |
194 | 211 | UInt32 pswCheck[SHA256_NUM_DIGEST_WORDS]; | |
195 | { | 212 | { |
196 | // Pbkdf HMAC-SHA-256 | 213 | // Pbkdf HMAC-SHA-256 |
197 | 214 | MY_ALIGN_FOR_SHA256 | |
198 | MY_ALIGN (16) | ||
199 | NSha256::CHmac baseCtx; | 215 | NSha256::CHmac baseCtx; |
200 | baseCtx.SetKey(_password, _password.Size()); | 216 | baseCtx.SetKey(_password, _password.Size()); |
201 | 217 | MY_ALIGN_FOR_SHA256 | |
202 | NSha256::CHmac ctx = baseCtx; | 218 | NSha256::CHmac ctx; |
219 | ctx = baseCtx; | ||
203 | ctx.Update(_salt, sizeof(_salt)); | 220 | ctx.Update(_salt, sizeof(_salt)); |
204 | 221 | ||
205 | MY_ALIGN (16) | 222 | MY_ALIGN_FOR_SHA256 |
206 | Byte u[NSha256::kDigestSize]; | 223 | UInt32 u[SHA256_NUM_DIGEST_WORDS]; |
207 | MY_ALIGN (16) | 224 | MY_ALIGN_FOR_SHA256 |
208 | Byte key[NSha256::kDigestSize]; | 225 | UInt32 key[SHA256_NUM_DIGEST_WORDS]; |
209 | 226 | ||
210 | u[0] = 0; | 227 | // u[0] = 0; |
211 | u[1] = 0; | 228 | // u[1] = 0; |
212 | u[2] = 0; | 229 | // u[2] = 0; |
213 | u[3] = 1; | 230 | // u[3] = 1; |
231 | SetUi32a(u, 0x1000000) | ||
214 | 232 | ||
215 | ctx.Update(u, 4); | 233 | ctx.Update((const Byte *)(const void *)u, 4); |
216 | ctx.Final(u); | 234 | ctx.Final((Byte *)(void *)u); |
217 | 235 | ||
218 | memcpy(key, u, NSha256::kDigestSize); | 236 | memcpy(key, u, NSha256::kDigestSize); |
219 | 237 | ||
@@ -221,35 +239,24 @@ bool CDecoder::CalcKey_and_CheckPassword() | |||
221 | 239 | ||
222 | for (unsigned i = 0; i < 3; i++) | 240 | for (unsigned i = 0; i < 3; i++) |
223 | { | 241 | { |
224 | UInt32 j = numIterations; | 242 | for (; numIterations != 0; numIterations--) |
225 | |||
226 | for (; j != 0; j--) | ||
227 | { | 243 | { |
228 | ctx = baseCtx; | 244 | ctx = baseCtx; |
229 | ctx.Update(u, NSha256::kDigestSize); | 245 | ctx.Update((const Byte *)(const void *)u, NSha256::kDigestSize); |
230 | ctx.Final(u); | 246 | ctx.Final((Byte *)(void *)u); |
231 | for (unsigned s = 0; s < NSha256::kDigestSize; s++) | 247 | for (unsigned s = 0; s < Z7_ARRAY_SIZE(u); s++) |
232 | key[s] ^= u[s]; | 248 | key[s] ^= u[s]; |
233 | } | 249 | } |
234 | 250 | ||
235 | // RAR uses additional iterations for additional keys | 251 | // RAR uses additional iterations for additional keys |
236 | memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize); | 252 | memcpy(i == 0 ? _key32 : i == 1 ? _hashKey32 : pswCheck, |
253 | key, NSha256::kDigestSize); | ||
237 | numIterations = 16; | 254 | numIterations = 16; |
238 | } | 255 | } |
239 | } | 256 | } |
240 | 257 | _check_Calced32[0] = pswCheck[0] ^ pswCheck[2] ^ pswCheck[4] ^ pswCheck[6]; | |
241 | { | 258 | _check_Calced32[1] = pswCheck[1] ^ pswCheck[3] ^ pswCheck[5] ^ pswCheck[7]; |
242 | unsigned i; | ||
243 | |||
244 | for (i = 0; i < kPswCheckSize; i++) | ||
245 | _check_Calced[i] = pswCheck[i]; | ||
246 | |||
247 | for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++) | ||
248 | _check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i]; | ||
249 | } | ||
250 | |||
251 | _needCalc = false; | 259 | _needCalc = false; |
252 | |||
253 | { | 260 | { |
254 | MT_LOCK | 261 | MT_LOCK |
255 | g_Key = *this; | 262 | g_Key = *this; |
@@ -258,7 +265,7 @@ bool CDecoder::CalcKey_and_CheckPassword() | |||
258 | } | 265 | } |
259 | 266 | ||
260 | if (IsThereCheck() && _canCheck) | 267 | if (IsThereCheck() && _canCheck) |
261 | return (memcmp(_check_Calced, _check, kPswCheckSize) == 0); | 268 | return memcmp(_check_Calced32, _check32, sizeof(_check32)) == 0; |
262 | return true; | 269 | return true; |
263 | } | 270 | } |
264 | 271 | ||
diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h index 3cd7992..c6059aa 100644 --- a/CPP/7zip/Crypto/Rar5Aes.h +++ b/CPP/7zip/Crypto/Rar5Aes.h | |||
@@ -13,7 +13,7 @@ namespace NCrypto { | |||
13 | namespace NRar5 { | 13 | namespace NRar5 { |
14 | 14 | ||
15 | const unsigned kSaltSize = 16; | 15 | const unsigned kSaltSize = 16; |
16 | const unsigned kPswCheckSize = 8; | 16 | const unsigned kPswCheckSize32 = 2; |
17 | const unsigned kAesKeySize = 32; | 17 | const unsigned kAesKeySize = 32; |
18 | 18 | ||
19 | namespace NCryptoFlags | 19 | namespace NCryptoFlags |
@@ -22,48 +22,47 @@ namespace NCryptoFlags | |||
22 | const unsigned kUseMAC = 1 << 1; | 22 | const unsigned kUseMAC = 1 << 1; |
23 | } | 23 | } |
24 | 24 | ||
25 | struct CKey | 25 | struct CKeyBase |
26 | { | 26 | { |
27 | bool _needCalc; | 27 | protected: |
28 | UInt32 _key32[kAesKeySize / 4]; | ||
29 | UInt32 _hashKey32[SHA256_NUM_DIGEST_WORDS]; | ||
30 | UInt32 _check_Calced32[kPswCheckSize32]; | ||
28 | 31 | ||
29 | unsigned _numIterationsLog; | 32 | void Wipe() |
30 | Byte _salt[kSaltSize]; | 33 | { |
31 | CByteBuffer _password; | 34 | memset(this, 0, sizeof(*this)); |
35 | } | ||
32 | 36 | ||
33 | Byte _key[kAesKeySize]; | 37 | void CopyCalcedKeysFrom(const CKeyBase &k) |
34 | Byte _check_Calced[kPswCheckSize]; | ||
35 | Byte _hashKey[SHA256_DIGEST_SIZE]; | ||
36 | |||
37 | void CopyCalcedKeysFrom(const CKey &k) | ||
38 | { | 38 | { |
39 | memcpy(_key, k._key, sizeof(_key)); | 39 | *this = k; |
40 | memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced)); | ||
41 | memcpy(_hashKey, k._hashKey, sizeof(_hashKey)); | ||
42 | } | 40 | } |
41 | }; | ||
43 | 42 | ||
43 | struct CKey: public CKeyBase | ||
44 | { | ||
45 | CByteBuffer _password; | ||
46 | bool _needCalc; | ||
47 | unsigned _numIterationsLog; | ||
48 | Byte _salt[kSaltSize]; | ||
49 | |||
44 | bool IsKeyEqualTo(const CKey &key) | 50 | bool IsKeyEqualTo(const CKey &key) |
45 | { | 51 | { |
46 | return (_numIterationsLog == key._numIterationsLog | 52 | return _numIterationsLog == key._numIterationsLog |
47 | && memcmp(_salt, key._salt, sizeof(_salt)) == 0 | 53 | && memcmp(_salt, key._salt, sizeof(_salt)) == 0 |
48 | && _password == key._password); | 54 | && _password == key._password; |
49 | } | 55 | } |
50 | |||
51 | CKey(); | ||
52 | 56 | ||
53 | void Wipe() | 57 | CKey(); |
54 | { | 58 | ~CKey(); |
55 | _password.Wipe(); | 59 | |
56 | Z7_memset_0_ARRAY(_salt); | 60 | void Wipe(); |
57 | Z7_memset_0_ARRAY(_key); | ||
58 | Z7_memset_0_ARRAY(_check_Calced); | ||
59 | Z7_memset_0_ARRAY(_hashKey); | ||
60 | } | ||
61 | 61 | ||
62 | #ifdef Z7_CPP_IS_SUPPORTED_default | 62 | #ifdef Z7_CPP_IS_SUPPORTED_default |
63 | // CKey(const CKey &) = default; | 63 | // CKey(const CKey &) = default; |
64 | CKey& operator =(const CKey &) = default; | 64 | CKey& operator =(const CKey &) = default; |
65 | #endif | 65 | #endif |
66 | ~CKey() { Wipe(); } | ||
67 | }; | 66 | }; |
68 | 67 | ||
69 | 68 | ||
@@ -71,11 +70,11 @@ class CDecoder Z7_final: | |||
71 | public CAesCbcDecoder, | 70 | public CAesCbcDecoder, |
72 | public CKey | 71 | public CKey |
73 | { | 72 | { |
74 | Byte _check[kPswCheckSize]; | 73 | UInt32 _check32[kPswCheckSize32]; |
75 | bool _canCheck; | 74 | bool _canCheck; |
76 | UInt64 Flags; | 75 | UInt64 Flags; |
77 | 76 | ||
78 | bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); } | 77 | bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; } |
79 | public: | 78 | public: |
80 | Byte _iv[AES_BLOCK_SIZE]; | 79 | Byte _iv[AES_BLOCK_SIZE]; |
81 | 80 | ||
diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp index 878ea3a..e63f82c 100644 --- a/CPP/7zip/Crypto/RarAes.cpp +++ b/CPP/7zip/Crypto/RarAes.cpp | |||
@@ -111,7 +111,8 @@ static void UpdatePswDataSha1(Byte *data) | |||
111 | 111 | ||
112 | for (i = 16; i < 80; i++) | 112 | for (i = 16; i < 80; i++) |
113 | { | 113 | { |
114 | WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1); | 114 | const UInt32 t = WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16); |
115 | WW(i) = rotlFixed(t, 1); | ||
115 | } | 116 | } |
116 | 117 | ||
117 | for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) | 118 | for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++) |
@@ -128,6 +129,7 @@ void CDecoder::CalcKey() | |||
128 | 129 | ||
129 | const unsigned kSaltSize = 8; | 130 | const unsigned kSaltSize = 8; |
130 | 131 | ||
132 | MY_ALIGN (16) | ||
131 | Byte buf[kPasswordLen_Bytes_MAX + kSaltSize]; | 133 | Byte buf[kPasswordLen_Bytes_MAX + kSaltSize]; |
132 | 134 | ||
133 | if (_password.Size() != 0) | 135 | if (_password.Size() != 0) |
@@ -148,7 +150,7 @@ void CDecoder::CalcKey() | |||
148 | MY_ALIGN (16) | 150 | MY_ALIGN (16) |
149 | Byte digest[NSha1::kDigestSize]; | 151 | Byte digest[NSha1::kDigestSize]; |
150 | // rar reverts hash for sha. | 152 | // rar reverts hash for sha. |
151 | const UInt32 kNumRounds = ((UInt32)1 << 18); | 153 | const UInt32 kNumRounds = (UInt32)1 << 18; |
152 | UInt32 pos = 0; | 154 | UInt32 pos = 0; |
153 | UInt32 i; | 155 | UInt32 i; |
154 | for (i = 0; i < kNumRounds; i++) | 156 | for (i = 0; i < kNumRounds; i++) |
@@ -171,8 +173,14 @@ void CDecoder::CalcKey() | |||
171 | } | 173 | } |
172 | } | 174 | } |
173 | pos += (UInt32)rawSize; | 175 | pos += (UInt32)rawSize; |
176 | #if 1 | ||
177 | UInt32 pswNum; | ||
178 | SetUi32a(&pswNum, i) | ||
179 | sha.Update((const Byte *)&pswNum, 3); | ||
180 | #else | ||
174 | Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; | 181 | Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; |
175 | sha.Update(pswNum, 3); | 182 | sha.Update(pswNum, 3); |
183 | #endif | ||
176 | pos += 3; | 184 | pos += 3; |
177 | if (i % (kNumRounds / 16) == 0) | 185 | if (i % (kNumRounds / 16) == 0) |
178 | { | 186 | { |
diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp index 59698d8..c4e8311 100644 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp | |||
@@ -24,30 +24,31 @@ static const UInt16 kAES128 = 0x660E; | |||
24 | if (method != AES && method != 3DES), probably we need another code. | 24 | if (method != AES && method != 3DES), probably we need another code. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | static void DeriveKey2(const Byte *digest, Byte c, Byte *dest) | 27 | static void DeriveKey2(const UInt32 *digest32, Byte c, UInt32 *dest32) |
28 | { | 28 | { |
29 | const unsigned kBufSize = 64; | ||
29 | MY_ALIGN (16) | 30 | MY_ALIGN (16) |
30 | Byte buf[64]; | 31 | UInt32 buf32[kBufSize / 4]; |
31 | memset(buf, c, 64); | 32 | memset(buf32, c, kBufSize); |
32 | for (unsigned i = 0; i < NSha1::kDigestSize; i++) | 33 | for (unsigned i = 0; i < NSha1::kNumDigestWords; i++) |
33 | buf[i] ^= digest[i]; | 34 | buf32[i] ^= digest32[i]; |
34 | MY_ALIGN (16) | 35 | MY_ALIGN (16) |
35 | NSha1::CContext sha; | 36 | NSha1::CContext sha; |
36 | sha.Init(); | 37 | sha.Init(); |
37 | sha.Update(buf, 64); | 38 | sha.Update((const Byte *)buf32, kBufSize); |
38 | sha.Final(dest); | 39 | sha.Final((Byte *)dest32); |
39 | } | 40 | } |
40 | 41 | ||
41 | static void DeriveKey(NSha1::CContext &sha, Byte *key) | 42 | static void DeriveKey(NSha1::CContext &sha, Byte *key) |
42 | { | 43 | { |
43 | MY_ALIGN (16) | 44 | MY_ALIGN (16) |
44 | Byte digest[NSha1::kDigestSize]; | 45 | UInt32 digest32[NSha1::kNumDigestWords]; |
45 | sha.Final(digest); | 46 | sha.Final((Byte *)digest32); |
46 | MY_ALIGN (16) | 47 | MY_ALIGN (16) |
47 | Byte temp[NSha1::kDigestSize * 2]; | 48 | UInt32 temp32[NSha1::kNumDigestWords * 2]; |
48 | DeriveKey2(digest, 0x36, temp); | 49 | DeriveKey2(digest32, 0x36, temp32); |
49 | DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize); | 50 | DeriveKey2(digest32, 0x5C, temp32 + NSha1::kNumDigestWords); |
50 | memcpy(key, temp, 32); | 51 | memcpy(key, temp32, 32); |
51 | } | 52 | } |
52 | 53 | ||
53 | void CKeyInfo::SetPassword(const Byte *data, UInt32 size) | 54 | void CKeyInfo::SetPassword(const Byte *data, UInt32 size) |
@@ -122,24 +123,24 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) | |||
122 | passwOK = false; | 123 | passwOK = false; |
123 | if (_remSize < 16) | 124 | if (_remSize < 16) |
124 | return E_NOTIMPL; | 125 | return E_NOTIMPL; |
125 | Byte *p = _bufAligned; | 126 | Byte * const p = _bufAligned; |
126 | const unsigned format = GetUi16(p); | 127 | const unsigned format = GetUi16a(p); |
127 | if (format != 3) | 128 | if (format != 3) |
128 | return E_NOTIMPL; | 129 | return E_NOTIMPL; |
129 | unsigned algId = GetUi16(p + 2); | 130 | unsigned algId = GetUi16a(p + 2); |
130 | if (algId < kAES128) | 131 | if (algId < kAES128) |
131 | return E_NOTIMPL; | 132 | return E_NOTIMPL; |
132 | algId -= kAES128; | 133 | algId -= kAES128; |
133 | if (algId > 2) | 134 | if (algId > 2) |
134 | return E_NOTIMPL; | 135 | return E_NOTIMPL; |
135 | const unsigned bitLen = GetUi16(p + 4); | 136 | const unsigned bitLen = GetUi16a(p + 4); |
136 | const unsigned flags = GetUi16(p + 6); | 137 | const unsigned flags = GetUi16a(p + 6); |
137 | if (algId * 64 + 128 != bitLen) | 138 | if (algId * 64 + 128 != bitLen) |
138 | return E_NOTIMPL; | 139 | return E_NOTIMPL; |
139 | _key.KeySize = 16 + algId * 8; | 140 | _key.KeySize = 16 + algId * 8; |
140 | const bool cert = ((flags & 2) != 0); | 141 | const bool cert = ((flags & 2) != 0); |
141 | 142 | ||
142 | if ((flags & 0x4000) != 0) | 143 | if (flags & 0x4000) |
143 | { | 144 | { |
144 | // Use 3DES for rd data | 145 | // Use 3DES for rd data |
145 | return E_NOTIMPL; | 146 | return E_NOTIMPL; |
@@ -155,7 +156,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) | |||
155 | return E_NOTIMPL; | 156 | return E_NOTIMPL; |
156 | } | 157 | } |
157 | 158 | ||
158 | UInt32 rdSize = GetUi16(p + 8); | 159 | UInt32 rdSize = GetUi16a(p + 8); |
159 | 160 | ||
160 | if (rdSize + 16 > _remSize) | 161 | if (rdSize + 16 > _remSize) |
161 | return E_NOTIMPL; | 162 | return E_NOTIMPL; |
@@ -174,7 +175,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) | |||
174 | // PKCS7 padding | 175 | // PKCS7 padding |
175 | if (rdSize < kPadSize) | 176 | if (rdSize < kPadSize) |
176 | return E_NOTIMPL; | 177 | return E_NOTIMPL; |
177 | if ((rdSize & (kPadSize - 1)) != 0) | 178 | if (rdSize & (kPadSize - 1)) |
178 | return E_NOTIMPL; | 179 | return E_NOTIMPL; |
179 | } | 180 | } |
180 | 181 | ||
diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc index 95654b6..bf8ad8b 100644 --- a/CPP/7zip/GuiCommon.rc +++ b/CPP/7zip/GuiCommon.rc | |||
@@ -115,5 +115,5 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | |||
115 | _x + _xSize, _y, 8, 12 // these values are unused | 115 | _x + _xSize, _y, 8, 12 // these values are unused |
116 | 116 | ||
117 | 117 | ||
118 | #define OPTIONS_PAGE_XC_SIZE 280 | 118 | #define OPTIONS_PAGE_XC_SIZE 300 |
119 | #define OPTIONS_PAGE_YC_SIZE 280 | 119 | #define OPTIONS_PAGE_YC_SIZE 280 |
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index abbaf20..fbae89c 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt | |||
@@ -20,6 +20,8 @@ | |||
20 | 10 IFolderArchiveUpdateCallback2 | 20 | 10 IFolderArchiveUpdateCallback2 |
21 | 11 IFolderScanProgress | 21 | 11 IFolderScanProgress |
22 | 12 IFolderSetZoneIdMode | 22 | 12 IFolderSetZoneIdMode |
23 | 13 IFolderSetZoneIdFile | ||
24 | 14 IFolderArchiveUpdateCallback_MoveArc | ||
23 | 25 | ||
24 | 20 IFileExtractCallback.h::IGetProp | 26 | 20 IFileExtractCallback.h::IGetProp |
25 | 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old) | 27 | 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old) |
diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index aec2834..20d0ff7 100644 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h | |||
@@ -136,6 +136,9 @@ namespace NCoderPropID | |||
136 | kAffinity, // VT_UI8 | 136 | kAffinity, // VT_UI8 |
137 | kBranchOffset, // VT_UI4 | 137 | kBranchOffset, // VT_UI4 |
138 | kHashBits, // VT_UI4 | 138 | kHashBits, // VT_UI4 |
139 | kNumThreadGroups, // VT_UI4 | ||
140 | kThreadGroup, // VT_UI4 | ||
141 | kAffinityInGroup, // VT_UI8 | ||
139 | /* | 142 | /* |
140 | // kHash3Bits, // VT_UI4 | 143 | // kHash3Bits, // VT_UI4 |
141 | // kHash2Bits, // VT_UI4 | 144 | // kHash2Bits, // VT_UI4 |
diff --git a/CPP/7zip/Sort.mak b/CPP/7zip/Sort.mak new file mode 100644 index 0000000..ca0ff59 --- /dev/null +++ b/CPP/7zip/Sort.mak | |||
@@ -0,0 +1,6 @@ | |||
1 | !IF defined(USE_NO_ASM) || defined(USE_C_SORT) || "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" | ||
2 | C_OBJS = $(C_OBJS) \ | ||
3 | !ELSE | ||
4 | ASM_OBJS = $(ASM_OBJS) \ | ||
5 | !ENDIF | ||
6 | $O\Sort.obj | ||
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index eb77f25..46b740a 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp | |||
@@ -1516,6 +1516,8 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices, | |||
1516 | if (_zoneMode != NExtract::NZoneIdMode::kNone) | 1516 | if (_zoneMode != NExtract::NZoneIdMode::kNone) |
1517 | { | 1517 | { |
1518 | ReadZoneFile_Of_BaseFile(us2fs(_agentSpec->_archiveFilePath), extractCallbackSpec->ZoneBuf); | 1518 | ReadZoneFile_Of_BaseFile(us2fs(_agentSpec->_archiveFilePath), extractCallbackSpec->ZoneBuf); |
1519 | if (_zoneBuf.Size() != 0) | ||
1520 | extractCallbackSpec->ZoneBuf = _zoneBuf; | ||
1519 | } | 1521 | } |
1520 | #endif | 1522 | #endif |
1521 | 1523 | ||
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index ea81aa8..a63e459 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h | |||
@@ -60,6 +60,7 @@ class CAgentFolder Z7_final: | |||
60 | public IArchiveFolderInternal, | 60 | public IArchiveFolderInternal, |
61 | public IInArchiveGetStream, | 61 | public IInArchiveGetStream, |
62 | public IFolderSetZoneIdMode, | 62 | public IFolderSetZoneIdMode, |
63 | public IFolderSetZoneIdFile, | ||
63 | public IFolderOperations, | 64 | public IFolderOperations, |
64 | public IFolderSetFlatMode, | 65 | public IFolderSetFlatMode, |
65 | public CMyUnknownImp | 66 | public CMyUnknownImp |
@@ -75,6 +76,7 @@ class CAgentFolder Z7_final: | |||
75 | Z7_COM_QI_ENTRY(IArchiveFolderInternal) | 76 | Z7_COM_QI_ENTRY(IArchiveFolderInternal) |
76 | Z7_COM_QI_ENTRY(IInArchiveGetStream) | 77 | Z7_COM_QI_ENTRY(IInArchiveGetStream) |
77 | Z7_COM_QI_ENTRY(IFolderSetZoneIdMode) | 78 | Z7_COM_QI_ENTRY(IFolderSetZoneIdMode) |
79 | Z7_COM_QI_ENTRY(IFolderSetZoneIdFile) | ||
78 | Z7_COM_QI_ENTRY(IFolderOperations) | 80 | Z7_COM_QI_ENTRY(IFolderOperations) |
79 | Z7_COM_QI_ENTRY(IFolderSetFlatMode) | 81 | Z7_COM_QI_ENTRY(IFolderSetFlatMode) |
80 | Z7_COM_QI_END | 82 | Z7_COM_QI_END |
@@ -91,6 +93,7 @@ class CAgentFolder Z7_final: | |||
91 | Z7_IFACE_COM7_IMP(IArchiveFolderInternal) | 93 | Z7_IFACE_COM7_IMP(IArchiveFolderInternal) |
92 | Z7_IFACE_COM7_IMP(IInArchiveGetStream) | 94 | Z7_IFACE_COM7_IMP(IInArchiveGetStream) |
93 | Z7_IFACE_COM7_IMP(IFolderSetZoneIdMode) | 95 | Z7_IFACE_COM7_IMP(IFolderSetZoneIdMode) |
96 | Z7_IFACE_COM7_IMP(IFolderSetZoneIdFile) | ||
94 | Z7_IFACE_COM7_IMP(IFolderOperations) | 97 | Z7_IFACE_COM7_IMP(IFolderOperations) |
95 | Z7_IFACE_COM7_IMP(IFolderSetFlatMode) | 98 | Z7_IFACE_COM7_IMP(IFolderSetFlatMode) |
96 | 99 | ||
@@ -106,11 +109,11 @@ public: | |||
106 | int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); | 109 | int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); |
107 | 110 | ||
108 | CAgentFolder(): | 111 | CAgentFolder(): |
109 | _proxyDirIndex(0), | ||
110 | _isAltStreamFolder(false), | 112 | _isAltStreamFolder(false), |
111 | _flatMode(false), | 113 | _flatMode(false), |
112 | _loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now | 114 | _loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now |
113 | , _zoneMode(NExtract::NZoneIdMode::kNone) | 115 | _proxyDirIndex(0), |
116 | _zoneMode(NExtract::NZoneIdMode::kNone) | ||
114 | /* , _replaceAltStreamCharsMode(0) */ | 117 | /* , _replaceAltStreamCharsMode(0) */ |
115 | {} | 118 | {} |
116 | 119 | ||
@@ -145,21 +148,23 @@ public: | |||
145 | UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive | 148 | UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive |
146 | 149 | ||
147 | public: | 150 | public: |
151 | bool _isAltStreamFolder; | ||
152 | bool _flatMode; | ||
153 | bool _loadAltStreams; // in Flat mode | ||
148 | const CProxyArc *_proxy; | 154 | const CProxyArc *_proxy; |
149 | const CProxyArc2 *_proxy2; | 155 | const CProxyArc2 *_proxy2; |
150 | unsigned _proxyDirIndex; | 156 | unsigned _proxyDirIndex; |
151 | bool _isAltStreamFolder; | 157 | NExtract::NZoneIdMode::EEnum _zoneMode; |
158 | CByteBuffer _zoneBuf; | ||
159 | // Int32 _replaceAltStreamCharsMode; | ||
152 | // CMyComPtr<IFolderFolder> _parentFolder; | 160 | // CMyComPtr<IFolderFolder> _parentFolder; |
153 | CMyComPtr<IInFolderArchive> _agent; | 161 | CMyComPtr<IInFolderArchive> _agent; |
154 | CAgent *_agentSpec; | 162 | CAgent *_agentSpec; |
155 | |||
156 | CRecordVector<CProxyItem> _items; | 163 | CRecordVector<CProxyItem> _items; |
157 | bool _flatMode; | ||
158 | bool _loadAltStreams; // in Flat mode | ||
159 | // Int32 _replaceAltStreamCharsMode; | ||
160 | NExtract::NZoneIdMode::EEnum _zoneMode; | ||
161 | }; | 164 | }; |
162 | 165 | ||
166 | |||
167 | |||
163 | class CAgent Z7_final: | 168 | class CAgent Z7_final: |
164 | public IInFolderArchive, | 169 | public IInFolderArchive, |
165 | public IFolderArcProps, | 170 | public IFolderArcProps, |
@@ -213,22 +218,22 @@ public: | |||
213 | CProxyArc2 *_proxy2; | 218 | CProxyArc2 *_proxy2; |
214 | CArchiveLink _archiveLink; | 219 | CArchiveLink _archiveLink; |
215 | 220 | ||
216 | bool ThereIsPathProp; | ||
217 | // bool ThereIsAltStreamProp; | ||
218 | |||
219 | UString ArchiveType; | 221 | UString ArchiveType; |
220 | 222 | ||
221 | FStringVector _names; | 223 | FStringVector _names; |
222 | FString _folderPrefix; // for new files from disk | 224 | FString _folderPrefix; // for new files from disk |
223 | 225 | ||
224 | bool _updatePathPrefix_is_AltFolder; | ||
225 | UString _updatePathPrefix; | 226 | UString _updatePathPrefix; |
226 | CAgentFolder *_agentFolder; | 227 | CAgentFolder *_agentFolder; |
227 | 228 | ||
228 | UString _archiveFilePath; | 229 | UString _archiveFilePath; // it can be path of non-existing file if file is virtual |
230 | |||
229 | DWORD _attrib; | 231 | DWORD _attrib; |
232 | bool _updatePathPrefix_is_AltFolder; | ||
233 | bool ThereIsPathProp; | ||
230 | bool _isDeviceFile; | 234 | bool _isDeviceFile; |
231 | bool _isHashHandler; | 235 | bool _isHashHandler; |
236 | |||
232 | FString _hashBaseFolderPrefix; | 237 | FString _hashBaseFolderPrefix; |
233 | 238 | ||
234 | #ifndef Z7_EXTRACT_ONLY | 239 | #ifndef Z7_EXTRACT_ONLY |
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 176f39b..d04ddab 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp | |||
@@ -636,7 +636,7 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
636 | file.Name = (const wchar_t *)p; | 636 | file.Name = (const wchar_t *)p; |
637 | file.NameLen = 0; | 637 | file.NameLen = 0; |
638 | if (size >= sizeof(wchar_t)) | 638 | if (size >= sizeof(wchar_t)) |
639 | file.NameLen = size / sizeof(wchar_t) - 1; | 639 | file.NameLen = size / (unsigned)sizeof(wchar_t) - 1; |
640 | } | 640 | } |
641 | else | 641 | else |
642 | #endif | 642 | #endif |
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp index 89b20dc..eea681c 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp | |||
@@ -22,6 +22,12 @@ Z7_COM7F_IMF(CAgentFolder::SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode)) | |||
22 | return S_OK; | 22 | return S_OK; |
23 | } | 23 | } |
24 | 24 | ||
25 | Z7_COM7F_IMF(CAgentFolder::SetZoneIdFile(const Byte *data, UInt32 size)) | ||
26 | { | ||
27 | _zoneBuf.CopyFrom(data, size); | ||
28 | return S_OK; | ||
29 | } | ||
30 | |||
25 | 31 | ||
26 | Z7_COM7F_IMF(CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, | 32 | Z7_COM7F_IMF(CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, |
27 | Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, | 33 | Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, |
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 0189224..1da6601 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | |||
@@ -62,6 +62,33 @@ static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path) | |||
62 | return RemoveDir(path); | 62 | return RemoveDir(path); |
63 | } | 63 | } |
64 | 64 | ||
65 | |||
66 | |||
67 | struct C_CopyFileProgress_to_FolderCallback_MoveArc Z7_final: | ||
68 | public ICopyFileProgress | ||
69 | { | ||
70 | IFolderArchiveUpdateCallback_MoveArc *Callback; | ||
71 | HRESULT CallbackResult; | ||
72 | |||
73 | virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override | ||
74 | { | ||
75 | HRESULT res = Callback->MoveArc_Progress(total, current); | ||
76 | CallbackResult = res; | ||
77 | // we can ignore E_ABORT here, because we update archive, | ||
78 | // and we want to get correct archive after updating | ||
79 | if (res == E_ABORT) | ||
80 | res = S_OK; | ||
81 | return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL; | ||
82 | } | ||
83 | |||
84 | C_CopyFileProgress_to_FolderCallback_MoveArc( | ||
85 | IFolderArchiveUpdateCallback_MoveArc *callback) : | ||
86 | Callback(callback), | ||
87 | CallbackResult(S_OK) | ||
88 | {} | ||
89 | }; | ||
90 | |||
91 | |||
65 | HRESULT CAgentFolder::CommonUpdateOperation( | 92 | HRESULT CAgentFolder::CommonUpdateOperation( |
66 | AGENT_OP operation, | 93 | AGENT_OP operation, |
67 | bool moveMode, | 94 | bool moveMode, |
@@ -159,8 +186,51 @@ HRESULT CAgentFolder::CommonUpdateOperation( | |||
159 | // now: we reopen archive after close | 186 | // now: we reopen archive after close |
160 | 187 | ||
161 | // m_FolderItem = NULL; | 188 | // m_FolderItem = NULL; |
189 | _items.Clear(); | ||
190 | _proxyDirIndex = k_Proxy_RootDirIndex; | ||
191 | |||
192 | CMyComPtr<IFolderArchiveUpdateCallback_MoveArc> updateCallback_MoveArc; | ||
193 | if (progress) | ||
194 | progress->QueryInterface(IID_IFolderArchiveUpdateCallback_MoveArc, (void **)&updateCallback_MoveArc); | ||
162 | 195 | ||
163 | const HRESULT res = tempFile.MoveToOriginal(true); | 196 | HRESULT res; |
197 | if (updateCallback_MoveArc) | ||
198 | { | ||
199 | const FString &tempFilePath = tempFile.Get_TempFilePath(); | ||
200 | UInt64 totalSize = 0; | ||
201 | { | ||
202 | NFind::CFileInfo fi; | ||
203 | if (fi.Find(tempFilePath)) | ||
204 | totalSize = fi.Size; | ||
205 | } | ||
206 | RINOK(updateCallback_MoveArc->MoveArc_Start( | ||
207 | fs2us(tempFilePath), | ||
208 | fs2us(tempFile.Get_OriginalFilePath()), | ||
209 | totalSize, | ||
210 | 1)) // updateMode | ||
211 | |||
212 | C_CopyFileProgress_to_FolderCallback_MoveArc prox(updateCallback_MoveArc); | ||
213 | res = tempFile.MoveToOriginal( | ||
214 | true, // deleteOriginal | ||
215 | &prox); | ||
216 | if (res == S_OK) | ||
217 | { | ||
218 | res = updateCallback_MoveArc->MoveArc_Finish(); | ||
219 | // we don't return after E_ABORT here, because | ||
220 | // we want to reopen new archive still. | ||
221 | } | ||
222 | else if (prox.CallbackResult != S_OK) | ||
223 | res = prox.CallbackResult; | ||
224 | |||
225 | // if updating callback returned E_ABORT, | ||
226 | // then openCallback still can return E_ABORT also. | ||
227 | // So ReOpen() will return with E_ABORT. | ||
228 | // But we want to open archive still. | ||
229 | // And Before_ArcReopen() call will clear user break status in that case. | ||
230 | RINOK(updateCallback_MoveArc->Before_ArcReopen()) | ||
231 | } | ||
232 | else | ||
233 | res = tempFile.MoveToOriginal(true); // deleteOriginal | ||
164 | 234 | ||
165 | // RINOK(res); | 235 | // RINOK(res); |
166 | if (res == S_OK) | 236 | if (res == S_OK) |
@@ -189,10 +259,10 @@ HRESULT CAgentFolder::CommonUpdateOperation( | |||
189 | } | 259 | } |
190 | 260 | ||
191 | // CAgent::ReOpen() deletes _proxy and _proxy2 | 261 | // CAgent::ReOpen() deletes _proxy and _proxy2 |
192 | _items.Clear(); | 262 | // _items.Clear(); |
193 | _proxy = NULL; | 263 | _proxy = NULL; |
194 | _proxy2 = NULL; | 264 | _proxy2 = NULL; |
195 | _proxyDirIndex = k_Proxy_RootDirIndex; | 265 | // _proxyDirIndex = k_Proxy_RootDirIndex; |
196 | _isAltStreamFolder = false; | 266 | _isAltStreamFolder = false; |
197 | 267 | ||
198 | 268 | ||
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h index 55f1423..12b900f 100644 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h | |||
@@ -103,5 +103,21 @@ Z7_IFACE_CONSTR_FOLDERARC(IFolderScanProgress, 0x11) | |||
103 | 103 | ||
104 | Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdMode, 0x12) | 104 | Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdMode, 0x12) |
105 | 105 | ||
106 | #define Z7_IFACEM_IFolderSetZoneIdFile(x) \ | ||
107 | x(SetZoneIdFile(const Byte *data, UInt32 size)) \ | ||
108 | |||
109 | Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdFile, 0x13) | ||
110 | |||
111 | |||
112 | // if the caller calls Before_ArcReopen(), the callee must | ||
113 | // clear user break status, because the caller want to open archive still. | ||
114 | #define Z7_IFACEM_IFolderArchiveUpdateCallback_MoveArc(x) \ | ||
115 | x(MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode)) \ | ||
116 | x(MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) \ | ||
117 | x(MoveArc_Finish()) \ | ||
118 | x(Before_ArcReopen()) \ | ||
119 | |||
120 | Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback_MoveArc, 0x14) | ||
121 | |||
106 | Z7_PURE_INTERFACES_END | 122 | Z7_PURE_INTERFACES_END |
107 | #endif | 123 | #endif |
diff --git a/CPP/7zip/UI/Client7z/makefile.gcc b/CPP/7zip/UI/Client7z/makefile.gcc index 3f97205..0f89cb0 100644 --- a/CPP/7zip/UI/Client7z/makefile.gcc +++ b/CPP/7zip/UI/Client7z/makefile.gcc | |||
@@ -24,7 +24,6 @@ else | |||
24 | 24 | ||
25 | SYS_OBJS = \ | 25 | SYS_OBJS = \ |
26 | $O/MyWindows.o \ | 26 | $O/MyWindows.o \ |
27 | $O/TimeUtils.o \ | ||
28 | 27 | ||
29 | endif | 28 | endif |
30 | 29 | ||
@@ -53,12 +52,16 @@ WIN_OBJS = \ | |||
53 | $O/FileName.o \ | 52 | $O/FileName.o \ |
54 | $O/PropVariant.o \ | 53 | $O/PropVariant.o \ |
55 | $O/PropVariantConv.o \ | 54 | $O/PropVariantConv.o \ |
55 | $O/TimeUtils.o \ | ||
56 | 56 | ||
57 | 7ZIP_COMMON_OBJS = \ | 57 | 7ZIP_COMMON_OBJS = \ |
58 | $O/FileStreams.o \ | 58 | $O/FileStreams.o \ |
59 | 59 | ||
60 | C_OBJS = \ | ||
61 | $O/Alloc.o \ | ||
60 | 62 | ||
61 | OBJS = \ | 63 | OBJS = \ |
64 | $(C_OBJS) \ | ||
62 | $(COMMON_OBJS) \ | 65 | $(COMMON_OBJS) \ |
63 | $(WIN_OBJS) \ | 66 | $(WIN_OBJS) \ |
64 | $(SYS_OBJS) \ | 67 | $(SYS_OBJS) \ |
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 556b25a..7fe18fb 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | |||
@@ -63,17 +63,46 @@ EXTERN_C_END | |||
63 | 63 | ||
64 | #else | 64 | #else |
65 | 65 | ||
66 | // #define MY_isatty_fileno(x) (isatty(fileno(x))) | 66 | static bool MY_IS_TERMINAL(FILE *x) |
67 | // #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); | ||
68 | static inline bool MY_IS_TERMINAL(FILE *x) | ||
69 | { | 67 | { |
70 | return ( | 68 | #ifdef _WIN32 |
71 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) | 69 | /* |
72 | _isatty(_fileno(x)) | 70 | crt/stdio.h: |
73 | #else | 71 | typedef struct _iobuf FILE; |
74 | isatty(fileno(x)) | 72 | #define stdin (&_iob[0]) |
75 | #endif | 73 | #define stdout (&_iob[1]) |
76 | != 0); | 74 | #define stderr (&_iob[2]) |
75 | */ | ||
76 | // fprintf(stderr, "\nMY_IS_TERMINAL = %p", x); | ||
77 | const int fd = _fileno(x); | ||
78 | /* (fd) is 0, 1 or 2 in console program. | ||
79 | docs: If stdout or stderr is not associated with | ||
80 | an output stream (for example, in a Windows application | ||
81 | without a console window), the file descriptor returned is -2. | ||
82 | In previous versions, the file descriptor returned was -1. | ||
83 | */ | ||
84 | if (fd < 0) // is not associated with an output stream application (without a console window) | ||
85 | return false; | ||
86 | // fprintf(stderr, "\n\nstderr _fileno(%p) = %d", x, fd); | ||
87 | if (!_isatty(fd)) | ||
88 | return false; | ||
89 | // fprintf(stderr, "\nisatty_val = true"); | ||
90 | const HANDLE h = (HANDLE)_get_osfhandle(fd); | ||
91 | /* _get_osfhandle() returns intptr_t in new SDK, or long in MSVC6. | ||
92 | Also it can return (INVALID_HANDLE_VALUE). | ||
93 | docs: _get_osfhandle also returns the special value -2 when | ||
94 | the file descriptor is not associated with a stream | ||
95 | in old msvcrt.dll: it returns (-1) for incorrect value | ||
96 | */ | ||
97 | // fprintf(stderr, "\n_get_osfhandle() = %p", (void *)h); | ||
98 | if (h == NULL || h == INVALID_HANDLE_VALUE) | ||
99 | return false; | ||
100 | DWORD st; | ||
101 | // fprintf(stderr, "\nGetConsoleMode() = %u", (unsigned)GetConsoleMode(h, &st)); | ||
102 | return GetConsoleMode(h, &st) != 0; | ||
103 | #else | ||
104 | return isatty(fileno(x)) != 0; | ||
105 | #endif | ||
77 | } | 106 | } |
78 | 107 | ||
79 | #endif | 108 | #endif |
@@ -312,7 +341,7 @@ static const CSwitchForm kSwitchForms[] = | |||
312 | { "spf", SWFRM_STRING_SINGL(0) }, | 341 | { "spf", SWFRM_STRING_SINGL(0) }, |
313 | 342 | ||
314 | { "snh", SWFRM_MINUS }, | 343 | { "snh", SWFRM_MINUS }, |
315 | { "snld", SWFRM_MINUS }, | 344 | { "snld", SWFRM_STRING }, |
316 | { "snl", SWFRM_MINUS }, | 345 | { "snl", SWFRM_MINUS }, |
317 | { "sni", SWFRM_SIMPLE }, | 346 | { "sni", SWFRM_SIMPLE }, |
318 | 347 | ||
@@ -1088,7 +1117,7 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, | |||
1088 | const UString &s = parser[NKey::kLargePages].PostStrings[0]; | 1117 | const UString &s = parser[NKey::kLargePages].PostStrings[0]; |
1089 | if (s.IsEmpty()) | 1118 | if (s.IsEmpty()) |
1090 | slp = 1; | 1119 | slp = 1; |
1091 | else if (s != L"-") | 1120 | else if (!s.IsEqualTo("-")) |
1092 | { | 1121 | { |
1093 | if (!StringToUInt32(s, slp)) | 1122 | if (!StringToUInt32(s, slp)) |
1094 | throw CArcCmdLineException("Unsupported switch postfix for -slp", s); | 1123 | throw CArcCmdLineException("Unsupported switch postfix for -slp", s); |
@@ -1338,7 +1367,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1338 | const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; | 1367 | const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; |
1339 | if (!s.IsEmpty()) | 1368 | if (!s.IsEmpty()) |
1340 | { | 1369 | { |
1341 | if (s == L"2") | 1370 | if (s.IsEqualTo("2")) |
1342 | censorPathMode = NWildcard::k_FullPath; | 1371 | censorPathMode = NWildcard::k_FullPath; |
1343 | else | 1372 | else |
1344 | throw CArcCmdLineException("Unsupported -spf:", s); | 1373 | throw CArcCmdLineException("Unsupported -spf:", s); |
@@ -1400,6 +1429,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1400 | const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); | 1429 | const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); |
1401 | const bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; | 1430 | const bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; |
1402 | const bool isRename = options.Command.CommandType == NCommandType::kRename; | 1431 | const bool isRename = options.Command.CommandType == NCommandType::kRename; |
1432 | options.UpdateOptions.RenameMode = isRename; | ||
1403 | 1433 | ||
1404 | if ((isExtractOrList || isRename) && options.StdInMode) | 1434 | if ((isExtractOrList || isRename) && options.StdInMode) |
1405 | thereIsArchiveName = false; | 1435 | thereIsArchiveName = false; |
@@ -1449,14 +1479,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1449 | 1479 | ||
1450 | SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId); | 1480 | SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId); |
1451 | SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName); | 1481 | SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName); |
1452 | |||
1453 | CBoolPair symLinks_AllowDangerous; | ||
1454 | SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); | ||
1455 | |||
1456 | |||
1457 | /* | 1482 | /* |
1458 | bool supportSymLink = options.SymLinks.Val; | 1483 | bool supportSymLink = options.SymLinks.Val; |
1459 | |||
1460 | if (!options.SymLinks.Def) | 1484 | if (!options.SymLinks.Def) |
1461 | { | 1485 | { |
1462 | if (isExtractOrList) | 1486 | if (isExtractOrList) |
@@ -1464,7 +1488,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1464 | else | 1488 | else |
1465 | supportSymLink = false; | 1489 | supportSymLink = false; |
1466 | } | 1490 | } |
1467 | |||
1468 | #ifdef ENV_HAVE_LSTAT | 1491 | #ifdef ENV_HAVE_LSTAT |
1469 | if (supportSymLink) | 1492 | if (supportSymLink) |
1470 | global_use_lstat = 1; | 1493 | global_use_lstat = 1; |
@@ -1473,7 +1496,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1473 | #endif | 1496 | #endif |
1474 | */ | 1497 | */ |
1475 | 1498 | ||
1476 | |||
1477 | if (isExtractOrList) | 1499 | if (isExtractOrList) |
1478 | { | 1500 | { |
1479 | CExtractOptionsBase &eo = options.ExtractOptions; | 1501 | CExtractOptionsBase &eo = options.ExtractOptions; |
@@ -1497,7 +1519,15 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1497 | if (!options.SymLinks.Def) | 1519 | if (!options.SymLinks.Def) |
1498 | nt.SymLinks.Val = true; | 1520 | nt.SymLinks.Val = true; |
1499 | 1521 | ||
1500 | nt.SymLinks_AllowDangerous = symLinks_AllowDangerous; | 1522 | if (parser[NKey::kSymLinks_AllowDangerous].ThereIs) |
1523 | { | ||
1524 | const UString &s = parser[NKey::kSymLinks_AllowDangerous].PostStrings[0]; | ||
1525 | UInt32 v = 9; // default value for "-snld" instead of default = 5 without "-snld". | ||
1526 | if (!s.IsEmpty()) | ||
1527 | if (!StringToUInt32(s, v)) | ||
1528 | throw CArcCmdLineException("Unsupported switch postfix -snld", s); | ||
1529 | nt.SymLinks_DangerousLevel = (unsigned)v; | ||
1530 | } | ||
1501 | 1531 | ||
1502 | nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; | 1532 | nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; |
1503 | nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; | 1533 | nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; |
@@ -1516,9 +1546,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1516 | const UString &s = parser[NKey::kZoneFile].PostStrings[0]; | 1546 | const UString &s = parser[NKey::kZoneFile].PostStrings[0]; |
1517 | if (!s.IsEmpty()) | 1547 | if (!s.IsEmpty()) |
1518 | { | 1548 | { |
1519 | if (s == L"0") eo.ZoneMode = NExtract::NZoneIdMode::kNone; | 1549 | if (s.IsEqualTo("0")) eo.ZoneMode = NExtract::NZoneIdMode::kNone; |
1520 | else if (s == L"1") eo.ZoneMode = NExtract::NZoneIdMode::kAll; | 1550 | else if (s.IsEqualTo("1")) eo.ZoneMode = NExtract::NZoneIdMode::kAll; |
1521 | else if (s == L"2") eo.ZoneMode = NExtract::NZoneIdMode::kOffice; | 1551 | else if (s.IsEqualTo("2")) eo.ZoneMode = NExtract::NZoneIdMode::kOffice; |
1522 | else | 1552 | else |
1523 | throw CArcCmdLineException("Unsupported -snz:", s); | 1553 | throw CArcCmdLineException("Unsupported -snz:", s); |
1524 | } | 1554 | } |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 2d32694..6631629 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | |||
@@ -6,12 +6,10 @@ | |||
6 | #undef printf | 6 | #undef printf |
7 | 7 | ||
8 | // #include <stdio.h> | 8 | // #include <stdio.h> |
9 | // #include "../../../../C/CpuTicks.h" | ||
10 | 9 | ||
11 | #include "../../../../C/Alloc.h" | 10 | #include "../../../../C/Alloc.h" |
12 | #include "../../../../C/CpuArch.h" | 11 | #include "../../../../C/CpuArch.h" |
13 | 12 | ||
14 | |||
15 | #include "../../../Common/ComTry.h" | 13 | #include "../../../Common/ComTry.h" |
16 | #include "../../../Common/IntToString.h" | 14 | #include "../../../Common/IntToString.h" |
17 | #include "../../../Common/StringConvert.h" | 15 | #include "../../../Common/StringConvert.h" |
@@ -33,6 +31,8 @@ | |||
33 | #include "../../Common/FilePathAutoRename.h" | 31 | #include "../../Common/FilePathAutoRename.h" |
34 | #include "../../Common/StreamUtils.h" | 32 | #include "../../Common/StreamUtils.h" |
35 | 33 | ||
34 | #include "../../Archive/Common/ItemNameUtils.h" | ||
35 | |||
36 | #include "../Common/ExtractingFilePath.h" | 36 | #include "../Common/ExtractingFilePath.h" |
37 | #include "../Common/PropIDUtils.h" | 37 | #include "../Common/PropIDUtils.h" |
38 | 38 | ||
@@ -54,6 +54,23 @@ static const char * const kCantSetFileLen = "Cannot set length for output file"; | |||
54 | #ifdef SUPPORT_LINKS | 54 | #ifdef SUPPORT_LINKS |
55 | static const char * const kCantCreateHardLink = "Cannot create hard link"; | 55 | static const char * const kCantCreateHardLink = "Cannot create hard link"; |
56 | static const char * const kCantCreateSymLink = "Cannot create symbolic link"; | 56 | static const char * const kCantCreateSymLink = "Cannot create symbolic link"; |
57 | static const char * const k_HardLink_to_SymLink_Ignored = "Hard link to symbolic link was ignored"; | ||
58 | static const char * const k_CantDelete_File_for_SymLink = "Cannot delete file for symbolic link creation"; | ||
59 | static const char * const k_CantDelete_Dir_for_SymLink = "Cannot delete directory for symbolic link creation"; | ||
60 | #endif | ||
61 | |||
62 | static const unsigned k_LinkDataSize_LIMIT = 1 << 12; | ||
63 | |||
64 | #ifdef SUPPORT_LINKS | ||
65 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
66 | // we convert linux slashes to windows slashes for further processing. | ||
67 | // also we convert linux backslashes to BackslashReplacement character. | ||
68 | #define REPLACE_SLASHES_from_Linux_to_Sys(s) \ | ||
69 | { NArchive::NItemName::ReplaceToWinSlashes(s, true); } // useBackslashReplacement | ||
70 | // { s.Replace(L'/', WCHAR_PATH_SEPARATOR); } | ||
71 | #else | ||
72 | #define REPLACE_SLASHES_from_Linux_to_Sys(s) | ||
73 | #endif | ||
57 | #endif | 74 | #endif |
58 | 75 | ||
59 | #ifndef Z7_SFX | 76 | #ifndef Z7_SFX |
@@ -140,21 +157,25 @@ static bool FindExt2(const char *p, const UString &name) | |||
140 | } | 157 | } |
141 | 158 | ||
142 | 159 | ||
143 | static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); | 160 | static const char * const k_ZoneId_StreamName_With_Colon_Prefix = ":Zone.Identifier"; |
144 | 161 | ||
145 | void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf) | 162 | bool Is_ZoneId_StreamName(const wchar_t *s) |
146 | { | 163 | { |
147 | FString fileName (fileName2); | 164 | return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1); |
148 | fileName += k_ZoneId_StreamName; | 165 | } |
149 | 166 | ||
167 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf) | ||
168 | { | ||
150 | buf.Free(); | 169 | buf.Free(); |
170 | FString path (fileName); | ||
171 | path += k_ZoneId_StreamName_With_Colon_Prefix; | ||
151 | NIO::CInFile file; | 172 | NIO::CInFile file; |
152 | if (!file.Open(fileName)) | 173 | if (!file.Open(path)) |
153 | return; | 174 | return; |
154 | UInt64 fileSize; | 175 | UInt64 fileSize; |
155 | if (!file.GetLength(fileSize)) | 176 | if (!file.GetLength(fileSize)) |
156 | return; | 177 | return; |
157 | if (fileSize == 0 || fileSize >= ((UInt32)1 << 16)) | 178 | if (fileSize == 0 || fileSize >= (1u << 15)) |
158 | return; | 179 | return; |
159 | buf.Alloc((size_t)fileSize); | 180 | buf.Alloc((size_t)fileSize); |
160 | size_t processed; | 181 | size_t processed; |
@@ -166,7 +187,7 @@ void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf) | |||
166 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf) | 187 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf) |
167 | { | 188 | { |
168 | FString path (fileName); | 189 | FString path (fileName); |
169 | path += k_ZoneId_StreamName; | 190 | path += k_ZoneId_StreamName_With_Colon_Prefix; |
170 | NIO::COutFile file; | 191 | NIO::COutFile file; |
171 | if (!file.Create_ALWAYS(path)) | 192 | if (!file.Create_ALWAYS(path)) |
172 | return false; | 193 | return false; |
@@ -213,7 +234,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r | |||
213 | if (!_arc->Ask_INode) | 234 | if (!_arc->Ask_INode) |
214 | return S_OK; | 235 | return S_OK; |
215 | 236 | ||
216 | IInArchive *archive = _arc->Archive; | 237 | IInArchive * const archive = _arc->Archive; |
217 | CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs; | 238 | CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs; |
218 | 239 | ||
219 | { | 240 | { |
@@ -275,16 +296,13 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r | |||
275 | 296 | ||
276 | 297 | ||
277 | CArchiveExtractCallback::CArchiveExtractCallback(): | 298 | CArchiveExtractCallback::CArchiveExtractCallback(): |
278 | _arc(NULL), | 299 | // Write_CTime(true), |
279 | Write_CTime(true), | 300 | // Write_ATime(true), |
280 | Write_ATime(true), | 301 | // Write_MTime(true), |
281 | Write_MTime(true), | ||
282 | Is_elimPrefix_Mode(false), | 302 | Is_elimPrefix_Mode(false), |
303 | _arc(NULL), | ||
283 | _multiArchives(false) | 304 | _multiArchives(false) |
284 | { | 305 | { |
285 | LocalProgressSpec = new CLocalProgress(); | ||
286 | _localProgress = LocalProgressSpec; | ||
287 | |||
288 | #ifdef Z7_USE_SECURITY_CODE | 306 | #ifdef Z7_USE_SECURITY_CODE |
289 | _saclEnabled = InitLocalPrivileges(); | 307 | _saclEnabled = InitLocalPrivileges(); |
290 | #endif | 308 | #endif |
@@ -293,9 +311,9 @@ CArchiveExtractCallback::CArchiveExtractCallback(): | |||
293 | 311 | ||
294 | void CArchiveExtractCallback::InitBeforeNewArchive() | 312 | void CArchiveExtractCallback::InitBeforeNewArchive() |
295 | { | 313 | { |
296 | #if defined(_WIN32) && !defined(UNDER_CE) | 314 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
297 | ZoneBuf.Free(); | 315 | ZoneBuf.Free(); |
298 | #endif | 316 | #endif |
299 | } | 317 | } |
300 | 318 | ||
301 | void CArchiveExtractCallback::Init( | 319 | void CArchiveExtractCallback::Init( |
@@ -312,37 +330,31 @@ void CArchiveExtractCallback::Init( | |||
312 | _outFileStream.Release(); | 330 | _outFileStream.Release(); |
313 | _bufPtrSeqOutStream.Release(); | 331 | _bufPtrSeqOutStream.Release(); |
314 | 332 | ||
315 | #ifdef SUPPORT_LINKS | 333 | #ifdef SUPPORT_LINKS |
316 | _hardLinks.Clear(); | 334 | _hardLinks.Clear(); |
317 | #endif | 335 | _postLinks.Clear(); |
336 | #endif | ||
318 | 337 | ||
319 | #ifdef SUPPORT_ALT_STREAMS | 338 | #ifdef SUPPORT_ALT_STREAMS |
320 | _renamedFiles.Clear(); | 339 | _renamedFiles.Clear(); |
321 | #endif | 340 | #endif |
322 | 341 | ||
323 | _ntOptions = ntOptions; | 342 | _ntOptions = ntOptions; |
324 | _wildcardCensor = wildcardCensor; | 343 | _wildcardCensor = wildcardCensor; |
325 | |||
326 | _stdOutMode = stdOutMode; | 344 | _stdOutMode = stdOutMode; |
327 | _testMode = testMode; | 345 | _testMode = testMode; |
328 | |||
329 | // _progressTotal = 0; | ||
330 | // _progressTotal_Defined = false; | ||
331 | |||
332 | _packTotal = packSize; | 346 | _packTotal = packSize; |
333 | _progressTotal = packSize; | 347 | _progressTotal = packSize; |
334 | _progressTotal_Defined = true; | 348 | // _progressTotal = 0; |
335 | 349 | // _progressTotal_Defined = false; | |
350 | // _progressTotal_Defined = true; | ||
336 | _extractCallback2 = extractCallback2; | 351 | _extractCallback2 = extractCallback2; |
337 | |||
338 | /* | 352 | /* |
339 | _compressProgress.Release(); | 353 | _compressProgress.Release(); |
340 | _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); | 354 | _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); |
341 | |||
342 | _callbackMessage.Release(); | 355 | _callbackMessage.Release(); |
343 | _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage); | 356 | _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage); |
344 | */ | 357 | */ |
345 | |||
346 | _folderArchiveExtractCallback2.Release(); | 358 | _folderArchiveExtractCallback2.Release(); |
347 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); | 359 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); |
348 | 360 | ||
@@ -390,7 +402,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size)) | |||
390 | { | 402 | { |
391 | COM_TRY_BEGIN | 403 | COM_TRY_BEGIN |
392 | _progressTotal = size; | 404 | _progressTotal = size; |
393 | _progressTotal_Defined = true; | 405 | // _progressTotal_Defined = true; |
394 | if (!_multiArchives && _extractCallback2) | 406 | if (!_multiArchives && _extractCallback2) |
395 | return _extractCallback2->SetTotal(size); | 407 | return _extractCallback2->SetTotal(size); |
396 | return S_OK; | 408 | return S_OK; |
@@ -430,7 +442,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)) | |||
430 | if (_multiArchives) | 442 | if (_multiArchives) |
431 | { | 443 | { |
432 | packCur = LocalProgressSpec->InSize; | 444 | packCur = LocalProgressSpec->InSize; |
433 | if (completeValue && _progressTotal_Defined) | 445 | if (completeValue /* && _progressTotal_Defined */) |
434 | packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); | 446 | packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); |
435 | completeValue = &packCur; | 447 | completeValue = &packCur; |
436 | } | 448 | } |
@@ -443,12 +455,13 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)) | |||
443 | Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) | 455 | Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) |
444 | { | 456 | { |
445 | COM_TRY_BEGIN | 457 | COM_TRY_BEGIN |
446 | return _localProgress->SetRatioInfo(inSize, outSize); | 458 | return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize); |
447 | COM_TRY_END | 459 | COM_TRY_END |
448 | } | 460 | } |
449 | 461 | ||
450 | 462 | ||
451 | void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) | 463 | void CArchiveExtractCallback::CreateComplexDirectory( |
464 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath) | ||
452 | { | 465 | { |
453 | // we use (_item.IsDir) in this function | 466 | // we use (_item.IsDir) in this function |
454 | 467 | ||
@@ -480,7 +493,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat | |||
480 | const UString &s = dirPathParts[i]; | 493 | const UString &s = dirPathParts[i]; |
481 | fullPath += us2fs(s); | 494 | fullPath += us2fs(s); |
482 | 495 | ||
483 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir); | 496 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir); |
484 | 497 | ||
485 | if (fullPath.IsEmpty()) | 498 | if (fullPath.IsEmpty()) |
486 | { | 499 | { |
@@ -541,7 +554,7 @@ static void AddPathToMessage(UString &s, const FString &path) | |||
541 | s += fs2us(path); | 554 | s += fs2us(path); |
542 | } | 555 | } |
543 | 556 | ||
544 | HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) | 557 | HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) const |
545 | { | 558 | { |
546 | UString s (message); | 559 | UString s (message); |
547 | AddPathToMessage(s, path); | 560 | AddPathToMessage(s, path); |
@@ -549,7 +562,7 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt | |||
549 | } | 562 | } |
550 | 563 | ||
551 | 564 | ||
552 | HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) | 565 | HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const |
553 | { | 566 | { |
554 | UString s (message); | 567 | UString s (message); |
555 | if (errorCode != S_OK) | 568 | if (errorCode != S_OK) |
@@ -561,13 +574,13 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, | |||
561 | return _extractCallback2->MessageError(s); | 574 | return _extractCallback2->MessageError(s); |
562 | } | 575 | } |
563 | 576 | ||
564 | HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) | 577 | HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) const |
565 | { | 578 | { |
566 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 579 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); |
567 | return SendMessageError_with_Error(errorCode, message, path); | 580 | return SendMessageError_with_Error(errorCode, message, path); |
568 | } | 581 | } |
569 | 582 | ||
570 | HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) | 583 | HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const |
571 | { | 584 | { |
572 | UString s (message); | 585 | UString s (message); |
573 | if (errorCode != 0) | 586 | if (errorCode != 0) |
@@ -580,15 +593,32 @@ HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char | |||
580 | return _extractCallback2->MessageError(s); | 593 | return _extractCallback2->MessageError(s); |
581 | } | 594 | } |
582 | 595 | ||
596 | HRESULT CArchiveExtractCallback::SendMessageError2_with_LastError( | ||
597 | const char *message, const FString &path1, const FString &path2) const | ||
598 | { | ||
599 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | ||
600 | return SendMessageError2(errorCode, message, path1, path2); | ||
601 | } | ||
602 | |||
583 | #ifndef Z7_SFX | 603 | #ifndef Z7_SFX |
584 | 604 | ||
605 | Z7_CLASS_IMP_COM_1( | ||
606 | CGetProp | ||
607 | , IGetProp | ||
608 | ) | ||
609 | public: | ||
610 | UInt32 IndexInArc; | ||
611 | const CArc *Arc; | ||
612 | // UString BaseName; // relative path | ||
613 | }; | ||
614 | |||
585 | Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) | 615 | Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) |
586 | { | 616 | { |
587 | /* | 617 | /* |
588 | if (propID == kpidName) | 618 | if (propID == kpidBaseName) |
589 | { | 619 | { |
590 | COM_TRY_BEGIN | 620 | COM_TRY_BEGIN |
591 | NCOM::CPropVariant prop = Name; | 621 | NCOM::CPropVariant prop = BaseName; |
592 | prop.Detach(value); | 622 | prop.Detach(value); |
593 | return S_OK; | 623 | return S_OK; |
594 | COM_TRY_END | 624 | COM_TRY_END |
@@ -600,38 +630,25 @@ Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) | |||
600 | #endif // Z7_SFX | 630 | #endif // Z7_SFX |
601 | 631 | ||
602 | 632 | ||
603 | #ifdef SUPPORT_LINKS | ||
604 | |||
605 | static UString GetDirPrefixOf(const UString &src) | ||
606 | { | ||
607 | UString s (src); | ||
608 | if (!s.IsEmpty()) | ||
609 | { | ||
610 | if (IsPathSepar(s.Back())) | ||
611 | s.DeleteBack(); | ||
612 | int pos = s.ReverseFind_PathSepar(); | ||
613 | s.DeleteFrom((unsigned)(pos + 1)); | ||
614 | } | ||
615 | return s; | ||
616 | } | ||
617 | |||
618 | #endif // SUPPORT_LINKS | ||
619 | |||
620 | struct CLinkLevelsInfo | 633 | struct CLinkLevelsInfo |
621 | { | 634 | { |
622 | bool IsAbsolute; | 635 | bool IsAbsolute; |
636 | bool ParentDirDots_after_NonParent; | ||
623 | int LowLevel; | 637 | int LowLevel; |
624 | int FinalLevel; | 638 | int FinalLevel; |
625 | 639 | ||
626 | void Parse(const UString &path); | 640 | void Parse(const UString &path, bool isWSL); |
627 | }; | 641 | }; |
628 | 642 | ||
629 | void CLinkLevelsInfo::Parse(const UString &path) | 643 | void CLinkLevelsInfo::Parse(const UString &path, bool isWSL) |
630 | { | 644 | { |
631 | IsAbsolute = NName::IsAbsolutePath(path); | 645 | IsAbsolute = isWSL ? |
632 | 646 | IS_PATH_SEPAR(path[0]) : | |
647 | NName::IsAbsolutePath(path); | ||
633 | LowLevel = 0; | 648 | LowLevel = 0; |
634 | FinalLevel = 0; | 649 | FinalLevel = 0; |
650 | ParentDirDots_after_NonParent = false; | ||
651 | bool nonParentDir = false; | ||
635 | 652 | ||
636 | UStringVector parts; | 653 | UStringVector parts; |
637 | SplitPathToParts(path, parts); | 654 | SplitPathToParts(path, parts); |
@@ -646,32 +663,41 @@ void CLinkLevelsInfo::Parse(const UString &path) | |||
646 | IsAbsolute = true; | 663 | IsAbsolute = true; |
647 | continue; | 664 | continue; |
648 | } | 665 | } |
649 | if (s == L".") | 666 | if (s.IsEqualTo(".")) |
650 | continue; | 667 | continue; |
651 | if (s == L"..") | 668 | if (s.IsEqualTo("..")) |
652 | { | 669 | { |
670 | if (IsAbsolute || nonParentDir) | ||
671 | ParentDirDots_after_NonParent = true; | ||
653 | level--; | 672 | level--; |
654 | if (LowLevel > level) | 673 | if (LowLevel > level) |
655 | LowLevel = level; | 674 | LowLevel = level; |
656 | } | 675 | } |
657 | else | 676 | else |
677 | { | ||
678 | nonParentDir = true; | ||
658 | level++; | 679 | level++; |
680 | } | ||
659 | } | 681 | } |
660 | 682 | ||
661 | FinalLevel = level; | 683 | FinalLevel = level; |
662 | } | 684 | } |
663 | 685 | ||
664 | 686 | ||
665 | bool IsSafePath(const UString &path); | 687 | static bool IsSafePath(const UString &path, bool isWSL) |
666 | bool IsSafePath(const UString &path) | ||
667 | { | 688 | { |
668 | CLinkLevelsInfo levelsInfo; | 689 | CLinkLevelsInfo levelsInfo; |
669 | levelsInfo.Parse(path); | 690 | levelsInfo.Parse(path, isWSL); |
670 | return !levelsInfo.IsAbsolute | 691 | return !levelsInfo.IsAbsolute |
671 | && levelsInfo.LowLevel >= 0 | 692 | && levelsInfo.LowLevel >= 0 |
672 | && levelsInfo.FinalLevel > 0; | 693 | && levelsInfo.FinalLevel > 0; |
673 | } | 694 | } |
674 | 695 | ||
696 | bool IsSafePath(const UString &path); | ||
697 | bool IsSafePath(const UString &path) | ||
698 | { | ||
699 | return IsSafePath(path, false); // isWSL | ||
700 | } | ||
675 | 701 | ||
676 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); | 702 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); |
677 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) | 703 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) |
@@ -787,159 +813,113 @@ HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) | |||
787 | 813 | ||
788 | HRESULT CArchiveExtractCallback::ReadLink() | 814 | HRESULT CArchiveExtractCallback::ReadLink() |
789 | { | 815 | { |
790 | IInArchive *archive = _arc->Archive; | 816 | IInArchive * const archive = _arc->Archive; |
791 | const UInt32 index = _index; | 817 | const UInt32 index = _index; |
792 | _link.Clear(); | 818 | // _link.Clear(); // _link.Clear() was called already. |
793 | |||
794 | { | 819 | { |
795 | NCOM::CPropVariant prop; | 820 | NCOM::CPropVariant prop; |
796 | RINOK(archive->GetProperty(index, kpidHardLink, &prop)) | 821 | RINOK(archive->GetProperty(index, kpidHardLink, &prop)) |
797 | if (prop.vt == VT_BSTR) | 822 | if (prop.vt == VT_BSTR) |
798 | { | 823 | { |
799 | _link.isHardLink = true; | 824 | _link.LinkType = k_LinkType_HardLink; |
800 | // _link.isCopyLink = false; | ||
801 | _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive | 825 | _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive |
802 | _link.linkPath.SetFromBstr(prop.bstrVal); | 826 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
827 | // 7-Zip 24-: tar handler returned original path (with linux slash in most case) | ||
828 | // 7-Zip 24-: rar5 handler returned path with system slash. | ||
829 | // 7-Zip 25+: tar/rar5 handlers return linux path in most cases. | ||
803 | } | 830 | } |
804 | else if (prop.vt != VT_EMPTY) | 831 | else if (prop.vt != VT_EMPTY) |
805 | return E_FAIL; | 832 | return E_FAIL; |
806 | } | 833 | } |
807 | |||
808 | /* | 834 | /* |
809 | { | 835 | { |
810 | NCOM::CPropVariant prop; | 836 | NCOM::CPropVariant prop; |
811 | RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); | 837 | RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); |
812 | if (prop.vt == VT_BSTR) | 838 | if (prop.vt == VT_BSTR) |
813 | { | 839 | { |
814 | _link.isHardLink = false; | 840 | _link.LinkType = k_LinkType_CopyLink; |
815 | _link.isCopyLink = true; | ||
816 | _link.isRelative = false; // RAR5: copy links are from root folder of archive | 841 | _link.isRelative = false; // RAR5: copy links are from root folder of archive |
817 | _link.linkPath.SetFromBstr(prop.bstrVal); | 842 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
818 | } | 843 | } |
819 | else if (prop.vt != VT_EMPTY) | 844 | else if (prop.vt != VT_EMPTY) |
820 | return E_FAIL; | 845 | return E_FAIL; |
821 | } | 846 | } |
822 | */ | 847 | */ |
823 | |||
824 | { | 848 | { |
825 | NCOM::CPropVariant prop; | 849 | NCOM::CPropVariant prop; |
826 | RINOK(archive->GetProperty(index, kpidSymLink, &prop)) | 850 | RINOK(archive->GetProperty(index, kpidSymLink, &prop)) |
827 | if (prop.vt == VT_BSTR) | 851 | if (prop.vt == VT_BSTR) |
828 | { | 852 | { |
829 | _link.isHardLink = false; | 853 | _link.LinkType = k_LinkType_PureSymLink; |
830 | // _link.isCopyLink = false; | 854 | _link.isRelative = true; // RAR5, TAR: symbolic links are relative by default |
831 | _link.isRelative = true; // RAR5, TAR: symbolic links can be relative | 855 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
832 | _link.linkPath.SetFromBstr(prop.bstrVal); | 856 | // 7-Zip 24-: (tar, cpio, xar, ext, iso) handlers returned returned original path (with linux slash in most case) |
857 | // 7-Zip 24-: rar5 handler returned path with system slash. | ||
858 | // 7-Zip 25+: all handlers return linux path in most cases. | ||
833 | } | 859 | } |
834 | else if (prop.vt != VT_EMPTY) | 860 | else if (prop.vt != VT_EMPTY) |
835 | return E_FAIL; | 861 | return E_FAIL; |
836 | } | 862 | } |
837 | 863 | ||
838 | NtReparse_Data = NULL; | 864 | // linux path separator in (_link.LinkPath) is expected for most cases, |
839 | NtReparse_Size = 0; | 865 | // if new handler code is used, and if data in archive is correct. |
840 | 866 | // NtReparse_Data = NULL; | |
841 | if (_link.linkPath.IsEmpty() && _arc->GetRawProps) | 867 | // NtReparse_Size = 0; |
868 | if (!_link.LinkPath.IsEmpty()) | ||
869 | { | ||
870 | REPLACE_SLASHES_from_Linux_to_Sys(_link.LinkPath) | ||
871 | } | ||
872 | else if (_arc->GetRawProps) | ||
842 | { | 873 | { |
843 | const void *data; | 874 | const void *data; |
844 | UInt32 dataSize; | 875 | UInt32 dataSize, propType; |
845 | UInt32 propType; | 876 | if (_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType) == S_OK |
846 | 877 | // && dataSize == 1234567 // for debug: unpacking without reparse | |
847 | _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); | 878 | && dataSize) |
848 | |||
849 | // if (dataSize == 1234567) // for debug: unpacking without reparse | ||
850 | if (dataSize != 0) | ||
851 | { | 879 | { |
852 | if (propType != NPropDataType::kRaw) | 880 | if (propType != NPropDataType::kRaw) |
853 | return E_FAIL; | 881 | return E_FAIL; |
854 | |||
855 | // 21.06: we need kpidNtReparse in linux for wim archives created in Windows | 882 | // 21.06: we need kpidNtReparse in linux for wim archives created in Windows |
856 | // #ifdef _WIN32 | 883 | // NtReparse_Data = data; |
857 | 884 | // NtReparse_Size = dataSize; | |
858 | NtReparse_Data = data; | 885 | // we ignore error code here, if there is failure of parsing: |
859 | NtReparse_Size = dataSize; | 886 | _link.Parse_from_WindowsReparseData((const Byte *)data, dataSize); |
860 | |||
861 | CReparseAttr reparse; | ||
862 | bool isOkReparse = reparse.Parse((const Byte *)data, dataSize); | ||
863 | if (isOkReparse) | ||
864 | { | ||
865 | _link.isHardLink = false; | ||
866 | // _link.isCopyLink = false; | ||
867 | _link.linkPath = reparse.GetPath(); | ||
868 | _link.isJunction = reparse.IsMountPoint(); | ||
869 | |||
870 | if (reparse.IsSymLink_WSL()) | ||
871 | { | ||
872 | _link.isWSL = true; | ||
873 | _link.isRelative = reparse.IsRelative_WSL(); | ||
874 | } | ||
875 | else | ||
876 | _link.isRelative = reparse.IsRelative_Win(); | ||
877 | |||
878 | // const AString s = GetAnsiString(_link.linkPath); | ||
879 | // printf("\n_link.linkPath: %s\n", s.Ptr()); | ||
880 | |||
881 | #ifndef _WIN32 | ||
882 | _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | ||
883 | #endif | ||
884 | } | ||
885 | // #endif | ||
886 | } | 887 | } |
887 | } | 888 | } |
888 | 889 | ||
889 | if (_link.linkPath.IsEmpty()) | 890 | if (_link.LinkPath.IsEmpty()) |
890 | return S_OK; | 891 | return S_OK; |
891 | 892 | // (_link.LinkPath) uses system path separator. | |
893 | // windows: (_link.LinkPath) doesn't contain linux separator (slash). | ||
892 | { | 894 | { |
893 | #ifdef _WIN32 | 895 | // _link.LinkPath = "\\??\\r:\\1\\2"; // for debug |
894 | _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); | 896 | // rar5+ returns kpidSymLink absolute link path with "\??\" prefix. |
895 | #endif | 897 | // we normalize such prefix: |
896 | 898 | if (_link.LinkPath.IsPrefixedBy(STRING_PATH_SEPARATOR "??" STRING_PATH_SEPARATOR)) | |
897 | // rar5 uses "\??\" prefix for absolute links | ||
898 | if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) | ||
899 | { | ||
900 | _link.isRelative = false; | ||
901 | _link.linkPath.DeleteFrontal(4); | ||
902 | } | ||
903 | |||
904 | for (;;) | ||
905 | // while (NName::IsAbsolutePath(linkPath)) | ||
906 | { | 899 | { |
907 | unsigned n = NName::GetRootPrefixSize(_link.linkPath); | ||
908 | if (n == 0) | ||
909 | break; | ||
910 | _link.isRelative = false; | 900 | _link.isRelative = false; |
911 | _link.linkPath.DeleteFrontal(n); | 901 | // we normalize prefix from "\??\" to "\\?\": |
912 | } | 902 | _link.LinkPath.ReplaceOneCharAtPos(1, WCHAR_PATH_SEPARATOR); |
913 | } | 903 | _link.isWindowsPath = true; |
914 | 904 | if (_link.LinkPath.IsPrefixedBy_Ascii_NoCase( | |
915 | if (_link.linkPath.IsEmpty()) | 905 | STRING_PATH_SEPARATOR |
916 | return S_OK; | 906 | STRING_PATH_SEPARATOR "?" |
917 | 907 | STRING_PATH_SEPARATOR "UNC" | |
918 | if (!_link.isRelative && _removePathParts.Size() != 0) | 908 | STRING_PATH_SEPARATOR)) |
919 | { | ||
920 | UStringVector pathParts; | ||
921 | SplitPathToParts(_link.linkPath, pathParts); | ||
922 | bool badPrefix = false; | ||
923 | FOR_VECTOR (i, _removePathParts) | ||
924 | { | ||
925 | if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) | ||
926 | { | 909 | { |
927 | badPrefix = true; | 910 | // we normalize prefix from "\\?\UNC\path" to "\\path": |
928 | break; | 911 | _link.LinkPath.DeleteFrontal(6); |
912 | _link.LinkPath.ReplaceOneCharAtPos(0, WCHAR_PATH_SEPARATOR); | ||
913 | } | ||
914 | else | ||
915 | { | ||
916 | const unsigned k_prefix_Size = 4; | ||
917 | if (NName::IsDrivePath(_link.LinkPath.Ptr(k_prefix_Size))) | ||
918 | _link.LinkPath.DeleteFrontal(k_prefix_Size); | ||
929 | } | 919 | } |
930 | } | 920 | } |
931 | if (!badPrefix) | ||
932 | pathParts.DeleteFrontal(_removePathParts.Size()); | ||
933 | _link.linkPath = MakePathFromParts(pathParts); | ||
934 | } | ||
935 | |||
936 | /* | ||
937 | if (!_link.linkPath.IsEmpty()) | ||
938 | { | ||
939 | printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr()); | ||
940 | } | 921 | } |
941 | */ | 922 | _link.Normalize_to_RelativeSafe(_removePathParts); |
942 | |||
943 | return S_OK; | 923 | return S_OK; |
944 | } | 924 | } |
945 | 925 | ||
@@ -949,7 +929,7 @@ HRESULT CArchiveExtractCallback::ReadLink() | |||
949 | #ifndef _WIN32 | 929 | #ifndef _WIN32 |
950 | 930 | ||
951 | static HRESULT GetOwner(IInArchive *archive, | 931 | static HRESULT GetOwner(IInArchive *archive, |
952 | UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res) | 932 | UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res) |
953 | { | 933 | { |
954 | { | 934 | { |
955 | NWindows::NCOM::CPropVariant prop; | 935 | NWindows::NCOM::CPropVariant prop; |
@@ -957,7 +937,7 @@ static HRESULT GetOwner(IInArchive *archive, | |||
957 | if (prop.vt == VT_UI4) | 937 | if (prop.vt == VT_UI4) |
958 | { | 938 | { |
959 | res.Id_Defined = true; | 939 | res.Id_Defined = true; |
960 | res.Id = prop.ulVal; // for debug | 940 | res.Id = prop.ulVal; |
961 | // res.Id++; // for debug | 941 | // res.Id++; // for debug |
962 | // if (pidId == kpidGroupId) res.Id += 7; // for debug | 942 | // if (pidId == kpidGroupId) res.Id += 7; // for debug |
963 | // res.Id = 0; // for debug | 943 | // res.Id = 0; // for debug |
@@ -989,7 +969,7 @@ static HRESULT GetOwner(IInArchive *archive, | |||
989 | 969 | ||
990 | HRESULT CArchiveExtractCallback::Read_fi_Props() | 970 | HRESULT CArchiveExtractCallback::Read_fi_Props() |
991 | { | 971 | { |
992 | IInArchive *archive = _arc->Archive; | 972 | IInArchive * const archive = _arc->Archive; |
993 | const UInt32 index = _index; | 973 | const UInt32 index = _index; |
994 | 974 | ||
995 | _fi.Attrib_Defined = false; | 975 | _fi.Attrib_Defined = false; |
@@ -1081,35 +1061,35 @@ void CArchiveExtractCallback::CorrectPathParts() | |||
1081 | } | 1061 | } |
1082 | 1062 | ||
1083 | 1063 | ||
1084 | void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt) | 1064 | static void GetFiTimesCAM(const CProcessedFileInfo &fi, CFiTimesCAM &pt, const CArc &arc) |
1085 | { | 1065 | { |
1086 | pt.CTime_Defined = false; | 1066 | pt.CTime_Defined = false; |
1087 | pt.ATime_Defined = false; | 1067 | pt.ATime_Defined = false; |
1088 | pt.MTime_Defined = false; | 1068 | pt.MTime_Defined = false; |
1089 | 1069 | ||
1090 | if (Write_MTime) | 1070 | // if (Write_MTime) |
1091 | { | 1071 | { |
1092 | if (_fi.MTime.Def) | 1072 | if (fi.MTime.Def) |
1093 | { | 1073 | { |
1094 | _fi.MTime.Write_To_FiTime(pt.MTime); | 1074 | fi.MTime.Write_To_FiTime(pt.MTime); |
1095 | pt.MTime_Defined = true; | 1075 | pt.MTime_Defined = true; |
1096 | } | 1076 | } |
1097 | else if (_arc->MTime.Def) | 1077 | else if (arc.MTime.Def) |
1098 | { | 1078 | { |
1099 | _arc->MTime.Write_To_FiTime(pt.MTime); | 1079 | arc.MTime.Write_To_FiTime(pt.MTime); |
1100 | pt.MTime_Defined = true; | 1080 | pt.MTime_Defined = true; |
1101 | } | 1081 | } |
1102 | } | 1082 | } |
1103 | 1083 | ||
1104 | if (Write_CTime && _fi.CTime.Def) | 1084 | if (/* Write_CTime && */ fi.CTime.Def) |
1105 | { | 1085 | { |
1106 | _fi.CTime.Write_To_FiTime(pt.CTime); | 1086 | fi.CTime.Write_To_FiTime(pt.CTime); |
1107 | pt.CTime_Defined = true; | 1087 | pt.CTime_Defined = true; |
1108 | } | 1088 | } |
1109 | 1089 | ||
1110 | if (Write_ATime && _fi.ATime.Def) | 1090 | if (/* Write_ATime && */ fi.ATime.Def) |
1111 | { | 1091 | { |
1112 | _fi.ATime.Write_To_FiTime(pt.ATime); | 1092 | fi.ATime.Write_To_FiTime(pt.ATime); |
1113 | pt.ATime_Defined = true; | 1093 | pt.ATime_Defined = true; |
1114 | } | 1094 | } |
1115 | } | 1095 | } |
@@ -1120,6 +1100,7 @@ void CArchiveExtractCallback::CreateFolders() | |||
1120 | // 21.04 : we don't change original (_item.PathParts) here | 1100 | // 21.04 : we don't change original (_item.PathParts) here |
1121 | UStringVector pathParts = _item.PathParts; | 1101 | UStringVector pathParts = _item.PathParts; |
1122 | 1102 | ||
1103 | bool isFinal = true; | ||
1123 | // bool is_DirOp = false; | 1104 | // bool is_DirOp = false; |
1124 | if (!pathParts.IsEmpty()) | 1105 | if (!pathParts.IsEmpty()) |
1125 | { | 1106 | { |
@@ -1129,12 +1110,15 @@ void CArchiveExtractCallback::CreateFolders() | |||
1129 | but if we create dir item here, it's not problem. */ | 1110 | but if we create dir item here, it's not problem. */ |
1130 | if (!_item.IsDir | 1111 | if (!_item.IsDir |
1131 | #ifdef SUPPORT_LINKS | 1112 | #ifdef SUPPORT_LINKS |
1132 | #ifndef WIN32 | 1113 | // #ifndef WIN32 |
1133 | || !_link.linkPath.IsEmpty() | 1114 | || !_link.LinkPath.IsEmpty() |
1134 | #endif | 1115 | // #endif |
1135 | #endif | 1116 | #endif |
1136 | ) | 1117 | ) |
1118 | { | ||
1137 | pathParts.DeleteBack(); | 1119 | pathParts.DeleteBack(); |
1120 | isFinal = false; // last path part was excluded | ||
1121 | } | ||
1138 | // else is_DirOp = true; | 1122 | // else is_DirOp = true; |
1139 | } | 1123 | } |
1140 | 1124 | ||
@@ -1158,7 +1142,7 @@ void CArchiveExtractCallback::CreateFolders() | |||
1158 | */ | 1142 | */ |
1159 | 1143 | ||
1160 | FString fullPathNew; | 1144 | FString fullPathNew; |
1161 | CreateComplexDirectory(pathParts, fullPathNew); | 1145 | CreateComplexDirectory(pathParts, isFinal, fullPathNew); |
1162 | 1146 | ||
1163 | /* | 1147 | /* |
1164 | if (is_DirOp) | 1148 | if (is_DirOp) |
@@ -1179,12 +1163,12 @@ void CArchiveExtractCallback::CreateFolders() | |||
1179 | return; | 1163 | return; |
1180 | 1164 | ||
1181 | CDirPathTime pt; | 1165 | CDirPathTime pt; |
1182 | GetFiTimesCAM(pt); | 1166 | GetFiTimesCAM(_fi, pt, *_arc); |
1183 | 1167 | ||
1184 | if (pt.IsSomeTimeDefined()) | 1168 | if (pt.IsSomeTimeDefined()) |
1185 | { | 1169 | { |
1186 | pt.Path = fullPathNew; | 1170 | pt.Path = fullPathNew; |
1187 | pt.SetDirTime(); | 1171 | pt.SetDirTime_to_FS_2(); |
1188 | _extractedFolders.Add(pt); | 1172 | _extractedFolders.Add(pt); |
1189 | } | 1173 | } |
1190 | } | 1174 | } |
@@ -1269,8 +1253,7 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1269 | // MyMoveFile can rename folders. So it's OK to use it for folders too | 1253 | // MyMoveFile can rename folders. So it's OK to use it for folders too |
1270 | if (!MyMoveFile(fullProcessedPath, existPath)) | 1254 | if (!MyMoveFile(fullProcessedPath, existPath)) |
1271 | { | 1255 | { |
1272 | HRESULT errorCode = GetLastError_noZero_HRESULT(); | 1256 | RINOK(SendMessageError2_with_LastError(kCantRenameFile, existPath, fullProcessedPath)) |
1273 | RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath)) | ||
1274 | return E_FAIL; | 1257 | return E_FAIL; |
1275 | } | 1258 | } |
1276 | } | 1259 | } |
@@ -1302,7 +1285,7 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1302 | { | 1285 | { |
1303 | #if defined(_WIN32) && !defined(UNDER_CE) | 1286 | #if defined(_WIN32) && !defined(UNDER_CE) |
1304 | // we need to clear READ-ONLY of parent before creating alt stream | 1287 | // we need to clear READ-ONLY of parent before creating alt stream |
1305 | int colonPos = NName::FindAltStreamColon(fullProcessedPath); | 1288 | const int colonPos = NName::FindAltStreamColon(fullProcessedPath); |
1306 | if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) | 1289 | if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) |
1307 | { | 1290 | { |
1308 | FString parentFsPath (fullProcessedPath); | 1291 | FString parentFsPath (fullProcessedPath); |
@@ -1311,7 +1294,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1311 | if (parentFi.Find(parentFsPath)) | 1294 | if (parentFi.Find(parentFsPath)) |
1312 | { | 1295 | { |
1313 | if (parentFi.IsReadOnly()) | 1296 | if (parentFi.IsReadOnly()) |
1297 | { | ||
1298 | _altStream_NeedRestore_Attrib_for_parentFsPath = parentFsPath; | ||
1299 | _altStream_NeedRestore_AttribVal = parentFi.Attrib; | ||
1314 | SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); | 1300 | SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); |
1301 | } | ||
1315 | } | 1302 | } |
1316 | } | 1303 | } |
1317 | #endif // defined(_WIN32) && !defined(UNDER_CE) | 1304 | #endif // defined(_WIN32) && !defined(UNDER_CE) |
@@ -1323,9 +1310,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1323 | 1310 | ||
1324 | 1311 | ||
1325 | 1312 | ||
1326 | 1313 | /* | |
1327 | 1314 | return: | |
1328 | 1315 | needExit = false: caller will use (outStreamLoc) and _hashStreamSpec | |
1316 | needExit = true : caller will not use (outStreamLoc) and _hashStreamSpec. | ||
1317 | */ | ||
1329 | HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit) | 1318 | HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit) |
1330 | { | 1319 | { |
1331 | needExit = true; | 1320 | needExit = true; |
@@ -1333,7 +1322,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1333 | RINOK(Read_fi_Props()) | 1322 | RINOK(Read_fi_Props()) |
1334 | 1323 | ||
1335 | #ifdef SUPPORT_LINKS | 1324 | #ifdef SUPPORT_LINKS |
1336 | IInArchive *archive = _arc->Archive; | 1325 | IInArchive * const archive = _arc->Archive; |
1337 | #endif | 1326 | #endif |
1338 | 1327 | ||
1339 | const UInt32 index = _index; | 1328 | const UInt32 index = _index; |
@@ -1379,7 +1368,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1379 | if (isAnti) | 1368 | if (isAnti) |
1380 | RemoveDir(_diskFilePath); | 1369 | RemoveDir(_diskFilePath); |
1381 | #ifdef SUPPORT_LINKS | 1370 | #ifdef SUPPORT_LINKS |
1382 | if (_link.linkPath.IsEmpty()) | 1371 | if (_link.LinkPath.IsEmpty()) |
1383 | #endif | 1372 | #endif |
1384 | { | 1373 | { |
1385 | if (!isAnti) | 1374 | if (!isAnti) |
@@ -1408,18 +1397,21 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1408 | 1397 | ||
1409 | #ifdef SUPPORT_LINKS | 1398 | #ifdef SUPPORT_LINKS |
1410 | 1399 | ||
1411 | if (!_link.linkPath.IsEmpty()) | 1400 | if (!_link.LinkPath.IsEmpty()) |
1412 | { | 1401 | { |
1413 | #ifndef UNDER_CE | 1402 | #ifndef UNDER_CE |
1414 | { | 1403 | { |
1415 | bool linkWasSet = false; | 1404 | bool linkWasSet = false; |
1416 | RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)) | 1405 | RINOK(SetLink(fullProcessedPath, _link, linkWasSet)) |
1406 | /* | ||
1407 | // we don't set attributes for placeholder. | ||
1417 | if (linkWasSet) | 1408 | if (linkWasSet) |
1418 | { | 1409 | { |
1419 | _isSymLinkCreated = _link.IsSymLink(); | 1410 | _isSymLinkCreated = _link.Is_AnySymLink(); |
1420 | SetAttrib(); | 1411 | SetAttrib(); |
1421 | // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); | 1412 | // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); |
1422 | } | 1413 | } |
1414 | */ | ||
1423 | } | 1415 | } |
1424 | #endif // UNDER_CE | 1416 | #endif // UNDER_CE |
1425 | 1417 | ||
@@ -1445,16 +1437,17 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1445 | hl = fullProcessedPath; | 1437 | hl = fullProcessedPath; |
1446 | else | 1438 | else |
1447 | { | 1439 | { |
1448 | if (!MyCreateHardLink(fullProcessedPath, hl)) | 1440 | bool link_was_Created = false; |
1449 | { | 1441 | RINOK(CreateHardLink2(fullProcessedPath, hl, link_was_Created)) |
1450 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 1442 | if (!link_was_Created) |
1451 | RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)) | ||
1452 | return S_OK; | 1443 | return S_OK; |
1453 | } | ||
1454 | |||
1455 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); | 1444 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); |
1456 | // _needSetAttrib = true; // do we need to set attribute ? | 1445 | // _needSetAttrib = true; // do we need to set attribute ? |
1457 | SetAttrib(); | 1446 | SetAttrib(); |
1447 | /* if we set (needExit = false) here, _hashStreamSpec will be used, | ||
1448 | and hash will be calulated for all hard links files (it's slower). | ||
1449 | But "Test" operation also calculates hashes. | ||
1450 | */ | ||
1458 | needExit = false; | 1451 | needExit = false; |
1459 | return S_OK; | 1452 | return S_OK; |
1460 | } | 1453 | } |
@@ -1483,7 +1476,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1483 | 1476 | ||
1484 | bool is_SymLink_in_Data = false; | 1477 | bool is_SymLink_in_Data = false; |
1485 | 1478 | ||
1486 | if (_curSize_Defined && _curSize > 0 && _curSize < (1 << 12)) | 1479 | if (_curSize_Defined && _curSize && _curSize < k_LinkDataSize_LIMIT) |
1487 | { | 1480 | { |
1488 | if (_fi.IsLinuxSymLink()) | 1481 | if (_fi.IsLinuxSymLink()) |
1489 | { | 1482 | { |
@@ -1505,7 +1498,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1505 | _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); | 1498 | _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); |
1506 | outStreamLoc = _bufPtrSeqOutStream; | 1499 | outStreamLoc = _bufPtrSeqOutStream; |
1507 | } | 1500 | } |
1508 | else // not reprase | 1501 | else // not reparse |
1509 | { | 1502 | { |
1510 | if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12)) | 1503 | if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12)) |
1511 | { | 1504 | { |
@@ -1560,7 +1553,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1560 | RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL)) | 1553 | RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL)) |
1561 | } | 1554 | } |
1562 | outStreamLoc = outFileStream_Loc; | 1555 | outStreamLoc = outFileStream_Loc; |
1563 | } // if not reprase | 1556 | } // if not reparse |
1564 | 1557 | ||
1565 | _outFileStream = outFileStream_Loc; | 1558 | _outFileStream = outFileStream_Loc; |
1566 | 1559 | ||
@@ -1607,37 +1600,36 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1607 | _bufPtrSeqOutStream.Release(); | 1600 | _bufPtrSeqOutStream.Release(); |
1608 | 1601 | ||
1609 | _encrypted = false; | 1602 | _encrypted = false; |
1610 | _position = 0; | ||
1611 | _isSplit = false; | 1603 | _isSplit = false; |
1612 | |||
1613 | _curSize = 0; | ||
1614 | _curSize_Defined = false; | 1604 | _curSize_Defined = false; |
1615 | _fileLength_WasSet = false; | 1605 | _fileLength_WasSet = false; |
1616 | _fileLength_that_WasSet = 0; | ||
1617 | _index = index; | ||
1618 | |||
1619 | _diskFilePath.Empty(); | ||
1620 | |||
1621 | _isRenamed = false; | 1606 | _isRenamed = false; |
1622 | |||
1623 | // _fi.Clear(); | 1607 | // _fi.Clear(); |
1624 | 1608 | _extractMode = false; | |
1625 | // _is_SymLink_in_Data = false; | ||
1626 | _is_SymLink_in_Data_Linux = false; | 1609 | _is_SymLink_in_Data_Linux = false; |
1627 | |||
1628 | _needSetAttrib = false; | 1610 | _needSetAttrib = false; |
1629 | _isSymLinkCreated = false; | 1611 | _isSymLinkCreated = false; |
1630 | _itemFailure = false; | 1612 | _itemFailure = false; |
1631 | |||
1632 | _some_pathParts_wereRemoved = false; | 1613 | _some_pathParts_wereRemoved = false; |
1633 | // _op_WasReported = false; | 1614 | // _op_WasReported = false; |
1634 | 1615 | ||
1616 | _position = 0; | ||
1617 | _curSize = 0; | ||
1618 | _fileLength_that_WasSet = 0; | ||
1619 | _index = index; | ||
1620 | |||
1621 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
1622 | _altStream_NeedRestore_AttribVal = 0; | ||
1623 | _altStream_NeedRestore_Attrib_for_parentFsPath.Empty(); | ||
1624 | #endif | ||
1625 | |||
1626 | _diskFilePath.Empty(); | ||
1627 | |||
1635 | #ifdef SUPPORT_LINKS | 1628 | #ifdef SUPPORT_LINKS |
1636 | // _copyFile_Path.Empty(); | 1629 | // _copyFile_Path.Empty(); |
1637 | _link.Clear(); | 1630 | _link.Clear(); |
1638 | #endif | 1631 | #endif |
1639 | 1632 | ||
1640 | _extractMode = false; | ||
1641 | 1633 | ||
1642 | switch (askExtractMode) | 1634 | switch (askExtractMode) |
1643 | { | 1635 | { |
@@ -1653,7 +1645,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1653 | } | 1645 | } |
1654 | 1646 | ||
1655 | 1647 | ||
1656 | IInArchive *archive = _arc->Archive; | 1648 | IInArchive * const archive = _arc->Archive; |
1657 | 1649 | ||
1658 | RINOK(GetItem(index)) | 1650 | RINOK(GetItem(index)) |
1659 | 1651 | ||
@@ -1669,10 +1661,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1669 | } | 1661 | } |
1670 | } | 1662 | } |
1671 | 1663 | ||
1672 | #ifdef SUPPORT_LINKS | 1664 | #ifdef SUPPORT_LINKS |
1673 | RINOK(ReadLink()) | 1665 | RINOK(ReadLink()) |
1674 | #endif // SUPPORT_LINKS | 1666 | #endif |
1675 | |||
1676 | 1667 | ||
1677 | RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)) | 1668 | RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)) |
1678 | 1669 | ||
@@ -1692,6 +1683,19 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1692 | return S_OK; | 1683 | return S_OK; |
1693 | } | 1684 | } |
1694 | 1685 | ||
1686 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | ||
1687 | if (askExtractMode == NArchive::NExtract::NAskMode::kExtract | ||
1688 | && !_testMode | ||
1689 | && _item.IsAltStream | ||
1690 | && ZoneBuf.Size() != 0 | ||
1691 | && Is_ZoneId_StreamName(_item.AltStreamName)) | ||
1692 | if (ZoneMode != NExtract::NZoneIdMode::kOffice | ||
1693 | || _item.PathParts.IsEmpty() | ||
1694 | || FindExt2(kOfficeExtensions, _item.PathParts.Back())) | ||
1695 | return S_OK; | ||
1696 | #endif | ||
1697 | |||
1698 | |||
1695 | #ifndef Z7_SFX | 1699 | #ifndef Z7_SFX |
1696 | if (_use_baseParentFolder_mode) | 1700 | if (_use_baseParentFolder_mode) |
1697 | { | 1701 | { |
@@ -1810,15 +1814,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1810 | 1814 | ||
1811 | if (ExtractToStreamCallback) | 1815 | if (ExtractToStreamCallback) |
1812 | { | 1816 | { |
1813 | if (!GetProp) | 1817 | CMyComPtr2_Create<IGetProp, CGetProp> GetProp; |
1814 | { | 1818 | GetProp->Arc = _arc; |
1815 | GetProp_Spec = new CGetProp; | 1819 | GetProp->IndexInArc = index; |
1816 | GetProp = GetProp_Spec; | ||
1817 | } | ||
1818 | GetProp_Spec->Arc = _arc; | ||
1819 | GetProp_Spec->IndexInArc = index; | ||
1820 | UString name (MakePathFromParts(pathParts)); | 1820 | UString name (MakePathFromParts(pathParts)); |
1821 | 1821 | // GetProp->BaseName = name; | |
1822 | #ifdef SUPPORT_ALT_STREAMS | 1822 | #ifdef SUPPORT_ALT_STREAMS |
1823 | if (_item.IsAltStream) | 1823 | if (_item.IsAltStream) |
1824 | { | 1824 | { |
@@ -1972,7 +1972,7 @@ HRESULT CArchiveExtractCallback::CloseFile() | |||
1972 | #endif | 1972 | #endif |
1973 | 1973 | ||
1974 | CFiTimesCAM t; | 1974 | CFiTimesCAM t; |
1975 | GetFiTimesCAM(t); | 1975 | GetFiTimesCAM(_fi, t, *_arc); |
1976 | 1976 | ||
1977 | // #ifdef _WIN32 | 1977 | // #ifdef _WIN32 |
1978 | if (t.IsSomeTimeDefined()) | 1978 | if (t.IsSomeTimeDefined()) |
@@ -1984,94 +1984,290 @@ HRESULT CArchiveExtractCallback::CloseFile() | |||
1984 | 1984 | ||
1985 | RINOK(_outFileStreamSpec->Close()) | 1985 | RINOK(_outFileStreamSpec->Close()) |
1986 | _outFileStream.Release(); | 1986 | _outFileStream.Release(); |
1987 | |||
1988 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
1989 | if (!_altStream_NeedRestore_Attrib_for_parentFsPath.IsEmpty()) | ||
1990 | { | ||
1991 | SetFileAttrib(_altStream_NeedRestore_Attrib_for_parentFsPath, _altStream_NeedRestore_AttribVal); | ||
1992 | _altStream_NeedRestore_Attrib_for_parentFsPath.Empty(); | ||
1993 | } | ||
1994 | #endif | ||
1995 | |||
1987 | return hres; | 1996 | return hres; |
1988 | } | 1997 | } |
1989 | 1998 | ||
1990 | 1999 | ||
1991 | #ifdef SUPPORT_LINKS | 2000 | #ifdef SUPPORT_LINKS |
1992 | 2001 | ||
2002 | static bool CheckLinkPath_in_FS_for_pathParts(const FString &path, const UStringVector &v) | ||
2003 | { | ||
2004 | FString path2 = path; | ||
2005 | FOR_VECTOR (i, v) | ||
2006 | { | ||
2007 | // if (i == v.Size() - 1) path = path2; // we don't need last part in returned path | ||
2008 | path2 += us2fs(v[i]); | ||
2009 | NFind::CFileInfo fi; | ||
2010 | // printf("\nCheckLinkPath_in_FS_for_pathParts(): %s\n", GetOemString(path2).Ptr()); | ||
2011 | if (fi.Find(path2) && fi.IsOsSymLink()) | ||
2012 | return false; | ||
2013 | path2.Add_PathSepar(); | ||
2014 | } | ||
2015 | return true; | ||
2016 | } | ||
2017 | |||
2018 | /* | ||
2019 | link.isRelative / relative_item_PathPrefix | ||
2020 | false / empty | ||
2021 | true / item path without last part | ||
2022 | */ | ||
2023 | static bool CheckLinkPath_in_FS( | ||
2024 | const FString &pathPrefix_in_FS, | ||
2025 | const CPostLink &postLink, | ||
2026 | const UString &relative_item_PathPrefix) | ||
2027 | { | ||
2028 | const CLinkInfo &link = postLink.LinkInfo; | ||
2029 | if (postLink.item_PathParts.IsEmpty() || link.LinkPath.IsEmpty()) | ||
2030 | return false; | ||
2031 | FString path; | ||
2032 | { | ||
2033 | const UString &s = postLink.item_PathParts[0]; | ||
2034 | if (!s.IsEmpty() && !NName::IsAbsolutePath(s)) | ||
2035 | path = pathPrefix_in_FS; // item_PathParts is relative. So we use absolutre prefix | ||
2036 | } | ||
2037 | if (!CheckLinkPath_in_FS_for_pathParts(path, postLink.item_PathParts)) | ||
2038 | return false; | ||
2039 | path += us2fs(relative_item_PathPrefix); | ||
2040 | UStringVector v; | ||
2041 | SplitPathToParts(link.LinkPath, v); | ||
2042 | // we check target paths: | ||
2043 | return CheckLinkPath_in_FS_for_pathParts(path, v); | ||
2044 | } | ||
1993 | 2045 | ||
1994 | HRESULT CArchiveExtractCallback::SetFromLinkPath( | 2046 | static const unsigned k_DangLevel_MAX_for_Link_over_Link = 9; |
1995 | const FString &fullProcessedPath, | 2047 | |
1996 | const CLinkInfo &linkInfo, | 2048 | HRESULT CArchiveExtractCallback::CreateHardLink2( |
1997 | bool &linkWasSet) | 2049 | const FString &newFilePath, const FString &existFilePath, bool &link_was_Created) const |
2050 | { | ||
2051 | link_was_Created = false; | ||
2052 | if (_ntOptions.SymLinks_DangerousLevel <= k_DangLevel_MAX_for_Link_over_Link) | ||
2053 | { | ||
2054 | NFind::CFileInfo fi; | ||
2055 | if (fi.Find(existFilePath) && fi.IsOsSymLink()) | ||
2056 | return SendMessageError2(0, k_HardLink_to_SymLink_Ignored, newFilePath, existFilePath); | ||
2057 | } | ||
2058 | if (!MyCreateHardLink(newFilePath, existFilePath)) | ||
2059 | return SendMessageError2_with_LastError(kCantCreateHardLink, newFilePath, existFilePath); | ||
2060 | link_was_Created = true; | ||
2061 | return S_OK; | ||
2062 | } | ||
2063 | |||
2064 | |||
2065 | |||
2066 | HRESULT CArchiveExtractCallback::SetLink( | ||
2067 | const FString &fullProcessedPath_from, | ||
2068 | const CLinkInfo &link, | ||
2069 | bool &linkWasSet) // placeholder was created | ||
1998 | { | 2070 | { |
1999 | linkWasSet = false; | 2071 | linkWasSet = false; |
2000 | if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink) | 2072 | if (link.LinkPath.IsEmpty()) |
2073 | return S_OK; | ||
2074 | if (!_ntOptions.SymLinks.Val && link.Is_AnySymLink()) | ||
2001 | return S_OK; | 2075 | return S_OK; |
2076 | CPostLink postLink; | ||
2077 | postLink.Index_in_Arc = _index; | ||
2078 | postLink.item_IsDir = _item.IsDir; | ||
2079 | postLink.item_Path = _item.Path; | ||
2080 | postLink.item_PathParts = _item.PathParts; | ||
2081 | postLink.item_FileInfo = _fi; | ||
2082 | postLink.fullProcessedPath_from = fullProcessedPath_from; | ||
2083 | postLink.LinkInfo = link; | ||
2084 | _postLinks.Add(postLink); | ||
2085 | |||
2086 | // file doesn't exist in most cases. So we don't check for error. | ||
2087 | DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, false); // checkThatFileIsEmpty = false | ||
2002 | 2088 | ||
2003 | UString relatPath; | 2089 | NIO::COutFile outFile; |
2090 | if (!outFile.Create_NEW(fullProcessedPath_from)) | ||
2091 | return SendMessageError("Cannot create temporary link file", fullProcessedPath_from); | ||
2092 | #if 0 // 1 for debug | ||
2093 | // here we can write link path to temporary link file placeholder, | ||
2094 | // but empty placeholder is better, because we don't want to get any non-eampty data instead of link file. | ||
2095 | AString s; | ||
2096 | ConvertUnicodeToUTF8(link.LinkPath, s); | ||
2097 | outFile.WriteFull(s, s.Len()); | ||
2098 | #endif | ||
2099 | linkWasSet = true; | ||
2100 | return S_OK; | ||
2101 | } | ||
2004 | 2102 | ||
2005 | /* if (linkInfo.isRelative) | 2103 | |
2006 | linkInfo.linkPath is final link path that must be stored to file link field | 2104 | // if file/dir is symbolic link it will remove only link itself |
2007 | else | 2105 | HRESULT CArchiveExtractCallback::DeleteLinkFileAlways_or_RemoveEmptyDir( |
2008 | linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath. | 2106 | const FString &path, bool checkThatFileIsEmpty) const |
2009 | */ | 2107 | { |
2010 | 2108 | NFile::NFind::CFileInfo fi; | |
2011 | if (linkInfo.isRelative) | 2109 | if (fi.Find(path)) // followLink = false |
2012 | relatPath = GetDirPrefixOf(_item.Path); | ||
2013 | relatPath += linkInfo.linkPath; | ||
2014 | |||
2015 | if (!IsSafePath(relatPath)) | ||
2016 | { | 2110 | { |
2017 | return SendMessageError2( | 2111 | if (fi.IsDir()) |
2018 | 0, // errorCode | 2112 | { |
2019 | "Dangerous link path was ignored", | 2113 | if (RemoveDirAlways_if_Empty(path)) |
2020 | us2fs(_item.Path), | 2114 | return S_OK; |
2021 | us2fs(linkInfo.linkPath)); // us2fs(relatPath) | 2115 | } |
2116 | else | ||
2117 | { | ||
2118 | // link file placeholder must be empty | ||
2119 | if (checkThatFileIsEmpty && !fi.IsOsSymLink() && fi.Size != 0) | ||
2120 | return SendMessageError("Temporary link file is not empty", path); | ||
2121 | if (DeleteFileAlways(path)) | ||
2122 | return S_OK; | ||
2123 | } | ||
2124 | if (GetLastError() != ERROR_FILE_NOT_FOUND) | ||
2125 | return SendMessageError_with_LastError( | ||
2126 | fi.IsDir() ? | ||
2127 | k_CantDelete_Dir_for_SymLink: | ||
2128 | k_CantDelete_File_for_SymLink, | ||
2129 | path); | ||
2022 | } | 2130 | } |
2131 | return S_OK; | ||
2132 | } | ||
2133 | |||
2134 | |||
2135 | /* | ||
2136 | in: | ||
2137 | link.LinkPath : must be relative (non-absolute) path in any case !!! | ||
2138 | link.isRelative / target path that must stored as created link: | ||
2139 | == false / _dirPathPrefix_Full + link.LinkPath | ||
2140 | == true / link.LinkPath | ||
2141 | */ | ||
2142 | static HRESULT SetLink2(const CArchiveExtractCallback &callback, | ||
2143 | const CPostLink &postLink, bool &linkWasSet) | ||
2144 | { | ||
2145 | const CLinkInfo &link = postLink.LinkInfo; | ||
2146 | const FString &fullProcessedPath_from = postLink.fullProcessedPath_from; // full file path in FS (fullProcessedPath_from) | ||
2023 | 2147 | ||
2024 | FString existPath; | 2148 | const unsigned level = callback._ntOptions.SymLinks_DangerousLevel; |
2025 | if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative) | 2149 | if (level < 20) |
2026 | { | 2150 | { |
2027 | if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) | 2151 | /* |
2152 | We want to use additional check for links that can link to directory. | ||
2153 | - linux: all symbolic links are files. | ||
2154 | - windows: we can have file/directory symbolic link, | ||
2155 | but file symbolic link works like directory link in windows. | ||
2156 | So we use additional check for all relative links. | ||
2157 | |||
2158 | We don't allow decreasing of final level of link. | ||
2159 | So if some another extracted file will use this link, | ||
2160 | then number of real path parts (after link redirection) cannot be | ||
2161 | smaller than number of requested path parts from archive records. | ||
2162 | |||
2163 | here we check only (link.LinkPath) without (_item.PathParts). | ||
2164 | */ | ||
2165 | CLinkLevelsInfo li; | ||
2166 | li.Parse(link.LinkPath, link.Is_WSL()); | ||
2167 | bool isDang; | ||
2168 | UString relativePathPrefix; | ||
2169 | if (li.IsAbsolute // unexpected | ||
2170 | || li.ParentDirDots_after_NonParent | ||
2171 | || (level <= 5 && link.isRelative && li.FinalLevel < 1) // final level lower | ||
2172 | || (level <= 5 && link.isRelative && li.LowLevel < 0) // negative temporary levels | ||
2173 | ) | ||
2174 | isDang = true; | ||
2175 | else // if (!isDang) | ||
2028 | { | 2176 | { |
2029 | RINOK(SendMessageError("Incorrect path", us2fs(relatPath))) | 2177 | UString path; |
2030 | } | 2178 | if (link.isRelative) |
2179 | { | ||
2180 | // item_PathParts : parts that will be created in output folder. | ||
2181 | // we want to get directory prefix of link item. | ||
2182 | // so we remove file name (last non-empty part) from PathParts: | ||
2183 | UStringVector v = postLink.item_PathParts; | ||
2184 | while (!v.IsEmpty()) | ||
2185 | { | ||
2186 | const unsigned len = v.Back().Len(); | ||
2187 | v.DeleteBack(); | ||
2188 | if (len) | ||
2189 | break; | ||
2190 | } | ||
2191 | path = MakePathFromParts(v); | ||
2192 | NName::NormalizeDirPathPrefix(path); | ||
2193 | relativePathPrefix = path; | ||
2194 | } | ||
2195 | path += link.LinkPath; | ||
2196 | /* | ||
2197 | path is calculated virtual target path of link | ||
2198 | path is relative to root folder of extracted items | ||
2199 | if (!link.isRelative), then (path == link.LinkPath) | ||
2200 | */ | ||
2201 | isDang = false; | ||
2202 | if (!IsSafePath(path, link.Is_WSL())) | ||
2203 | isDang = true; | ||
2204 | } | ||
2205 | const char *message = NULL; | ||
2206 | if (isDang) | ||
2207 | message = "Dangerous link path was ignored"; | ||
2208 | else if (level <= k_DangLevel_MAX_for_Link_over_Link | ||
2209 | && !CheckLinkPath_in_FS(callback._dirPathPrefix_Full, | ||
2210 | postLink, relativePathPrefix)) | ||
2211 | message = "Dangerous link via another link was ignored"; | ||
2212 | if (message) | ||
2213 | return callback.SendMessageError2(0, // errorCode | ||
2214 | message, us2fs(postLink.item_Path), us2fs(link.LinkPath)); | ||
2215 | } | ||
2216 | |||
2217 | FString target; // target path that will be stored to link field | ||
2218 | if (link.Is_HardLink() /* || link.IsCopyLink */ || !link.isRelative) | ||
2219 | { | ||
2220 | // isRelative == false | ||
2221 | // all hard links and absolute symbolic links | ||
2222 | // relatPath == link.LinkPath | ||
2223 | // we get absolute link path for target: | ||
2224 | if (!NName::GetFullPath(callback._dirPathPrefix_Full, us2fs(link.LinkPath), target)) | ||
2225 | return callback.SendMessageError("Incorrect link path", us2fs(link.LinkPath)); | ||
2226 | // (target) is (_dirPathPrefix_Full + relatPath) | ||
2031 | } | 2227 | } |
2032 | else | 2228 | else |
2033 | { | 2229 | { |
2034 | existPath = us2fs(linkInfo.linkPath); | 2230 | // link.isRelative == true |
2035 | // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr()); | 2231 | // relative symbolic links only |
2232 | target = us2fs(link.LinkPath); | ||
2036 | } | 2233 | } |
2037 | 2234 | if (target.IsEmpty()) | |
2038 | if (existPath.IsEmpty()) | 2235 | return callback.SendMessageError("Empty link", fullProcessedPath_from); |
2039 | return SendMessageError("Empty link", fullProcessedPath); | ||
2040 | 2236 | ||
2041 | if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */) | 2237 | if (link.Is_HardLink() /* || link.IsCopyLink */) |
2042 | { | 2238 | { |
2043 | // if (linkInfo.isHardLink) | 2239 | // if (link.isHardLink) |
2044 | { | 2240 | { |
2045 | if (!MyCreateHardLink(fullProcessedPath, existPath)) | 2241 | RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty |
2046 | { | 2242 | { |
2047 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 2243 | // RINOK(SendMessageError_with_LastError(k_Cant_DeleteTempLinkFile, fullProcessedPath_from)) |
2048 | RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)) | ||
2049 | } | 2244 | } |
2245 | return callback.CreateHardLink2(fullProcessedPath_from, target, linkWasSet); | ||
2050 | /* | 2246 | /* |
2051 | RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) | 2247 | RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) |
2052 | _op_WasReported = true; | 2248 | _op_WasReported = true; |
2053 | RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK)) | 2249 | RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK)) |
2054 | */ | ||
2055 | linkWasSet = true; | 2250 | linkWasSet = true; |
2056 | return S_OK; | 2251 | return S_OK; |
2252 | */ | ||
2057 | } | 2253 | } |
2058 | /* | 2254 | /* |
2059 | // IsCopyLink | 2255 | // IsCopyLink |
2060 | { | 2256 | { |
2061 | NFind::CFileInfo fi; | 2257 | NFind::CFileInfo fi; |
2062 | if (!fi.Find(existPath)) | 2258 | if (!fi.Find(target)) |
2063 | { | 2259 | { |
2064 | RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath)); | 2260 | RINOK(SendMessageError2("Cannot find the file for copying", target, fullProcessedPath)); |
2065 | } | 2261 | } |
2066 | else | 2262 | else |
2067 | { | 2263 | { |
2068 | if (_curSize_Defined && _curSize == fi.Size) | 2264 | if (_curSize_Defined && _curSize == fi.Size) |
2069 | _copyFile_Path = existPath; | 2265 | _copyFile_Path = target; |
2070 | else | 2266 | else |
2071 | { | 2267 | { |
2072 | RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); | 2268 | RINOK(SendMessageError2("File size collision for file copying", target, fullProcessedPath)); |
2073 | } | 2269 | } |
2074 | // RINOK(MyCopyFile(existPath, fullProcessedPath)); | 2270 | // RINOK(MyCopyFile(target, fullProcessedPath)); |
2075 | } | 2271 | } |
2076 | } | 2272 | } |
2077 | */ | 2273 | */ |
@@ -2085,127 +2281,227 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath( | |||
2085 | // Windows before Vista doesn't support symbolic links. | 2281 | // Windows before Vista doesn't support symbolic links. |
2086 | // we could convert such symbolic links to Junction Points | 2282 | // we could convert such symbolic links to Junction Points |
2087 | // isJunction = true; | 2283 | // isJunction = true; |
2088 | // convertToAbs = true; | ||
2089 | } | 2284 | } |
2090 | */ | 2285 | */ |
2091 | 2286 | ||
2092 | if (!_ntOptions.SymLinks_AllowDangerous.Val) | 2287 | #ifdef _WIN32 |
2093 | { | 2288 | const bool isDir = (postLink.item_IsDir || link.LinkType == k_LinkType_Junction); |
2094 | #ifdef _WIN32 | 2289 | #endif |
2095 | if (_item.IsDir) | ||
2096 | #endif | ||
2097 | if (linkInfo.isRelative) | ||
2098 | { | ||
2099 | CLinkLevelsInfo levelsInfo; | ||
2100 | levelsInfo.Parse(linkInfo.linkPath); | ||
2101 | if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute) | ||
2102 | { | ||
2103 | return SendMessageError2( | ||
2104 | 0, // errorCode | ||
2105 | "Dangerous symbolic link path was ignored", | ||
2106 | us2fs(_item.Path), | ||
2107 | us2fs(linkInfo.linkPath)); | ||
2108 | } | ||
2109 | } | ||
2110 | } | ||
2111 | 2290 | ||
2112 | 2291 | ||
2113 | #ifdef _WIN32 | 2292 | #ifdef _WIN32 |
2114 | |||
2115 | CByteBuffer data; | 2293 | CByteBuffer data; |
2116 | // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr()); | 2294 | // printf("\nFillLinkData(): %s\n", GetOemString(target).Ptr()); |
2117 | if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL)) | 2295 | if (link.Is_WSL()) |
2118 | return SendMessageError("Cannot fill link data", us2fs(_item.Path)); | ||
2119 | |||
2120 | /* | ||
2121 | if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) | ||
2122 | { | 2296 | { |
2123 | SendMessageError("reconstructed Reparse is different", fs2us(existPath)); | 2297 | Convert_WinPath_to_WslLinuxPath(target, !link.isRelative); |
2298 | FillLinkData_WslLink(data, fs2us(target)); | ||
2124 | } | 2299 | } |
2300 | else | ||
2301 | FillLinkData_WinLink(data, fs2us(target), link.LinkType != k_LinkType_Junction); | ||
2302 | if (data.Size() == 0) | ||
2303 | return callback.SendMessageError("Cannot fill link data", us2fs(postLink.item_Path)); | ||
2304 | /* | ||
2305 | if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) | ||
2306 | SendMessageError("reconstructed Reparse is different", fs2us(target)); | ||
2125 | */ | 2307 | */ |
2126 | |||
2127 | CReparseAttr attr; | ||
2128 | if (!attr.Parse(data, data.Size())) | ||
2129 | { | 2308 | { |
2130 | RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))) | 2309 | // we check that reparse data is correct, but we ignore attr.MinorError. |
2131 | return S_OK; | 2310 | CReparseAttr attr; |
2132 | } | 2311 | if (!attr.Parse(data, data.Size())) |
2133 | if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) | 2312 | return callback.SendMessageError("Internal error for symbolic link file", us2fs(postLink.item_Path)); |
2134 | { | ||
2135 | RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) | ||
2136 | return S_OK; | ||
2137 | } | 2313 | } |
2138 | linkWasSet = true; | 2314 | #endif |
2139 | |||
2140 | return S_OK; | ||
2141 | |||
2142 | |||
2143 | #else // ! _WIN32 | ||
2144 | 2315 | ||
2145 | if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath)) | 2316 | RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty |
2317 | #ifdef _WIN32 | ||
2318 | if (!NFile::NIO::SetReparseData(fullProcessedPath_from, isDir, data, (DWORD)data.Size())) | ||
2319 | #else // ! _WIN32 | ||
2320 | if (!NFile::NIO::SetSymLink(fullProcessedPath_from, target)) | ||
2321 | #endif // ! _WIN32 | ||
2146 | { | 2322 | { |
2147 | RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) | 2323 | return callback.SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath_from); |
2148 | return S_OK; | ||
2149 | } | 2324 | } |
2150 | linkWasSet = true; | 2325 | linkWasSet = true; |
2151 | |||
2152 | return S_OK; | 2326 | return S_OK; |
2153 | |||
2154 | #endif // ! _WIN32 | ||
2155 | } | 2327 | } |
2156 | 2328 | ||
2157 | 2329 | ||
2158 | bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) | ||
2159 | { | ||
2160 | Clear(); | ||
2161 | // this->isLinux = isLinuxData; | ||
2162 | |||
2163 | if (isLinuxData) | ||
2164 | { | ||
2165 | isJunction = false; | ||
2166 | isHardLink = false; | ||
2167 | AString utf; | ||
2168 | if (dataSize >= (1 << 12)) | ||
2169 | return false; | ||
2170 | utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); | ||
2171 | UString u; | ||
2172 | if (!ConvertUTF8ToUnicode(utf, u)) | ||
2173 | return false; | ||
2174 | linkPath = u; | ||
2175 | |||
2176 | // in linux symbolic data: we expect that linux separator '/' is used | ||
2177 | // if windows link was created, then we also must use linux separator | ||
2178 | if (u.IsEmpty()) | ||
2179 | return false; | ||
2180 | const wchar_t c = u[0]; | ||
2181 | isRelative = !IS_PATH_SEPAR(c); | ||
2182 | return true; | ||
2183 | } | ||
2184 | 2330 | ||
2331 | bool CLinkInfo::Parse_from_WindowsReparseData(const Byte *data, size_t dataSize) | ||
2332 | { | ||
2185 | CReparseAttr reparse; | 2333 | CReparseAttr reparse; |
2186 | if (!reparse.Parse(data, dataSize)) | 2334 | if (!reparse.Parse(data, dataSize)) |
2187 | return false; | 2335 | return false; |
2188 | isHardLink = false; | 2336 | // const AString s = GetAnsiString(LinkPath); |
2189 | // isCopyLink = false; | 2337 | // printf("\nlinkPath: %s\n", s.Ptr()); |
2190 | linkPath = reparse.GetPath(); | 2338 | LinkPath = reparse.GetPath(); |
2191 | isJunction = reparse.IsMountPoint(); | ||
2192 | |||
2193 | if (reparse.IsSymLink_WSL()) | 2339 | if (reparse.IsSymLink_WSL()) |
2194 | { | 2340 | { |
2195 | isWSL = true; | 2341 | LinkType = k_LinkType_WSL; |
2196 | isRelative = reparse.IsRelative_WSL(); | 2342 | isRelative = reparse.IsRelative_WSL(); // detected from LinkPath[0] |
2343 | // LinkPath is original raw name converted to UString from AString | ||
2344 | // Linux separator '/' is expected here. | ||
2345 | REPLACE_SLASHES_from_Linux_to_Sys(LinkPath) | ||
2197 | } | 2346 | } |
2198 | else | 2347 | else |
2199 | isRelative = reparse.IsRelative_Win(); | 2348 | { |
2200 | 2349 | LinkType = reparse.IsMountPoint() ? k_LinkType_Junction : k_LinkType_PureSymLink; | |
2201 | // FIXME !!! | 2350 | isRelative = reparse.IsRelative_Win(); // detected by (Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE) |
2202 | #ifndef _WIN32 | 2351 | isWindowsPath = true; |
2203 | linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | 2352 | // LinkPath is original windows link path from raparse data with \??\ prefix removed. |
2204 | #endif | 2353 | // windows '\\' separator is expected here. |
2205 | 2354 | // linux '/' separator is not expected here. | |
2355 | // we translate both types of separators to system separator. | ||
2356 | LinkPath.Replace( | ||
2357 | #if WCHAR_PATH_SEPARATOR == L'\\' | ||
2358 | L'/' | ||
2359 | #else | ||
2360 | L'\\' | ||
2361 | #endif | ||
2362 | , WCHAR_PATH_SEPARATOR); | ||
2363 | } | ||
2364 | // (LinkPath) uses system path separator. | ||
2365 | // windows: (LinkPath) doesn't contain linux separator (slash). | ||
2366 | return true; | ||
2367 | } | ||
2368 | |||
2369 | |||
2370 | bool CLinkInfo::Parse_from_LinuxData(const Byte *data, size_t dataSize) | ||
2371 | { | ||
2372 | // Clear(); // *this object was cleared by constructor already. | ||
2373 | LinkType = k_LinkType_PureSymLink; | ||
2374 | AString utf; | ||
2375 | if (dataSize >= k_LinkDataSize_LIMIT) | ||
2376 | return false; | ||
2377 | utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); | ||
2378 | UString u; | ||
2379 | if (!ConvertUTF8ToUnicode(utf, u)) | ||
2380 | return false; | ||
2381 | if (u.IsEmpty()) | ||
2382 | return false; | ||
2383 | const wchar_t c = u[0]; | ||
2384 | isRelative = (c != L'/'); | ||
2385 | // linux path separator is expected | ||
2386 | REPLACE_SLASHES_from_Linux_to_Sys(u) | ||
2387 | LinkPath = u; | ||
2388 | // (LinkPath) uses system path separator. | ||
2389 | // windows: (LinkPath) doesn't contain linux separator (slash). | ||
2206 | return true; | 2390 | return true; |
2207 | } | 2391 | } |
2208 | 2392 | ||
2393 | |||
2394 | // in/out: (LinkPath) uses system path separator | ||
2395 | // in/out: windows: (LinkPath) doesn't contain linux separator (slash). | ||
2396 | // out: (LinkPath) is relative path, and LinkPath[0] is not path separator | ||
2397 | // out: isRelative changed to false, if any prefix was removed. | ||
2398 | // note: absolute windows links "c:\" to root will be reduced to empty string: | ||
2399 | void CLinkInfo::Remove_AbsPathPrefixes() | ||
2400 | { | ||
2401 | while (!LinkPath.IsEmpty()) | ||
2402 | { | ||
2403 | unsigned n = 0; | ||
2404 | if (!Is_WSL()) | ||
2405 | { | ||
2406 | n = | ||
2407 | #ifndef _WIN32 | ||
2408 | isWindowsPath ? | ||
2409 | NName::GetRootPrefixSize_WINDOWS(LinkPath) : | ||
2410 | #endif | ||
2411 | NName::GetRootPrefixSize(LinkPath); | ||
2412 | /* | ||
2413 | // "c:path" will be ignored later as "Dangerous absolute path" | ||
2414 | // so check is not required | ||
2415 | if (n == 0 | ||
2416 | #ifndef _WIN32 | ||
2417 | && isWindowsPath | ||
2418 | #endif | ||
2419 | && NName::IsDrivePath2(LinkPath)) | ||
2420 | n = 2; | ||
2421 | */ | ||
2422 | } | ||
2423 | if (n == 0) | ||
2424 | { | ||
2425 | if (!IS_PATH_SEPAR(LinkPath[0])) | ||
2426 | break; | ||
2427 | n = 1; | ||
2428 | } | ||
2429 | isRelative = false; // (LinkPath) will be treated as relative to root folder of archive | ||
2430 | LinkPath.DeleteFrontal(n); | ||
2431 | } | ||
2432 | } | ||
2433 | |||
2434 | |||
2435 | /* | ||
2436 | it removes redundant separators, if there are double separators, | ||
2437 | but it keeps double separators at start of string //name/. | ||
2438 | in/out: system path separator is used | ||
2439 | windows: slash character (linux separator) is not treated as separator | ||
2440 | windows: (path) doesn't contain linux separator (slash). | ||
2441 | */ | ||
2442 | static void RemoveRedundantPathSeparators(UString &path) | ||
2443 | { | ||
2444 | wchar_t *dest = path.GetBuf(); | ||
2445 | const wchar_t * const start = dest; | ||
2446 | const wchar_t *src = dest; | ||
2447 | for (;;) | ||
2448 | { | ||
2449 | wchar_t c = *src++; | ||
2450 | if (c == 0) | ||
2451 | break; | ||
2452 | // if (IS_PATH_SEPAR(c)) // for Windows: we can change (/) to (\). | ||
2453 | if (c == WCHAR_PATH_SEPARATOR) | ||
2454 | { | ||
2455 | if (dest - start >= 2 && dest[-1] == WCHAR_PATH_SEPARATOR) | ||
2456 | continue; | ||
2457 | // c = WCHAR_PATH_SEPARATOR; // for Windows: we can change (/) to (\). | ||
2458 | } | ||
2459 | *dest++ = c; | ||
2460 | } | ||
2461 | *dest = 0; | ||
2462 | path.ReleaseBuf_SetLen((unsigned)(dest - path.Ptr())); | ||
2463 | } | ||
2464 | |||
2465 | |||
2466 | // in/out: (LinkPath) uses system path separator | ||
2467 | // in/out: windows: (LinkPath) doesn't contain linux separator (slash). | ||
2468 | // out: (LinkPath) is relative path, and LinkPath[0] is not path separator | ||
2469 | void CLinkInfo::Normalize_to_RelativeSafe(UStringVector &removePathParts) | ||
2470 | { | ||
2471 | // We WILL NOT WRITE original absolute link path from archive to filesystem. | ||
2472 | // So here we remove all root prefixes from (LinkPath). | ||
2473 | // If we see any absolute root prefix, then we suppose that this prefix is virtual prefix | ||
2474 | // that shows that link is relative to root folder of archive | ||
2475 | RemoveRedundantPathSeparators(LinkPath); | ||
2476 | // LinkPath = "\\\\?\\r:test\\test2"; // for debug | ||
2477 | Remove_AbsPathPrefixes(); | ||
2478 | // (LinkPath) now is relative: | ||
2479 | // if (isRelative == false), then (LinkPath) is relative to root folder of archive | ||
2480 | // if (isRelative == true ), then (LinkPath) is relative to current item | ||
2481 | if (LinkPath.IsEmpty() || isRelative || removePathParts.Size() == 0) | ||
2482 | return; | ||
2483 | |||
2484 | // if LinkPath is prefixed by _removePathParts, we remove these paths | ||
2485 | UStringVector pathParts; | ||
2486 | SplitPathToParts(LinkPath, pathParts); | ||
2487 | bool badPrefix = false; | ||
2488 | { | ||
2489 | FOR_VECTOR (i, removePathParts) | ||
2490 | { | ||
2491 | if (i >= pathParts.Size() | ||
2492 | || CompareFileNames(removePathParts[i], pathParts[i]) != 0) | ||
2493 | { | ||
2494 | badPrefix = true; | ||
2495 | break; | ||
2496 | } | ||
2497 | } | ||
2498 | } | ||
2499 | if (!badPrefix) | ||
2500 | pathParts.DeleteFrontal(removePathParts.Size()); | ||
2501 | LinkPath = MakePathFromParts(pathParts); | ||
2502 | Remove_AbsPathPrefixes(); | ||
2503 | } | ||
2504 | |||
2209 | #endif // SUPPORT_LINKS | 2505 | #endif // SUPPORT_LINKS |
2210 | 2506 | ||
2211 | 2507 | ||
@@ -2213,12 +2509,12 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2213 | { | 2509 | { |
2214 | HRESULT res = S_OK; | 2510 | HRESULT res = S_OK; |
2215 | 2511 | ||
2216 | #ifdef SUPPORT_LINKS | 2512 | #ifdef SUPPORT_LINKS |
2217 | 2513 | ||
2218 | size_t reparseSize = 0; | 2514 | size_t reparseSize = 0; |
2219 | bool repraseMode = false; | 2515 | bool repraseMode = false; |
2220 | bool needSetReparse = false; | 2516 | bool needSetReparse = false; |
2221 | CLinkInfo linkInfo; | 2517 | CLinkInfo link; |
2222 | 2518 | ||
2223 | if (_bufPtrSeqOutStream) | 2519 | if (_bufPtrSeqOutStream) |
2224 | { | 2520 | { |
@@ -2232,15 +2528,19 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2232 | needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); | 2528 | needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); |
2233 | if (needSetReparse) | 2529 | if (needSetReparse) |
2234 | { | 2530 | { |
2235 | UString linkPath = reparse.GetPath(); | 2531 | UString LinkPath = reparse.GetPath(); |
2236 | #ifndef _WIN32 | 2532 | #ifndef _WIN32 |
2237 | linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | 2533 | LinkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); |
2238 | #endif | 2534 | #endif |
2239 | } | 2535 | } |
2240 | */ | 2536 | */ |
2241 | needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux); | 2537 | needSetReparse = _is_SymLink_in_Data_Linux ? |
2538 | link.Parse_from_LinuxData(_outMemBuf, reparseSize) : | ||
2539 | link.Parse_from_WindowsReparseData(_outMemBuf, reparseSize); | ||
2242 | if (!needSetReparse) | 2540 | if (!needSetReparse) |
2243 | res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); | 2541 | res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); |
2542 | // (link.LinkPath) uses system path separator. | ||
2543 | // windows: (link.LinkPath) doesn't contain linux separator (slash). | ||
2244 | } | 2544 | } |
2245 | else | 2545 | else |
2246 | { | 2546 | { |
@@ -2255,25 +2555,21 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2255 | _bufPtrSeqOutStream.Release(); | 2555 | _bufPtrSeqOutStream.Release(); |
2256 | } | 2556 | } |
2257 | 2557 | ||
2258 | #endif // SUPPORT_LINKS | 2558 | #endif // SUPPORT_LINKS |
2259 | |||
2260 | 2559 | ||
2261 | const HRESULT res2 = CloseFile(); | 2560 | const HRESULT res2 = CloseFile(); |
2262 | |||
2263 | if (res == S_OK) | 2561 | if (res == S_OK) |
2264 | res = res2; | 2562 | res = res2; |
2265 | |||
2266 | RINOK(res) | 2563 | RINOK(res) |
2267 | 2564 | ||
2268 | #ifdef SUPPORT_LINKS | 2565 | #ifdef SUPPORT_LINKS |
2269 | if (repraseMode) | 2566 | if (repraseMode) |
2270 | { | 2567 | { |
2271 | _curSize = reparseSize; | 2568 | _curSize = reparseSize; |
2272 | _curSize_Defined = true; | 2569 | _curSize_Defined = true; |
2273 | |||
2274 | #ifdef SUPPORT_LINKS | ||
2275 | if (needSetReparse) | 2570 | if (needSetReparse) |
2276 | { | 2571 | { |
2572 | // empty file was created so we must delete it. | ||
2277 | // in Linux : we must delete empty file before symbolic link creation | 2573 | // in Linux : we must delete empty file before symbolic link creation |
2278 | // in Windows : we can create symbolic link even without file deleting | 2574 | // in Windows : we can create symbolic link even without file deleting |
2279 | if (!DeleteFileAlways(_diskFilePath)) | 2575 | if (!DeleteFileAlways(_diskFilePath)) |
@@ -2281,42 +2577,57 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2281 | RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)) | 2577 | RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)) |
2282 | } | 2578 | } |
2283 | { | 2579 | { |
2284 | /* | ||
2285 | // for DEBUG ONLY: we can extract sym links as WSL links | ||
2286 | // to eliminate (non-admin) errors for sym links. | ||
2287 | #ifdef _WIN32 | ||
2288 | if (!linkInfo.isHardLink && !linkInfo.isJunction) | ||
2289 | linkInfo.isWSL = true; | ||
2290 | #endif | ||
2291 | */ | ||
2292 | bool linkWasSet = false; | 2580 | bool linkWasSet = false; |
2293 | RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)) | 2581 | // link.LinkPath = "r:\\1\\2"; // for debug |
2582 | // link.isJunction = true; // for debug | ||
2583 | link.Normalize_to_RelativeSafe(_removePathParts); | ||
2584 | RINOK(SetLink(_diskFilePath, link, linkWasSet)) | ||
2585 | /* | ||
2586 | // we don't set attributes for placeholder. | ||
2294 | if (linkWasSet) | 2587 | if (linkWasSet) |
2295 | _isSymLinkCreated = linkInfo.IsSymLink(); | 2588 | _isSymLinkCreated = true; // link.IsSymLink(); |
2296 | else | 2589 | else |
2590 | */ | ||
2297 | _needSetAttrib = false; | 2591 | _needSetAttrib = false; |
2298 | } | 2592 | } |
2299 | /* | ||
2300 | if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) | ||
2301 | { | ||
2302 | res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath); | ||
2303 | } | ||
2304 | */ | ||
2305 | } | 2593 | } |
2306 | #endif | ||
2307 | } | 2594 | } |
2308 | #endif | 2595 | #endif // SUPPORT_LINKS |
2309 | return res; | 2596 | return res; |
2310 | } | 2597 | } |
2311 | 2598 | ||
2312 | 2599 | ||
2313 | void CArchiveExtractCallback::SetAttrib() | 2600 | static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi, |
2601 | const CArchiveExtractCallback &callback) | ||
2314 | { | 2602 | { |
2315 | #ifndef _WIN32 | 2603 | #ifndef _WIN32 |
2604 | if (fi.Owner.Id_Defined && | ||
2605 | fi.Group.Id_Defined) | ||
2606 | { | ||
2607 | if (my_chown(path, fi.Owner.Id, fi.Group.Id) != 0) | ||
2608 | callback.SendMessageError_with_LastError("Cannot set owner", path); | ||
2609 | } | ||
2610 | #endif | ||
2611 | |||
2612 | if (fi.Attrib_Defined) | ||
2613 | { | ||
2614 | // const AString s = GetAnsiString(_diskFilePath); | ||
2615 | // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); | ||
2616 | if (!SetFileAttrib_PosixHighDetect(path, fi.Attrib)) | ||
2617 | { | ||
2618 | // do we need error message here in Windows and in posix? | ||
2619 | callback.SendMessageError_with_LastError("Cannot set file attribute", path); | ||
2620 | } | ||
2621 | } | ||
2622 | } | ||
2623 | |||
2624 | void CArchiveExtractCallback::SetAttrib() const | ||
2625 | { | ||
2626 | #ifndef _WIN32 | ||
2316 | // Linux now doesn't support permissions for symlinks | 2627 | // Linux now doesn't support permissions for symlinks |
2317 | if (_isSymLinkCreated) | 2628 | if (_isSymLinkCreated) |
2318 | return; | 2629 | return; |
2319 | #endif | 2630 | #endif |
2320 | 2631 | ||
2321 | if (_itemFailure | 2632 | if (_itemFailure |
2322 | || _diskFilePath.IsEmpty() | 2633 | || _diskFilePath.IsEmpty() |
@@ -2324,29 +2635,39 @@ void CArchiveExtractCallback::SetAttrib() | |||
2324 | || !_extractMode) | 2635 | || !_extractMode) |
2325 | return; | 2636 | return; |
2326 | 2637 | ||
2327 | #ifndef _WIN32 | 2638 | SetAttrib_Base(_diskFilePath, _fi, *this); |
2328 | if (_fi.Owner.Id_Defined && | 2639 | } |
2329 | _fi.Group.Id_Defined) | ||
2330 | { | ||
2331 | if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0) | ||
2332 | { | ||
2333 | SendMessageError_with_LastError("Cannot set owner", _diskFilePath); | ||
2334 | } | ||
2335 | } | ||
2336 | #endif | ||
2337 | 2640 | ||
2338 | if (_fi.Attrib_Defined) | 2641 | |
2642 | #ifdef Z7_USE_SECURITY_CODE | ||
2643 | HRESULT CArchiveExtractCallback::SetSecurityInfo(UInt32 indexInArc, const FString &path) const | ||
2644 | { | ||
2645 | if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) | ||
2339 | { | 2646 | { |
2340 | // const AString s = GetAnsiString(_diskFilePath); | 2647 | const void *data; |
2341 | // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); | 2648 | UInt32 dataSize; |
2342 | bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); | 2649 | UInt32 propType; |
2343 | if (!res) | 2650 | _arc->GetRawProps->GetRawProp(indexInArc, kpidNtSecure, &data, &dataSize, &propType); |
2651 | if (dataSize != 0) | ||
2344 | { | 2652 | { |
2345 | // do we need error message here in Windows and in posix? | 2653 | if (propType != NPropDataType::kRaw) |
2346 | SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); | 2654 | return E_FAIL; |
2655 | if (CheckNtSecure((const Byte *)data, dataSize)) | ||
2656 | { | ||
2657 | SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; | ||
2658 | if (_saclEnabled) | ||
2659 | securInfo |= SACL_SECURITY_INFORMATION; | ||
2660 | // if (! | ||
2661 | ::SetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); | ||
2662 | { | ||
2663 | // RINOK(SendMessageError_with_LastError("SetFileSecurity FAILS", path)) | ||
2664 | } | ||
2665 | } | ||
2347 | } | 2666 | } |
2348 | } | 2667 | } |
2668 | return S_OK; | ||
2349 | } | 2669 | } |
2670 | #endif // Z7_USE_SECURITY_CODE | ||
2350 | 2671 | ||
2351 | 2672 | ||
2352 | Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | 2673 | Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) |
@@ -2384,27 +2705,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | |||
2384 | 2705 | ||
2385 | RINOK(CloseReparseAndFile()) | 2706 | RINOK(CloseReparseAndFile()) |
2386 | 2707 | ||
2387 | #ifdef Z7_USE_SECURITY_CODE | 2708 | #ifdef Z7_USE_SECURITY_CODE |
2388 | if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) | 2709 | RINOK(SetSecurityInfo(_index, _diskFilePath)) |
2389 | { | 2710 | #endif |
2390 | const void *data; | ||
2391 | UInt32 dataSize; | ||
2392 | UInt32 propType; | ||
2393 | _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); | ||
2394 | if (dataSize != 0) | ||
2395 | { | ||
2396 | if (propType != NPropDataType::kRaw) | ||
2397 | return E_FAIL; | ||
2398 | if (CheckNtSecure((const Byte *)data, dataSize)) | ||
2399 | { | ||
2400 | SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; | ||
2401 | if (_saclEnabled) | ||
2402 | securInfo |= SACL_SECURITY_INFORMATION; | ||
2403 | ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); | ||
2404 | } | ||
2405 | } | ||
2406 | } | ||
2407 | #endif // Z7_USE_SECURITY_CODE | ||
2408 | 2711 | ||
2409 | if (!_curSize_Defined) | 2712 | if (!_curSize_Defined) |
2410 | GetUnpackSize(); | 2713 | GetUnpackSize(); |
@@ -2648,15 +2951,58 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s) | |||
2648 | } | 2951 | } |
2649 | 2952 | ||
2650 | 2953 | ||
2651 | bool CDirPathTime::SetDirTime() const | 2954 | bool CFiTimesCAM::SetDirTime_to_FS(CFSTR path) const |
2652 | { | 2955 | { |
2653 | return NDir::SetDirTime(Path, | 2956 | // it's same function for dir and for file |
2957 | return NDir::SetDirTime(path, | ||
2654 | CTime_Defined ? &CTime : NULL, | 2958 | CTime_Defined ? &CTime : NULL, |
2655 | ATime_Defined ? &ATime : NULL, | 2959 | ATime_Defined ? &ATime : NULL, |
2656 | MTime_Defined ? &MTime : NULL); | 2960 | MTime_Defined ? &MTime : NULL); |
2657 | } | 2961 | } |
2658 | 2962 | ||
2659 | 2963 | ||
2964 | #ifdef SUPPORT_LINKS | ||
2965 | |||
2966 | bool CFiTimesCAM::SetLinkFileTime_to_FS(CFSTR path) const | ||
2967 | { | ||
2968 | // it's same function for dir and for file | ||
2969 | return NDir::SetLinkFileTime(path, | ||
2970 | CTime_Defined ? &CTime : NULL, | ||
2971 | ATime_Defined ? &ATime : NULL, | ||
2972 | MTime_Defined ? &MTime : NULL); | ||
2973 | } | ||
2974 | |||
2975 | HRESULT CArchiveExtractCallback::SetPostLinks() const | ||
2976 | { | ||
2977 | FOR_VECTOR (i, _postLinks) | ||
2978 | { | ||
2979 | const CPostLink &link = _postLinks[i]; | ||
2980 | bool linkWasSet = false; | ||
2981 | RINOK(SetLink2(*this, link, linkWasSet)) | ||
2982 | if (linkWasSet) | ||
2983 | { | ||
2984 | #ifdef _WIN32 | ||
2985 | // Linux now doesn't support permissions for symlinks | ||
2986 | SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this); | ||
2987 | #endif | ||
2988 | |||
2989 | CFiTimesCAM pt; | ||
2990 | GetFiTimesCAM(link.item_FileInfo, pt, *_arc); | ||
2991 | if (pt.IsSomeTimeDefined()) | ||
2992 | pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from); | ||
2993 | |||
2994 | #ifdef Z7_USE_SECURITY_CODE | ||
2995 | // we set security information after timestamps setting | ||
2996 | RINOK(SetSecurityInfo(link.Index_in_Arc, link.fullProcessedPath_from)) | ||
2997 | #endif | ||
2998 | } | ||
2999 | } | ||
3000 | return S_OK; | ||
3001 | } | ||
3002 | |||
3003 | #endif | ||
3004 | |||
3005 | |||
2660 | HRESULT CArchiveExtractCallback::SetDirsTimes() | 3006 | HRESULT CArchiveExtractCallback::SetDirsTimes() |
2661 | { | 3007 | { |
2662 | if (!_arc) | 3008 | if (!_arc) |
@@ -2680,7 +3026,7 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() | |||
2680 | for (i = 0; i < pairs.Size(); i++) | 3026 | for (i = 0; i < pairs.Size(); i++) |
2681 | { | 3027 | { |
2682 | const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; | 3028 | const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; |
2683 | if (!dpt.SetDirTime()) | 3029 | if (!dpt.SetDirTime_to_FS_2()) |
2684 | { | 3030 | { |
2685 | // result = E_FAIL; | 3031 | // result = E_FAIL; |
2686 | // do we need error message here in Windows and in posix? | 3032 | // do we need error message here in Windows and in posix? |
@@ -2712,10 +3058,20 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() | |||
2712 | 3058 | ||
2713 | HRESULT CArchiveExtractCallback::CloseArc() | 3059 | HRESULT CArchiveExtractCallback::CloseArc() |
2714 | { | 3060 | { |
3061 | // we call CloseReparseAndFile() here because we can have non-closed file in some cases? | ||
2715 | HRESULT res = CloseReparseAndFile(); | 3062 | HRESULT res = CloseReparseAndFile(); |
2716 | const HRESULT res2 = SetDirsTimes(); | 3063 | #ifdef SUPPORT_LINKS |
2717 | if (res == S_OK) | 3064 | { |
2718 | res = res2; | 3065 | const HRESULT res2 = SetPostLinks(); |
3066 | if (res == S_OK) | ||
3067 | res = res2; | ||
3068 | } | ||
3069 | #endif | ||
3070 | { | ||
3071 | const HRESULT res2 = SetDirsTimes(); | ||
3072 | if (res == S_OK) | ||
3073 | res = res2; | ||
3074 | } | ||
2719 | _arc = NULL; | 3075 | _arc = NULL; |
2720 | return res; | 3076 | return res; |
2721 | } | 3077 | } |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 7eb2f67..3c62763 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h | |||
@@ -52,7 +52,6 @@ struct CExtractNtOptions | |||
52 | { | 52 | { |
53 | CBoolPair NtSecurity; | 53 | CBoolPair NtSecurity; |
54 | CBoolPair SymLinks; | 54 | CBoolPair SymLinks; |
55 | CBoolPair SymLinks_AllowDangerous; | ||
56 | CBoolPair HardLinks; | 55 | CBoolPair HardLinks; |
57 | CBoolPair AltStreams; | 56 | CBoolPair AltStreams; |
58 | bool ReplaceColonForAltStream; | 57 | bool ReplaceColonForAltStream; |
@@ -66,6 +65,8 @@ struct CExtractNtOptions | |||
66 | bool PreserveATime; | 65 | bool PreserveATime; |
67 | bool OpenShareForWrite; | 66 | bool OpenShareForWrite; |
68 | 67 | ||
68 | unsigned SymLinks_DangerousLevel; | ||
69 | |||
69 | UInt64 MemLimit; | 70 | UInt64 MemLimit; |
70 | 71 | ||
71 | CExtractNtOptions(): | 72 | CExtractNtOptions(): |
@@ -74,10 +75,10 @@ struct CExtractNtOptions | |||
74 | ExtractOwner(false), | 75 | ExtractOwner(false), |
75 | PreserveATime(false), | 76 | PreserveATime(false), |
76 | OpenShareForWrite(false), | 77 | OpenShareForWrite(false), |
78 | SymLinks_DangerousLevel(5), | ||
77 | MemLimit((UInt64)(Int64)-1) | 79 | MemLimit((UInt64)(Int64)-1) |
78 | { | 80 | { |
79 | SymLinks.Val = true; | 81 | SymLinks.Val = true; |
80 | SymLinks_AllowDangerous.Val = false; | ||
81 | HardLinks.Val = true; | 82 | HardLinks.Val = true; |
82 | AltStreams.Val = true; | 83 | AltStreams.Val = true; |
83 | 84 | ||
@@ -90,25 +91,10 @@ struct CExtractNtOptions | |||
90 | } | 91 | } |
91 | }; | 92 | }; |
92 | 93 | ||
93 | #ifndef Z7_SFX | ||
94 | |||
95 | Z7_CLASS_IMP_COM_1( | ||
96 | CGetProp | ||
97 | , IGetProp | ||
98 | ) | ||
99 | public: | ||
100 | UInt32 IndexInArc; | ||
101 | const CArc *Arc; | ||
102 | // UString Name; // relative path | ||
103 | }; | ||
104 | |||
105 | #endif | ||
106 | 94 | ||
107 | #ifndef Z7_SFX | 95 | #ifndef Z7_SFX |
108 | #ifndef UNDER_CE | 96 | #ifndef UNDER_CE |
109 | |||
110 | #define SUPPORT_LINKS | 97 | #define SUPPORT_LINKS |
111 | |||
112 | #endif | 98 | #endif |
113 | #endif | 99 | #endif |
114 | 100 | ||
@@ -181,53 +167,79 @@ struct CFiTimesCAM | |||
181 | ATime_Defined | | 167 | ATime_Defined | |
182 | MTime_Defined; | 168 | MTime_Defined; |
183 | } | 169 | } |
170 | bool SetDirTime_to_FS(CFSTR path) const; | ||
171 | #ifdef SUPPORT_LINKS | ||
172 | bool SetLinkFileTime_to_FS(CFSTR path) const; | ||
173 | #endif | ||
184 | }; | 174 | }; |
185 | 175 | ||
186 | struct CDirPathTime: public CFiTimesCAM | 176 | struct CDirPathTime: public CFiTimesCAM |
187 | { | 177 | { |
188 | FString Path; | 178 | FString Path; |
189 | 179 | ||
190 | bool SetDirTime() const; | 180 | bool SetDirTime_to_FS_2() const { return SetDirTime_to_FS(Path); } |
191 | }; | 181 | }; |
192 | 182 | ||
193 | 183 | ||
194 | #ifdef SUPPORT_LINKS | 184 | #ifdef SUPPORT_LINKS |
195 | 185 | ||
186 | enum ELinkType | ||
187 | { | ||
188 | k_LinkType_HardLink, | ||
189 | k_LinkType_PureSymLink, | ||
190 | k_LinkType_Junction, | ||
191 | k_LinkType_WSL | ||
192 | // , k_LinkType_CopyLink; | ||
193 | }; | ||
194 | |||
195 | |||
196 | struct CLinkInfo | 196 | struct CLinkInfo |
197 | { | 197 | { |
198 | // bool isCopyLink; | 198 | ELinkType LinkType; |
199 | bool isHardLink; | ||
200 | bool isJunction; | ||
201 | bool isRelative; | 199 | bool isRelative; |
202 | bool isWSL; | 200 | // if (isRelative == false), then (LinkPath) is relative to root folder of archive |
203 | UString linkPath; | 201 | // if (isRelative == true ), then (LinkPath) is relative to current item |
202 | bool isWindowsPath; | ||
203 | UString LinkPath; | ||
204 | |||
205 | bool Is_HardLink() const { return LinkType == k_LinkType_HardLink; } | ||
206 | bool Is_AnySymLink() const { return LinkType != k_LinkType_HardLink; } | ||
204 | 207 | ||
205 | bool IsSymLink() const { return !isHardLink; } | 208 | bool Is_WSL() const { return LinkType == k_LinkType_WSL; } |
206 | 209 | ||
207 | CLinkInfo(): | 210 | CLinkInfo(): |
208 | // IsCopyLink(false), | 211 | LinkType(k_LinkType_PureSymLink), |
209 | isHardLink(false), | ||
210 | isJunction(false), | ||
211 | isRelative(false), | 212 | isRelative(false), |
212 | isWSL(false) | 213 | isWindowsPath(false) |
213 | {} | 214 | {} |
214 | 215 | ||
215 | void Clear() | 216 | void Clear() |
216 | { | 217 | { |
217 | // IsCopyLink = false; | 218 | LinkType = k_LinkType_PureSymLink; |
218 | isHardLink = false; | ||
219 | isJunction = false; | ||
220 | isRelative = false; | 219 | isRelative = false; |
221 | isWSL = false; | 220 | isWindowsPath = false; |
222 | linkPath.Empty(); | 221 | LinkPath.Empty(); |
223 | } | 222 | } |
224 | 223 | ||
225 | bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); | 224 | bool Parse_from_WindowsReparseData(const Byte *data, size_t dataSize); |
225 | bool Parse_from_LinuxData(const Byte *data, size_t dataSize); | ||
226 | void Normalize_to_RelativeSafe(UStringVector &removePathParts); | ||
227 | private: | ||
228 | void Remove_AbsPathPrefixes(); | ||
226 | }; | 229 | }; |
227 | 230 | ||
228 | #endif // SUPPORT_LINKS | 231 | #endif // SUPPORT_LINKS |
229 | 232 | ||
230 | 233 | ||
234 | |||
235 | struct CProcessedFileInfo | ||
236 | { | ||
237 | CArcTime CTime; | ||
238 | CArcTime ATime; | ||
239 | CArcTime MTime; | ||
240 | UInt32 Attrib; | ||
241 | bool Attrib_Defined; | ||
242 | |||
231 | #ifndef _WIN32 | 243 | #ifndef _WIN32 |
232 | 244 | ||
233 | struct COwnerInfo | 245 | struct COwnerInfo |
@@ -244,7 +256,75 @@ struct COwnerInfo | |||
244 | } | 256 | } |
245 | }; | 257 | }; |
246 | 258 | ||
259 | COwnerInfo Owner; | ||
260 | COwnerInfo Group; | ||
261 | #endif | ||
262 | |||
263 | void Clear() | ||
264 | { | ||
265 | #ifndef _WIN32 | ||
266 | Attrib_Defined = false; | ||
267 | Owner.Clear(); | ||
247 | #endif | 268 | #endif |
269 | } | ||
270 | |||
271 | bool IsReparse() const | ||
272 | { | ||
273 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); | ||
274 | } | ||
275 | |||
276 | bool IsLinuxSymLink() const | ||
277 | { | ||
278 | return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16)); | ||
279 | } | ||
280 | |||
281 | void SetFromPosixAttrib(UInt32 a) | ||
282 | { | ||
283 | // here we set only part of combined attribute required by SetFileAttrib() call | ||
284 | #ifdef _WIN32 | ||
285 | // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. | ||
286 | Attrib = MY_LIN_S_ISDIR(a) ? | ||
287 | FILE_ATTRIBUTE_DIRECTORY : | ||
288 | FILE_ATTRIBUTE_ARCHIVE; | ||
289 | if ((a & 0222) == 0) // (& S_IWUSR) in p7zip | ||
290 | Attrib |= FILE_ATTRIBUTE_READONLY; | ||
291 | // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink() | ||
292 | a &= MY_LIN_S_IFMT; | ||
293 | if (a == MY_LIN_S_IFLNK) | ||
294 | Attrib |= (a << 16); | ||
295 | #else | ||
296 | Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; | ||
297 | #endif | ||
298 | Attrib_Defined = true; | ||
299 | } | ||
300 | }; | ||
301 | |||
302 | |||
303 | #ifdef SUPPORT_LINKS | ||
304 | |||
305 | struct CPostLink | ||
306 | { | ||
307 | UInt32 Index_in_Arc; | ||
308 | bool item_IsDir; // _item.IsDir | ||
309 | UString item_Path; // _item.Path; | ||
310 | UStringVector item_PathParts; // _item.PathParts; | ||
311 | CProcessedFileInfo item_FileInfo; // _fi | ||
312 | FString fullProcessedPath_from; // full file path in FS | ||
313 | CLinkInfo LinkInfo; | ||
314 | }; | ||
315 | |||
316 | /* | ||
317 | struct CPostLinks | ||
318 | { | ||
319 | void Clear() | ||
320 | { | ||
321 | Links.Clear(); | ||
322 | } | ||
323 | }; | ||
324 | */ | ||
325 | |||
326 | #endif // SUPPORT_LINKS | ||
327 | |||
248 | 328 | ||
249 | 329 | ||
250 | class CArchiveExtractCallback Z7_final: | 330 | class CArchiveExtractCallback Z7_final: |
@@ -282,114 +362,78 @@ class CArchiveExtractCallback Z7_final: | |||
282 | Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) | 362 | Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) |
283 | #endif | 363 | #endif |
284 | 364 | ||
365 | // bool Write_CTime; | ||
366 | // bool Write_ATime; | ||
367 | // bool Write_MTime; | ||
368 | bool _stdOutMode; | ||
369 | bool _testMode; | ||
370 | bool _removePartsForAltStreams; | ||
371 | public: | ||
372 | bool Is_elimPrefix_Mode; | ||
373 | private: | ||
374 | |||
285 | const CArc *_arc; | 375 | const CArc *_arc; |
376 | public: | ||
286 | CExtractNtOptions _ntOptions; | 377 | CExtractNtOptions _ntOptions; |
287 | 378 | private: | |
379 | bool _encrypted; | ||
288 | bool _isSplit; | 380 | bool _isSplit; |
381 | bool _curSize_Defined; | ||
382 | bool _fileLength_WasSet; | ||
289 | 383 | ||
384 | bool _isRenamed; | ||
290 | bool _extractMode; | 385 | bool _extractMode; |
291 | 386 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX. | |
292 | bool Write_CTime; | 387 | // _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file. |
293 | bool Write_ATime; | ||
294 | bool Write_MTime; | ||
295 | bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; | ||
296 | |||
297 | bool _encrypted; | ||
298 | |||
299 | // bool _is_SymLink_in_Data; | ||
300 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX | ||
301 | |||
302 | bool _needSetAttrib; | 388 | bool _needSetAttrib; |
303 | bool _isSymLinkCreated; | 389 | bool _isSymLinkCreated; |
304 | bool _itemFailure; | 390 | bool _itemFailure; |
305 | |||
306 | bool _some_pathParts_wereRemoved; | 391 | bool _some_pathParts_wereRemoved; |
307 | public: | ||
308 | bool Is_elimPrefix_Mode; | ||
309 | |||
310 | private: | ||
311 | bool _curSize_Defined; | ||
312 | bool _fileLength_WasSet; | ||
313 | 392 | ||
314 | bool _removePartsForAltStreams; | ||
315 | |||
316 | bool _stdOutMode; | ||
317 | bool _testMode; | ||
318 | bool _multiArchives; | 393 | bool _multiArchives; |
394 | bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; | ||
395 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | ||
396 | bool _saclEnabled; | ||
397 | #endif | ||
319 | 398 | ||
320 | NExtract::NPathMode::EEnum _pathMode; | 399 | NExtract::NPathMode::EEnum _pathMode; |
321 | NExtract::NOverwriteMode::EEnum _overwriteMode; | 400 | NExtract::NOverwriteMode::EEnum _overwriteMode; |
322 | 401 | ||
323 | const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) | ||
324 | CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; | 402 | CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; |
403 | const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) | ||
325 | // CMyComPtr<ICompressProgressInfo> _compressProgress; | 404 | // CMyComPtr<ICompressProgressInfo> _compressProgress; |
326 | // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage; | 405 | // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage; |
327 | CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; | 406 | CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; |
328 | CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; | 407 | CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; |
329 | 408 | ||
330 | FString _dirPathPrefix; | 409 | FString _dirPathPrefix; |
410 | public: | ||
331 | FString _dirPathPrefix_Full; | 411 | FString _dirPathPrefix_Full; |
412 | private: | ||
332 | 413 | ||
333 | #ifndef Z7_SFX | 414 | #ifndef Z7_SFX |
334 | 415 | ||
335 | CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; | 416 | CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; |
336 | CGetProp *GetProp_Spec; | ||
337 | CMyComPtr<IGetProp> GetProp; | ||
338 | CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback; | 417 | CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback; |
339 | 418 | ||
340 | #endif | 419 | #endif |
341 | 420 | ||
342 | CReadArcItem _item; | 421 | CReadArcItem _item; |
343 | FString _diskFilePath; | 422 | FString _diskFilePath; |
344 | UInt64 _position; | ||
345 | |||
346 | struct CProcessedFileInfo | ||
347 | { | ||
348 | CArcTime CTime; | ||
349 | CArcTime ATime; | ||
350 | CArcTime MTime; | ||
351 | UInt32 Attrib; | ||
352 | bool Attrib_Defined; | ||
353 | 423 | ||
354 | #ifndef _WIN32 | 424 | CProcessedFileInfo _fi; |
355 | COwnerInfo Owner; | ||
356 | COwnerInfo Group; | ||
357 | #endif | ||
358 | |||
359 | bool IsReparse() const | ||
360 | { | ||
361 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); | ||
362 | } | ||
363 | |||
364 | bool IsLinuxSymLink() const | ||
365 | { | ||
366 | return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16)); | ||
367 | } | ||
368 | 425 | ||
369 | void SetFromPosixAttrib(UInt32 a) | 426 | UInt64 _position; |
370 | { | ||
371 | // here we set only part of combined attribute required by SetFileAttrib() call | ||
372 | #ifdef _WIN32 | ||
373 | // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. | ||
374 | Attrib = MY_LIN_S_ISDIR(a) ? | ||
375 | FILE_ATTRIBUTE_DIRECTORY : | ||
376 | FILE_ATTRIBUTE_ARCHIVE; | ||
377 | if ((a & 0222) == 0) // (& S_IWUSR) in p7zip | ||
378 | Attrib |= FILE_ATTRIBUTE_READONLY; | ||
379 | // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink() | ||
380 | a &= MY_LIN_S_IFMT; | ||
381 | if (a == MY_LIN_S_IFLNK) | ||
382 | Attrib |= (a << 16); | ||
383 | #else | ||
384 | Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; | ||
385 | #endif | ||
386 | Attrib_Defined = true; | ||
387 | } | ||
388 | } _fi; | ||
389 | |||
390 | UInt32 _index; | ||
391 | UInt64 _curSize; | 427 | UInt64 _curSize; |
392 | UInt64 _fileLength_that_WasSet; | 428 | UInt64 _fileLength_that_WasSet; |
429 | UInt32 _index; | ||
430 | |||
431 | // #ifdef SUPPORT_ALT_STREAMS | ||
432 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
433 | DWORD _altStream_NeedRestore_AttribVal; | ||
434 | FString _altStream_NeedRestore_Attrib_for_parentFsPath; | ||
435 | #endif | ||
436 | // #endif | ||
393 | 437 | ||
394 | COutFileStream *_outFileStreamSpec; | 438 | COutFileStream *_outFileStreamSpec; |
395 | CMyComPtr<ISequentialOutStream> _outFileStream; | 439 | CMyComPtr<ISequentialOutStream> _outFileStream; |
@@ -398,9 +442,7 @@ private: | |||
398 | CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; | 442 | CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; |
399 | CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; | 443 | CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; |
400 | 444 | ||
401 | |||
402 | #ifndef Z7_SFX | 445 | #ifndef Z7_SFX |
403 | |||
404 | COutStreamWithHash *_hashStreamSpec; | 446 | COutStreamWithHash *_hashStreamSpec; |
405 | CMyComPtr<ISequentialOutStream> _hashStream; | 447 | CMyComPtr<ISequentialOutStream> _hashStream; |
406 | bool _hashStreamWasUsed; | 448 | bool _hashStreamWasUsed; |
@@ -411,11 +453,9 @@ private: | |||
411 | 453 | ||
412 | UStringVector _removePathParts; | 454 | UStringVector _removePathParts; |
413 | 455 | ||
414 | CMyComPtr<ICompressProgressInfo> _localProgress; | ||
415 | UInt64 _packTotal; | 456 | UInt64 _packTotal; |
416 | |||
417 | UInt64 _progressTotal; | 457 | UInt64 _progressTotal; |
418 | bool _progressTotal_Defined; | 458 | // bool _progressTotal_Defined; |
419 | 459 | ||
420 | CObjectVector<CDirPathTime> _extractedFolders; | 460 | CObjectVector<CDirPathTime> _extractedFolders; |
421 | 461 | ||
@@ -423,31 +463,28 @@ private: | |||
423 | // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; | 463 | // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; |
424 | #endif | 464 | #endif |
425 | 465 | ||
426 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | 466 | void CreateComplexDirectory( |
427 | bool _saclEnabled; | 467 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath); |
428 | #endif | ||
429 | |||
430 | void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); | ||
431 | HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft); | 468 | HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft); |
432 | HRESULT GetUnpackSize(); | 469 | HRESULT GetUnpackSize(); |
433 | 470 | ||
434 | FString Hash_GetFullFilePath(); | 471 | FString Hash_GetFullFilePath(); |
435 | 472 | ||
436 | void SetAttrib(); | 473 | void SetAttrib() const; |
437 | 474 | ||
438 | public: | 475 | public: |
439 | HRESULT SendMessageError(const char *message, const FString &path); | 476 | HRESULT SendMessageError(const char *message, const FString &path) const; |
440 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path); | 477 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const; |
441 | HRESULT SendMessageError_with_LastError(const char *message, const FString &path); | 478 | HRESULT SendMessageError_with_LastError(const char *message, const FString &path) const; |
442 | HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); | 479 | HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const; |
480 | HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2) const; | ||
443 | 481 | ||
444 | public: | 482 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
445 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
446 | NExtract::NZoneIdMode::EEnum ZoneMode; | 483 | NExtract::NZoneIdMode::EEnum ZoneMode; |
447 | CByteBuffer ZoneBuf; | 484 | CByteBuffer ZoneBuf; |
448 | #endif | 485 | #endif |
449 | 486 | ||
450 | CLocalProgress *LocalProgressSpec; | 487 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> LocalProgressSpec; |
451 | 488 | ||
452 | UInt64 NumFolders; | 489 | UInt64 NumFolders; |
453 | UInt64 NumFiles; | 490 | UInt64 NumFiles; |
@@ -468,11 +505,11 @@ public: | |||
468 | _multiArchives = multiArchives; | 505 | _multiArchives = multiArchives; |
469 | _pathMode = pathMode; | 506 | _pathMode = pathMode; |
470 | _overwriteMode = overwriteMode; | 507 | _overwriteMode = overwriteMode; |
471 | #if defined(_WIN32) && !defined(UNDER_CE) | 508 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
472 | ZoneMode = zoneMode; | 509 | ZoneMode = zoneMode; |
473 | #else | 510 | #else |
474 | UNUSED_VAR(zoneMode) | 511 | UNUSED_VAR(zoneMode) |
475 | #endif | 512 | #endif |
476 | _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; | 513 | _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; |
477 | NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; | 514 | NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; |
478 | } | 515 | } |
@@ -503,23 +540,32 @@ public: | |||
503 | UInt64 packSize); | 540 | UInt64 packSize); |
504 | 541 | ||
505 | 542 | ||
506 | #ifdef SUPPORT_LINKS | 543 | #ifdef SUPPORT_LINKS |
507 | 544 | ||
508 | private: | 545 | private: |
509 | CHardLinks _hardLinks; | 546 | CHardLinks _hardLinks; |
547 | CObjectVector<CPostLink> _postLinks; | ||
510 | CLinkInfo _link; | 548 | CLinkInfo _link; |
549 | // const void *NtReparse_Data; | ||
550 | // UInt32 NtReparse_Size; | ||
511 | 551 | ||
512 | // FString _copyFile_Path; | 552 | // FString _copyFile_Path; |
513 | // HRESULT MyCopyFile(ISequentialOutStream *outStream); | 553 | // HRESULT MyCopyFile(ISequentialOutStream *outStream); |
514 | HRESULT Link(const FString &fullProcessedPath); | ||
515 | HRESULT ReadLink(); | 554 | HRESULT ReadLink(); |
555 | HRESULT SetLink( | ||
556 | const FString &fullProcessedPath_from, | ||
557 | const CLinkInfo &linkInfo, | ||
558 | bool &linkWasSet); | ||
559 | HRESULT SetPostLinks() const; | ||
516 | 560 | ||
517 | public: | 561 | public: |
518 | // call PrepareHardLinks() after Init() | 562 | HRESULT CreateHardLink2(const FString &newFilePath, |
563 | const FString &existFilePath, bool &link_was_Created) const; | ||
564 | HRESULT DeleteLinkFileAlways_or_RemoveEmptyDir(const FString &path, bool checkThatFileIsEmpty) const; | ||
519 | HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items | 565 | HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items |
566 | #endif | ||
520 | 567 | ||
521 | #endif | 568 | private: |
522 | |||
523 | 569 | ||
524 | #ifdef SUPPORT_ALT_STREAMS | 570 | #ifdef SUPPORT_ALT_STREAMS |
525 | CObjectVector<CIndexToPathPair> _renamedFiles; | 571 | CObjectVector<CIndexToPathPair> _renamedFiles; |
@@ -527,6 +573,7 @@ public: | |||
527 | 573 | ||
528 | // call it after Init() | 574 | // call it after Init() |
529 | 575 | ||
576 | public: | ||
530 | #ifndef Z7_SFX | 577 | #ifndef Z7_SFX |
531 | void SetBaseParentFolderIndex(UInt32 indexInArc) | 578 | void SetBaseParentFolderIndex(UInt32 indexInArc) |
532 | { | 579 | { |
@@ -548,28 +595,16 @@ private: | |||
548 | 595 | ||
549 | HRESULT Read_fi_Props(); | 596 | HRESULT Read_fi_Props(); |
550 | void CorrectPathParts(); | 597 | void CorrectPathParts(); |
551 | void GetFiTimesCAM(CFiTimesCAM &pt); | ||
552 | void CreateFolders(); | 598 | void CreateFolders(); |
553 | 599 | ||
554 | bool _isRenamed; | ||
555 | HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); | 600 | HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); |
556 | HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); | 601 | HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); |
557 | HRESULT GetItem(UInt32 index); | 602 | HRESULT GetItem(UInt32 index); |
558 | 603 | ||
559 | HRESULT CloseFile(); | 604 | HRESULT CloseFile(); |
560 | HRESULT CloseReparseAndFile(); | 605 | HRESULT CloseReparseAndFile(); |
561 | HRESULT CloseReparseAndFile2(); | ||
562 | HRESULT SetDirsTimes(); | 606 | HRESULT SetDirsTimes(); |
563 | 607 | HRESULT SetSecurityInfo(UInt32 indexInArc, const FString &path) const; | |
564 | const void *NtReparse_Data; | ||
565 | UInt32 NtReparse_Size; | ||
566 | |||
567 | #ifdef SUPPORT_LINKS | ||
568 | HRESULT SetFromLinkPath( | ||
569 | const FString &fullProcessedPath, | ||
570 | const CLinkInfo &linkInfo, | ||
571 | bool &linkWasSet); | ||
572 | #endif | ||
573 | }; | 608 | }; |
574 | 609 | ||
575 | 610 | ||
@@ -599,7 +634,8 @@ struct CArchiveExtractCallback_Closer | |||
599 | 634 | ||
600 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); | 635 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); |
601 | 636 | ||
602 | void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf); | 637 | bool Is_ZoneId_StreamName(const wchar_t *s); |
638 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf); | ||
603 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf); | 639 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf); |
604 | 640 | ||
605 | #endif | 641 | #endif |
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index e1ca846..eb24e7f 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp | |||
@@ -871,14 +871,27 @@ struct CAffinityMode | |||
871 | unsigned NumCoreThreads; | 871 | unsigned NumCoreThreads; |
872 | unsigned NumCores; | 872 | unsigned NumCores; |
873 | // unsigned DivideNum; | 873 | // unsigned DivideNum; |
874 | |||
875 | #ifdef _WIN32 | ||
876 | unsigned NumGroups; | ||
877 | #endif | ||
878 | |||
874 | UInt32 Sizes[NUM_CPU_LEVELS_MAX]; | 879 | UInt32 Sizes[NUM_CPU_LEVELS_MAX]; |
875 | 880 | ||
876 | void SetLevels(unsigned numCores, unsigned numCoreThreads); | 881 | void SetLevels(unsigned numCores, unsigned numCoreThreads); |
877 | DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; | 882 | DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; |
878 | bool NeedAffinity() const { return NumBundleThreads != 0; } | 883 | bool NeedAffinity() const { return NumBundleThreads != 0; } |
879 | 884 | ||
885 | #ifdef _WIN32 | ||
886 | bool NeedGroupsMode() const { return NumGroups > 1; } | ||
887 | #endif | ||
888 | |||
880 | WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_TYPE startAddress, LPVOID parameter, UInt32 bundleIndex) const | 889 | WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_TYPE startAddress, LPVOID parameter, UInt32 bundleIndex) const |
881 | { | 890 | { |
891 | #ifdef _WIN32 | ||
892 | if (NeedGroupsMode()) // we need fix for bundleIndex usage | ||
893 | return thread.Create_With_Group(startAddress, parameter, bundleIndex % NumGroups); | ||
894 | #endif | ||
882 | if (NeedAffinity()) | 895 | if (NeedAffinity()) |
883 | { | 896 | { |
884 | CCpuSet cpuSet; | 897 | CCpuSet cpuSet; |
@@ -892,6 +905,9 @@ struct CAffinityMode | |||
892 | NumBundleThreads(0), | 905 | NumBundleThreads(0), |
893 | NumLevels(0), | 906 | NumLevels(0), |
894 | NumCoreThreads(1) | 907 | NumCoreThreads(1) |
908 | #ifdef _WIN32 | ||
909 | , NumGroups(0) | ||
910 | #endif | ||
895 | // DivideNum(1) | 911 | // DivideNum(1) |
896 | {} | 912 | {} |
897 | }; | 913 | }; |
@@ -1288,22 +1304,28 @@ HRESULT CEncoderInfo::Generate() | |||
1288 | if (scp) | 1304 | if (scp) |
1289 | { | 1305 | { |
1290 | const UInt64 reduceSize = kBufferSize; | 1306 | const UInt64 reduceSize = kBufferSize; |
1291 | 1307 | /* in posix : new thread uses same affinity as parent thread, | |
1292 | /* in posix new thread uses same affinity as parent thread, | ||
1293 | so we don't need to send affinity to coder in posix */ | 1308 | so we don't need to send affinity to coder in posix */ |
1294 | UInt64 affMask; | 1309 | UInt64 affMask = 0; |
1295 | #if !defined(Z7_ST) && defined(_WIN32) | 1310 | UInt32 affinityGroup = (UInt32)(Int32)-1; |
1311 | // UInt64 affinityInGroup = 0; | ||
1312 | #if !defined(Z7_ST) && defined(_WIN32) | ||
1296 | { | 1313 | { |
1297 | CCpuSet cpuSet; | 1314 | CCpuSet cpuSet; |
1298 | affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); | 1315 | if (AffinityMode.NeedGroupsMode()) // we need fix for affinityInGroup also |
1316 | affinityGroup = EncoderIndex % AffinityMode.NumGroups; | ||
1317 | else | ||
1318 | affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); | ||
1299 | } | 1319 | } |
1300 | #else | 1320 | #endif |
1301 | affMask = 0; | 1321 | // affMask <<= 3; // debug line: to test no affinity in coder |
1302 | #endif | 1322 | // affMask = 0; // for debug |
1303 | // affMask <<= 3; // debug line: to test no affinity in coder; | 1323 | // affinityGroup = 0; // for debug |
1304 | // affMask = 0; | 1324 | // affinityInGroup = 1; // for debug |
1305 | 1325 | RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, | |
1306 | RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, (affMask != 0 ? &affMask : NULL))) | 1326 | affMask != 0 ? &affMask : NULL, |
1327 | affinityGroup != (UInt32)(Int32)-1 ? &affinityGroup : NULL, | ||
1328 | /* affinityInGroup != 0 ? &affinityInGroup : */ NULL)) | ||
1307 | } | 1329 | } |
1308 | else | 1330 | else |
1309 | { | 1331 | { |
@@ -2298,6 +2320,28 @@ HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) | |||
2298 | } | 2320 | } |
2299 | 2321 | ||
2300 | 2322 | ||
2323 | #if 1 | ||
2324 | #define HashUpdate(hf, data, size) hf->Update(data, size) | ||
2325 | #else | ||
2326 | // for debug: | ||
2327 | static void HashUpdate(IHasher *hf, const void *data, UInt32 size) | ||
2328 | { | ||
2329 | for (;;) | ||
2330 | { | ||
2331 | if (size == 0) | ||
2332 | return; | ||
2333 | UInt32 size2 = (size * 0x85EBCA87) % size / 8; | ||
2334 | // UInt32 size2 = size / 2; | ||
2335 | if (size2 == 0) | ||
2336 | size2 = 1; | ||
2337 | hf->Update(data, size2); | ||
2338 | data = (const void *)((const Byte *)data + size2); | ||
2339 | size -= size2; | ||
2340 | } | ||
2341 | } | ||
2342 | #endif | ||
2343 | |||
2344 | |||
2301 | HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, | 2345 | HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, |
2302 | const UInt32 *checkSum, IHasher *hf, | 2346 | const UInt32 *checkSum, IHasher *hf, |
2303 | IBenchPrintCallback *callback) | 2347 | IBenchPrintCallback *callback) |
@@ -2328,7 +2372,7 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, | |||
2328 | const size_t rem = size - pos; | 2372 | const size_t rem = size - pos; |
2329 | const UInt32 kStep = ((UInt32)1 << 31); | 2373 | const UInt32 kStep = ((UInt32)1 << 31); |
2330 | const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; | 2374 | const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; |
2331 | hf->Update(buf + pos, curSize); | 2375 | HashUpdate(hf, buf + pos, curSize); |
2332 | pos += curSize; | 2376 | pos += curSize; |
2333 | } | 2377 | } |
2334 | while (pos != size); | 2378 | while (pos != size); |
@@ -2742,14 +2786,20 @@ static const CBenchHash g_Hash[] = | |||
2742 | { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, | 2786 | { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, |
2743 | { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, | 2787 | { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, |
2744 | { 10, 256, 0x41b901d1, "CRC64" }, | 2788 | { 10, 256, 0x41b901d1, "CRC64" }, |
2745 | { 10, 64, 0x43eac94f, "XXH64" }, | 2789 | { 5, 64, 0x43eac94f, "XXH64" }, |
2746 | 2790 | { 2, 2340, 0x3398a904, "MD5" }, | |
2747 | { 10, 5100, 0x7913ba03, "SHA256:1" }, | 2791 | { 10, 2340, 0xff769021, "SHA1:1" }, |
2748 | { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, | ||
2749 | |||
2750 | { 10, 2340, 0xff769021, "SHA1:1" }, | ||
2751 | { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, | 2792 | { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, |
2752 | 2793 | { 10, 5100, 0x7913ba03, "SHA256:1" }, | |
2794 | { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, | ||
2795 | { 5, 3200, 0xe7aeb394, "SHA512:1" }, | ||
2796 | { 2, CMPLX((40 * 4 + 1) * 4 + 4), 0xe7aeb394, "SHA512:2" }, | ||
2797 | // { 10, 3428, 0x1cc99b18, "SHAKE128" }, | ||
2798 | // { 10, 4235, 0x74eaddc3, "SHAKE256" }, | ||
2799 | // { 10, 4000, 0xdf3e6863, "SHA3-224" }, | ||
2800 | { 5, 4200, 0xcecac10d, "SHA3-256" }, | ||
2801 | // { 10, 5538, 0x4e5d9163, "SHA3-384" }, | ||
2802 | // { 10, 8000, 0x96a58289, "SHA3-512" }, | ||
2753 | { 2, 4096, 0x85189d02, "BLAKE2sp:1" }, | 2803 | { 2, 4096, 0x85189d02, "BLAKE2sp:1" }, |
2754 | { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast | 2804 | { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast |
2755 | { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast | 2805 | { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast |
@@ -2934,7 +2984,7 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
2934 | { | 2984 | { |
2935 | AString s; | 2985 | AString s; |
2936 | // s.Add_UInt32(ti.numProcessThreads); | 2986 | // s.Add_UInt32(ti.numProcessThreads); |
2937 | unsigned numSysThreads = ti.GetNumSystemThreads(); | 2987 | const unsigned numSysThreads = ti.GetNumSystemThreads(); |
2938 | if (ti.GetNumProcessThreads() != numSysThreads) | 2988 | if (ti.GetNumProcessThreads() != numSysThreads) |
2939 | { | 2989 | { |
2940 | // if (ti.numProcessThreads != ti.numSysThreads) | 2990 | // if (ti.numProcessThreads != ti.numSysThreads) |
@@ -2964,6 +3014,35 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
2964 | } | 3014 | } |
2965 | #endif | 3015 | #endif |
2966 | } | 3016 | } |
3017 | #ifdef _WIN32 | ||
3018 | if (ti.Groups.GroupSizes.Size() > 1 || | ||
3019 | (ti.Groups.GroupSizes.Size() == 1 | ||
3020 | && ti.Groups.NumThreadsTotal != numSysThreads)) | ||
3021 | { | ||
3022 | s += " : "; | ||
3023 | s.Add_UInt32(ti.Groups.GroupSizes.Size()); | ||
3024 | s += " groups : "; | ||
3025 | if (ti.Groups.NumThreadsTotal == numSysThreads) | ||
3026 | { | ||
3027 | s.Add_UInt32(ti.Groups.NumThreadsTotal); | ||
3028 | s += " c : "; | ||
3029 | } | ||
3030 | UInt32 minSize, maxSize; | ||
3031 | ti.Groups.Get_GroupSize_Min_Max(minSize, maxSize); | ||
3032 | if (minSize == maxSize) | ||
3033 | { | ||
3034 | s.Add_UInt32(ti.Groups.GroupSizes[0]); | ||
3035 | s += " c/g"; | ||
3036 | } | ||
3037 | else | ||
3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) | ||
3039 | { | ||
3040 | if (i != 0) | ||
3041 | s.Add_Char(' '); | ||
3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); | ||
3043 | } | ||
3044 | } | ||
3045 | #endif | ||
2967 | return s; | 3046 | return s; |
2968 | } | 3047 | } |
2969 | 3048 | ||
@@ -3687,7 +3766,7 @@ HRESULT Bench( | |||
3687 | return E_FAIL; | 3766 | return E_FAIL; |
3688 | 3767 | ||
3689 | UInt32 numCPUs = 1; | 3768 | UInt32 numCPUs = 1; |
3690 | UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; | 3769 | size_t ramSize = (size_t)sizeof(size_t) << 29; |
3691 | 3770 | ||
3692 | NSystem::CProcessAffinity threadsInfo; | 3771 | NSystem::CProcessAffinity threadsInfo; |
3693 | threadsInfo.InitST(); | 3772 | threadsInfo.InitST(); |
@@ -3725,9 +3804,13 @@ HRESULT Bench( | |||
3725 | UInt64 complexInCommands = kComplexInCommands; | 3804 | UInt64 complexInCommands = kComplexInCommands; |
3726 | UInt32 numThreads_Start = 1; | 3805 | UInt32 numThreads_Start = 1; |
3727 | 3806 | ||
3728 | #ifndef Z7_ST | 3807 | #ifndef Z7_ST |
3729 | CAffinityMode affinityMode; | 3808 | CAffinityMode affinityMode; |
3730 | #endif | 3809 | #ifdef _WIN32 |
3810 | if (threadsInfo.IsGroupMode && threadsInfo.Groups.GroupSizes.Size() > 1) | ||
3811 | affinityMode.NumGroups = threadsInfo.Groups.GroupSizes.Size(); | ||
3812 | #endif | ||
3813 | #endif | ||
3731 | 3814 | ||
3732 | 3815 | ||
3733 | COneMethodInfo method; | 3816 | COneMethodInfo method; |
@@ -4580,6 +4663,8 @@ HRESULT Bench( | |||
4580 | 4663 | ||
4581 | if (!dictIsDefined && !onlyHashBench) | 4664 | if (!dictIsDefined && !onlyHashBench) |
4582 | { | 4665 | { |
4666 | // we use dicSizeLog and dicSizeLog_Main for data size. | ||
4667 | // also we use it to reduce dictionary size of LZMA encoder via NCoderPropID::kReduceSize. | ||
4583 | const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); | 4668 | const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); |
4584 | unsigned dicSizeLog = dicSizeLog_Main; | 4669 | unsigned dicSizeLog = dicSizeLog_Main; |
4585 | 4670 | ||
@@ -4831,7 +4916,7 @@ HRESULT Bench( | |||
4831 | if (AreSameMethodNames(benchMethod, methodName)) | 4916 | if (AreSameMethodNames(benchMethod, methodName)) |
4832 | { | 4917 | { |
4833 | if (benchProps.IsEmpty() | 4918 | if (benchProps.IsEmpty() |
4834 | || (benchProps == "x5" && method.PropsString.IsEmpty()) | 4919 | || (benchProps.IsEqualTo("x5") && method.PropsString.IsEmpty()) |
4835 | || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) | 4920 | || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) |
4836 | { | 4921 | { |
4837 | callback.BenchProps.EncComplex = h.EncComplex; | 4922 | callback.BenchProps.EncComplex = h.EncComplex; |
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index 0758547..cada2e6 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp | |||
@@ -671,7 +671,7 @@ static HRESULT EnumerateForItem( | |||
671 | } | 671 | } |
672 | 672 | ||
673 | #if defined(_WIN32) | 673 | #if defined(_WIN32) |
674 | if (needAltStreams && dirItems.ScanAltStreams) | 674 | if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream) |
675 | { | 675 | { |
676 | RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, | 676 | RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, |
677 | phyPrefix + fi.Name, // with (fi.Name) | 677 | phyPrefix + fi.Name, // with (fi.Name) |
@@ -929,7 +929,7 @@ static HRESULT EnumerateDirItems( | |||
929 | } | 929 | } |
930 | 930 | ||
931 | #if defined(_WIN32) | 931 | #if defined(_WIN32) |
932 | if (needAltStreams && dirItems.ScanAltStreams) | 932 | if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream) |
933 | { | 933 | { |
934 | UStringVector pathParts; | 934 | UStringVector pathParts; |
935 | pathParts.Add(fs2us(fi.Name)); | 935 | pathParts.Add(fs2us(fi.Name)); |
@@ -1213,11 +1213,13 @@ HRESULT CDirItems::FillFixedReparse() | |||
1213 | // continue; // for debug | 1213 | // continue; // for debug |
1214 | if (!item.Has_Attrib_ReparsePoint()) | 1214 | if (!item.Has_Attrib_ReparsePoint()) |
1215 | continue; | 1215 | continue; |
1216 | 1216 | /* | |
1217 | We want to get properties of target file instead of properies of symbolic link. | ||
1218 | Probably this code is unused, because | ||
1219 | CFileInfo::Find(with followLink = true) called Fill_From_ByHandleFileInfo() already. | ||
1220 | */ | ||
1217 | // if (item.IsDir()) continue; | 1221 | // if (item.IsDir()) continue; |
1218 | |||
1219 | const FString phyPath = GetPhyPath(i); | 1222 | const FString phyPath = GetPhyPath(i); |
1220 | |||
1221 | NFind::CFileInfo fi; | 1223 | NFind::CFileInfo fi; |
1222 | if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() | 1224 | if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() |
1223 | { | 1225 | { |
@@ -1228,38 +1230,13 @@ HRESULT CDirItems::FillFixedReparse() | |||
1228 | item.Attrib = fi.Attrib; | 1230 | item.Attrib = fi.Attrib; |
1229 | continue; | 1231 | continue; |
1230 | } | 1232 | } |
1231 | |||
1232 | /* | ||
1233 | // we request properties of target file instead of properies of symbolic link | ||
1234 | // here we also can manually parse unsupported links (like WSL links) | ||
1235 | NIO::CInFile inFile; | ||
1236 | if (inFile.Open(phyPath)) | ||
1237 | { | ||
1238 | BY_HANDLE_FILE_INFORMATION info; | ||
1239 | if (inFile.GetFileInformation(&info)) | ||
1240 | { | ||
1241 | // Stat.FilesSize doesn't contain item.Size already | ||
1242 | // Stat.FilesSize -= item.Size; | ||
1243 | item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | ||
1244 | Stat.FilesSize += item.Size; | ||
1245 | item.CTime = info.ftCreationTime; | ||
1246 | item.ATime = info.ftLastAccessTime; | ||
1247 | item.MTime = info.ftLastWriteTime; | ||
1248 | item.Attrib = info.dwFileAttributes; | ||
1249 | continue; | ||
1250 | } | ||
1251 | } | ||
1252 | */ | ||
1253 | |||
1254 | RINOK(AddError(phyPath)) | 1233 | RINOK(AddError(phyPath)) |
1255 | continue; | 1234 | continue; |
1256 | } | 1235 | } |
1257 | 1236 | ||
1258 | // (SymLinks == true) here | 1237 | // (SymLinks == true) |
1259 | |||
1260 | if (item.ReparseData.Size() == 0) | 1238 | if (item.ReparseData.Size() == 0) |
1261 | continue; | 1239 | continue; |
1262 | |||
1263 | // if (item.Size == 0) | 1240 | // if (item.Size == 0) |
1264 | { | 1241 | { |
1265 | // 20.03: we use Reparse Data instead of real data | 1242 | // 20.03: we use Reparse Data instead of real data |
@@ -1277,7 +1254,7 @@ HRESULT CDirItems::FillFixedReparse() | |||
1277 | /* imagex/WIM reduces absolute paths in links (raparse data), | 1254 | /* imagex/WIM reduces absolute paths in links (raparse data), |
1278 | if we archive non root folder. We do same thing here */ | 1255 | if we archive non root folder. We do same thing here */ |
1279 | 1256 | ||
1280 | bool isWSL = false; | 1257 | // bool isWSL = false; |
1281 | if (attr.IsSymLink_WSL()) | 1258 | if (attr.IsSymLink_WSL()) |
1282 | { | 1259 | { |
1283 | // isWSL = true; | 1260 | // isWSL = true; |
@@ -1314,21 +1291,27 @@ HRESULT CDirItems::FillFixedReparse() | |||
1314 | continue; | 1291 | continue; |
1315 | if (rootPrefixSize == prefix.Len()) | 1292 | if (rootPrefixSize == prefix.Len()) |
1316 | continue; // simple case: paths are from root | 1293 | continue; // simple case: paths are from root |
1317 | |||
1318 | if (link.Len() <= prefix.Len()) | 1294 | if (link.Len() <= prefix.Len()) |
1319 | continue; | 1295 | continue; |
1320 | |||
1321 | if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) | 1296 | if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) |
1322 | continue; | 1297 | continue; |
1323 | 1298 | ||
1324 | UString newLink = prefix.Left(rootPrefixSize); | 1299 | UString newLink = prefix.Left(rootPrefixSize); |
1325 | newLink += link.Ptr(prefix.Len()); | 1300 | newLink += link.Ptr(prefix.Len()); |
1326 | 1301 | ||
1327 | CByteBuffer data; | 1302 | CByteBuffer &data = item.ReparseData2; |
1328 | bool isSymLink = !attr.IsMountPoint(); | 1303 | /* |
1329 | if (!FillLinkData(data, newLink, isSymLink, isWSL)) | 1304 | if (isWSL) |
1305 | { | ||
1306 | Convert_WinPath_to_WslLinuxPath(newLink, true); // is absolute : change it | ||
1307 | FillLinkData_WslLink(data, newLink); | ||
1308 | } | ||
1309 | else | ||
1310 | */ | ||
1311 | FillLinkData_WinLink(data, newLink, !attr.IsMountPoint()); | ||
1312 | if (data.Size() == 0) | ||
1330 | continue; | 1313 | continue; |
1331 | item.ReparseData2 = data; | 1314 | // item.ReparseData2 = data; |
1332 | } | 1315 | } |
1333 | return S_OK; | 1316 | return S_OK; |
1334 | } | 1317 | } |
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 010b01c..0301976 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp | |||
@@ -389,7 +389,7 @@ HRESULT Extract( | |||
389 | { | 389 | { |
390 | UString s = arcPath.Ptr(pos + 1); | 390 | UString s = arcPath.Ptr(pos + 1); |
391 | int index = codecs->FindFormatForExtension(s); | 391 | int index = codecs->FindFormatForExtension(s); |
392 | if (index >= 0 && s == L"001") | 392 | if (index >= 0 && s.IsEqualTo("001")) |
393 | { | 393 | { |
394 | s = arcPath.Left(pos); | 394 | s = arcPath.Left(pos); |
395 | pos = s.ReverseFind(L'.'); | 395 | pos = s.ReverseFind(L'.'); |
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 88da4ad..5ca5e66 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp | |||
@@ -208,7 +208,7 @@ void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UString | |||
208 | if (parts.Size() > 1 && parts[1].IsEmpty()) | 208 | if (parts.Size() > 1 && parts[1].IsEmpty()) |
209 | { | 209 | { |
210 | i = 2; | 210 | i = 2; |
211 | if (parts.Size() > 2 && parts[2] == L"?") | 211 | if (parts.Size() > 2 && parts[2].IsEqualTo("?")) |
212 | { | 212 | { |
213 | i = 3; | 213 | i = 3; |
214 | if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) | 214 | if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) |
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp index f3d65ef..f026f80 100644 --- a/CPP/7zip/UI/Common/HashCalc.cpp +++ b/CPP/7zip/UI/Common/HashCalc.cpp | |||
@@ -62,7 +62,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto | |||
62 | if (m.MethodName.IsEmpty()) | 62 | if (m.MethodName.IsEmpty()) |
63 | m.MethodName = k_DefaultHashMethod; | 63 | m.MethodName = k_DefaultHashMethod; |
64 | 64 | ||
65 | if (m.MethodName == "*") | 65 | if (m.MethodName.IsEqualTo("*")) |
66 | { | 66 | { |
67 | CRecordVector<CMethodId> tempMethods; | 67 | CRecordVector<CMethodId> tempMethods; |
68 | GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); | 68 | GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); |
@@ -431,6 +431,19 @@ static void WriteLine(CDynLimBuf &hashFileString, | |||
431 | } | 431 | } |
432 | 432 | ||
433 | 433 | ||
434 | static void Convert_TagName_to_MethodName(AString &method) | ||
435 | { | ||
436 | // we need to convert at least SHA512/256 to SHA512-256, and SHA512/224 to SHA512-224 | ||
437 | // but we convert any '/' to '-'. | ||
438 | method.Replace('/', '-'); | ||
439 | } | ||
440 | |||
441 | static void Convert_MethodName_to_TagName(AString &method) | ||
442 | { | ||
443 | if (method.IsPrefixedBy_Ascii_NoCase("SHA512-2")) | ||
444 | method.ReplaceOneCharAtPos(6, '/'); | ||
445 | } | ||
446 | |||
434 | 447 | ||
435 | static void WriteLine(CDynLimBuf &hashFileString, | 448 | static void WriteLine(CDynLimBuf &hashFileString, |
436 | const CHashOptionsLocal &options, | 449 | const CHashOptionsLocal &options, |
@@ -440,8 +453,10 @@ static void WriteLine(CDynLimBuf &hashFileString, | |||
440 | { | 453 | { |
441 | AString methodName; | 454 | AString methodName; |
442 | if (!hb.Hashers.IsEmpty()) | 455 | if (!hb.Hashers.IsEmpty()) |
456 | { | ||
443 | methodName = hb.Hashers[0].Name; | 457 | methodName = hb.Hashers[0].Name; |
444 | 458 | Convert_MethodName_to_TagName(methodName); | |
459 | } | ||
445 | AString hashesString; | 460 | AString hashesString; |
446 | AddHashResultLine(hashesString, hb.Hashers); | 461 | AddHashResultLine(hashesString, hb.Hashers); |
447 | WriteLine(hashFileString, options, path, isDir, methodName, hashesString); | 462 | WriteLine(hashFileString, options, path, isDir, methodName, hashesString); |
@@ -752,7 +767,7 @@ bool CHashPair::ParseCksum(const char *s) | |||
752 | Name = end; | 767 | Name = end; |
753 | 768 | ||
754 | Hash.Alloc(4); | 769 | Hash.Alloc(4); |
755 | SetBe32(Hash, crc) | 770 | SetBe32a(Hash, crc) |
756 | 771 | ||
757 | Size_from_Arc = size; | 772 | Size_from_Arc = size; |
758 | Size_from_Arc_Defined = true; | 773 | Size_from_Arc_Defined = true; |
@@ -773,48 +788,87 @@ static const char * const k_CsumMethodNames[] = | |||
773 | { | 788 | { |
774 | "sha256" | 789 | "sha256" |
775 | , "sha224" | 790 | , "sha224" |
776 | // , "sha512/224" | 791 | , "sha512-224" |
777 | // , "sha512/256" | 792 | , "sha512-256" |
778 | , "sha512" | ||
779 | , "sha384" | 793 | , "sha384" |
794 | , "sha512" | ||
795 | , "sha3-224" | ||
796 | , "sha3-256" | ||
797 | , "sha3-384" | ||
798 | , "sha3-512" | ||
799 | // , "shake128" | ||
800 | // , "shake256" | ||
780 | , "sha1" | 801 | , "sha1" |
802 | , "sha2" | ||
803 | , "sha3" | ||
804 | , "sha" | ||
781 | , "md5" | 805 | , "md5" |
806 | , "blake2s" | ||
782 | , "blake2b" | 807 | , "blake2b" |
783 | , "crc64" | 808 | , "blake2sp" |
809 | , "xxh64" | ||
784 | , "crc32" | 810 | , "crc32" |
811 | , "crc64" | ||
785 | , "cksum" | 812 | , "cksum" |
786 | }; | 813 | }; |
787 | 814 | ||
788 | static UString GetMethod_from_FileName(const UString &name) | 815 | |
816 | // returns true, if (method) is known hash method or hash method group name. | ||
817 | static bool GetMethod_from_FileName(const UString &name, AString &method) | ||
789 | { | 818 | { |
819 | method.Empty(); | ||
790 | AString s; | 820 | AString s; |
791 | ConvertUnicodeToUTF8(name, s); | 821 | ConvertUnicodeToUTF8(name, s); |
792 | const int dotPos = s.ReverseFind_Dot(); | 822 | const int dotPos = s.ReverseFind_Dot(); |
793 | const char *src = s.Ptr(); | ||
794 | bool isExtension = false; | ||
795 | if (dotPos >= 0) | 823 | if (dotPos >= 0) |
796 | { | 824 | { |
797 | isExtension = true; | 825 | method = s.Ptr(dotPos + 1); |
798 | src = s.Ptr(dotPos + 1); | 826 | if (method.IsEqualTo_Ascii_NoCase("txt") || |
827 | method.IsEqualTo_Ascii_NoCase("asc")) | ||
828 | { | ||
829 | method.Empty(); | ||
830 | const int dotPos2 = s.Find('.'); | ||
831 | if (dotPos2 >= 0) | ||
832 | s.DeleteFrom(dotPos2); | ||
833 | } | ||
799 | } | 834 | } |
800 | const char *m = ""; | 835 | if (method.IsEmpty()) |
836 | { | ||
837 | // we support file names with "sum" and "sums" postfixes: "sha256sum", "sha256sums" | ||
838 | unsigned size; | ||
839 | if (s.Len() > 4 && StringsAreEqualNoCase_Ascii(s.RightPtr(4), "sums")) | ||
840 | size = 4; | ||
841 | else if (s.Len() > 3 && StringsAreEqualNoCase_Ascii(s.RightPtr(3), "sum")) | ||
842 | size = 3; | ||
843 | else | ||
844 | return false; | ||
845 | method = s; | ||
846 | method.DeleteFrom(s.Len() - size); | ||
847 | } | ||
848 | |||
801 | unsigned i; | 849 | unsigned i; |
802 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) | 850 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) |
803 | { | 851 | { |
804 | m = k_CsumMethodNames[i]; | 852 | const char *m = k_CsumMethodNames[i]; |
805 | if (isExtension) | 853 | if (method.IsEqualTo_Ascii_NoCase(m)) |
806 | { | 854 | { |
807 | if (StringsAreEqual_Ascii(src, m)) | 855 | // method = m; // we can get lowcase |
808 | break; | 856 | return true; |
809 | } | 857 | } |
810 | else if (IsString1PrefixedByString2_NoCase_Ascii(src, m)) | ||
811 | if (StringsAreEqual_Ascii(src + strlen(m), "sums")) | ||
812 | break; | ||
813 | } | 858 | } |
814 | UString res; | 859 | |
815 | if (i != Z7_ARRAY_SIZE(k_CsumMethodNames)) | 860 | /* |
816 | res = m; | 861 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) |
817 | return res; | 862 | { |
863 | const char *m = k_CsumMethodNames[i]; | ||
864 | if (method.IsPrefixedBy_Ascii_NoCase(m)) | ||
865 | { | ||
866 | method = m; // we get lowcase | ||
867 | return true; | ||
868 | } | ||
869 | } | ||
870 | */ | ||
871 | return false; | ||
818 | } | 872 | } |
819 | 873 | ||
820 | 874 | ||
@@ -1039,7 +1093,7 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data | |||
1039 | if (propID == kpidChecksum) | 1093 | if (propID == kpidChecksum) |
1040 | { | 1094 | { |
1041 | const CHashPair &hp = HashPairs[index]; | 1095 | const CHashPair &hp = HashPairs[index]; |
1042 | if (hp.Hash.Size() > 0) | 1096 | if (hp.Hash.Size() != 0) |
1043 | { | 1097 | { |
1044 | *data = hp.Hash; | 1098 | *data = hp.Hash; |
1045 | *dataSize = (UInt32)hp.Hash.Size(); | 1099 | *dataSize = (UInt32)hp.Hash.Size(); |
@@ -1092,11 +1146,6 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
1092 | s.Add_UInt32(_hashSize * 8); | 1146 | s.Add_UInt32(_hashSize * 8); |
1093 | s += "-bit"; | 1147 | s += "-bit"; |
1094 | } | 1148 | } |
1095 | if (!_nameExtenstion.IsEmpty()) | ||
1096 | { | ||
1097 | s.Add_Space_if_NotEmpty(); | ||
1098 | s += _nameExtenstion; | ||
1099 | } | ||
1100 | if (_is_PgpMethod) | 1149 | if (_is_PgpMethod) |
1101 | { | 1150 | { |
1102 | Add_OptSpace_String(s, "PGP"); | 1151 | Add_OptSpace_String(s, "PGP"); |
@@ -1112,6 +1161,18 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
1112 | Add_OptSpace_String(s, "TAG"); | 1161 | Add_OptSpace_String(s, "TAG"); |
1113 | if (_are_there_Dirs) | 1162 | if (_are_there_Dirs) |
1114 | Add_OptSpace_String(s, "DIRS"); | 1163 | Add_OptSpace_String(s, "DIRS"); |
1164 | if (!_method_from_FileName.IsEmpty()) | ||
1165 | { | ||
1166 | Add_OptSpace_String(s, "filename_method:"); | ||
1167 | s += _method_from_FileName; | ||
1168 | if (!_is_KnownMethod_in_FileName) | ||
1169 | s += ":UNKNOWN"; | ||
1170 | } | ||
1171 | if (!_methods.IsEmpty()) | ||
1172 | { | ||
1173 | Add_OptSpace_String(s, "cmd_method:"); | ||
1174 | s += _methods[0]; | ||
1175 | } | ||
1115 | prop = s; | 1176 | prop = s; |
1116 | break; | 1177 | break; |
1117 | } | 1178 | } |
@@ -1220,6 +1281,15 @@ static HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOp | |||
1220 | } | 1281 | } |
1221 | 1282 | ||
1222 | 1283 | ||
1284 | static bool isThere_Zero_Byte(const Byte *data, size_t size) | ||
1285 | { | ||
1286 | for (size_t i = 0; i < size; i++) | ||
1287 | if (data[i] == 0) | ||
1288 | return true; | ||
1289 | return false; | ||
1290 | } | ||
1291 | |||
1292 | |||
1223 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) | 1293 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) |
1224 | { | 1294 | { |
1225 | COM_TRY_BEGIN | 1295 | COM_TRY_BEGIN |
@@ -1231,17 +1301,9 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
1231 | 1301 | ||
1232 | CObjectVector<CHashPair> &pairs = HashPairs; | 1302 | CObjectVector<CHashPair> &pairs = HashPairs; |
1233 | 1303 | ||
1234 | bool zeroMode = false; | 1304 | const bool zeroMode = isThere_Zero_Byte(buf, buf.Size()); |
1235 | bool cr_lf_Mode = false; | ||
1236 | { | ||
1237 | for (size_t i = 0; i < buf.Size(); i++) | ||
1238 | if (buf.ConstData()[i] == 0) | ||
1239 | { | ||
1240 | zeroMode = true; | ||
1241 | break; | ||
1242 | } | ||
1243 | } | ||
1244 | _is_ZeroMode = zeroMode; | 1305 | _is_ZeroMode = zeroMode; |
1306 | bool cr_lf_Mode = false; | ||
1245 | if (!zeroMode) | 1307 | if (!zeroMode) |
1246 | cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); | 1308 | cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); |
1247 | 1309 | ||
@@ -1255,13 +1317,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
1255 | NCOM::CPropVariant prop; | 1317 | NCOM::CPropVariant prop; |
1256 | RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) | 1318 | RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) |
1257 | if (prop.vt == VT_BSTR) | 1319 | if (prop.vt == VT_BSTR) |
1258 | _nameExtenstion = GetMethod_from_FileName(prop.bstrVal); | 1320 | _is_KnownMethod_in_FileName = GetMethod_from_FileName(prop.bstrVal, _method_from_FileName); |
1259 | } | 1321 | } |
1260 | } | 1322 | } |
1261 | 1323 | ||
1262 | bool cksumMode = false; | 1324 | if (!_methods.IsEmpty()) |
1263 | if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum")) | 1325 | { |
1264 | cksumMode = true; | 1326 | ConvertUnicodeToUTF8(_methods[0], _method_for_Extraction); |
1327 | } | ||
1328 | if (_method_for_Extraction.IsEmpty()) | ||
1329 | { | ||
1330 | // if (_is_KnownMethod_in_FileName) | ||
1331 | _method_for_Extraction = _method_from_FileName; | ||
1332 | } | ||
1333 | |||
1334 | const bool cksumMode = _method_for_Extraction.IsEqualTo_Ascii_NoCase("cksum"); | ||
1265 | _is_CksumMode = cksumMode; | 1335 | _is_CksumMode = cksumMode; |
1266 | 1336 | ||
1267 | size_t pos = 0; | 1337 | size_t pos = 0; |
@@ -1358,6 +1428,7 @@ void CHandler::ClearVars() | |||
1358 | _is_ZeroMode = false; | 1428 | _is_ZeroMode = false; |
1359 | _are_there_Tags = false; | 1429 | _are_there_Tags = false; |
1360 | _are_there_Dirs = false; | 1430 | _are_there_Dirs = false; |
1431 | _is_KnownMethod_in_FileName = false; | ||
1361 | _hashSize_Defined = false; | 1432 | _hashSize_Defined = false; |
1362 | _hashSize = 0; | 1433 | _hashSize = 0; |
1363 | } | 1434 | } |
@@ -1366,7 +1437,8 @@ void CHandler::ClearVars() | |||
1366 | Z7_COM7F_IMF(CHandler::Close()) | 1437 | Z7_COM7F_IMF(CHandler::Close()) |
1367 | { | 1438 | { |
1368 | ClearVars(); | 1439 | ClearVars(); |
1369 | _nameExtenstion.Empty(); | 1440 | _method_from_FileName.Empty(); |
1441 | _method_for_Extraction.Empty(); | ||
1370 | _pgpMethod.Empty(); | 1442 | _pgpMethod.Empty(); |
1371 | HashPairs.Clear(); | 1443 | HashPairs.Clear(); |
1372 | return S_OK; | 1444 | return S_OK; |
@@ -1393,19 +1465,73 @@ static bool CheckDigests(const Byte *a, const Byte *b, size_t size) | |||
1393 | } | 1465 | } |
1394 | 1466 | ||
1395 | 1467 | ||
1396 | static void AddDefaultMethod(UStringVector &methods, unsigned size) | 1468 | static void AddDefaultMethod(UStringVector &methods, |
1469 | const char *name, unsigned size) | ||
1397 | { | 1470 | { |
1471 | int shaVersion = -1; | ||
1472 | if (name) | ||
1473 | { | ||
1474 | if (StringsAreEqualNoCase_Ascii(name, "sha")) | ||
1475 | { | ||
1476 | shaVersion = 0; | ||
1477 | if (size == 0) | ||
1478 | size = 32; | ||
1479 | } | ||
1480 | else if (StringsAreEqualNoCase_Ascii(name, "sha1")) | ||
1481 | { | ||
1482 | shaVersion = 1; | ||
1483 | if (size == 0) | ||
1484 | size = 20; | ||
1485 | } | ||
1486 | else if (StringsAreEqualNoCase_Ascii(name, "sha2")) | ||
1487 | { | ||
1488 | shaVersion = 2; | ||
1489 | if (size == 0) | ||
1490 | size = 32; | ||
1491 | } | ||
1492 | else if (StringsAreEqualNoCase_Ascii(name, "sha3")) | ||
1493 | { | ||
1494 | if (size == 0 || | ||
1495 | size == 32) name = "sha3-256"; | ||
1496 | else if (size == 28) name = "sha3-224"; | ||
1497 | else if (size == 48) name = "sha3-384"; | ||
1498 | else if (size == 64) name = "sha3-512"; | ||
1499 | } | ||
1500 | else if (StringsAreEqualNoCase_Ascii(name, "sha512")) | ||
1501 | { | ||
1502 | // we allow any sha512 derived hash inside .sha512 file: | ||
1503 | if (size == 48) name = "sha384"; | ||
1504 | else if (size == 32) name = "sha512-256"; | ||
1505 | else if (size == 28) name = "sha512-224"; | ||
1506 | } | ||
1507 | if (shaVersion >= 0) | ||
1508 | name = NULL; | ||
1509 | } | ||
1510 | |||
1398 | const char *m = NULL; | 1511 | const char *m = NULL; |
1399 | if (size == 32) m = "sha256"; | 1512 | if (name) |
1400 | else if (size == 20) m = "sha1"; | 1513 | m = name; |
1401 | else if (size == 16) m = "md5"; | ||
1402 | else if (size == 8) m = "crc64"; | ||
1403 | else if (size == 4) m = "crc32"; | ||
1404 | else | 1514 | else |
1515 | { | ||
1516 | if (size == 64) m = "sha512"; | ||
1517 | else if (size == 48) m = "sha384"; | ||
1518 | else if (size == 32) m = "sha256"; | ||
1519 | else if (size == 28) m = "sha224"; | ||
1520 | else if (size == 20) m = "sha1"; | ||
1521 | else if (shaVersion < 0) | ||
1522 | { | ||
1523 | if (size == 16) m = "md5"; | ||
1524 | else if (size == 8) m = "crc64"; | ||
1525 | else if (size == 4) m = "crc32"; | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1529 | if (!m) | ||
1405 | return; | 1530 | return; |
1406 | #ifdef Z7_EXTERNAL_CODECS | 1531 | |
1532 | #ifdef Z7_EXTERNAL_CODECS | ||
1407 | const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; | 1533 | const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; |
1408 | #endif | 1534 | #endif |
1409 | CMethodId id; | 1535 | CMethodId id; |
1410 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS | 1536 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS |
1411 | AString(m), id)) | 1537 | AString(m), id)) |
@@ -1436,15 +1562,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1436 | CHashBundle hb_Glob; | 1562 | CHashBundle hb_Glob; |
1437 | // UStringVector methods = options.Methods; | 1563 | // UStringVector methods = options.Methods; |
1438 | UStringVector methods; | 1564 | UStringVector methods; |
1439 | 1565 | ||
1440 | if (methods.IsEmpty() && !_nameExtenstion.IsEmpty()) | 1566 | /* |
1567 | if (methods.IsEmpty() && !utf_nameExtenstion.IsEmpty() && !_hashSize_Defined) | ||
1441 | { | 1568 | { |
1442 | AString utf; | ||
1443 | ConvertUnicodeToUTF8(_nameExtenstion, utf); | ||
1444 | CMethodId id; | 1569 | CMethodId id; |
1445 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id)) | 1570 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf_nameExtenstion, id)) |
1446 | methods.Add(_nameExtenstion); | 1571 | methods.Add(_nameExtenstion); |
1447 | } | 1572 | } |
1573 | */ | ||
1448 | 1574 | ||
1449 | if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) | 1575 | if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) |
1450 | { | 1576 | { |
@@ -1453,12 +1579,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1453 | methods.Add(UString(_pgpMethod)); | 1579 | methods.Add(UString(_pgpMethod)); |
1454 | } | 1580 | } |
1455 | 1581 | ||
1582 | /* | ||
1456 | if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) | 1583 | if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) |
1457 | AddDefaultMethod(methods, _hashSize); | 1584 | { |
1585 | AddDefaultMethod(methods, | ||
1586 | utf_nameExtenstion.IsEmpty() ? NULL : utf_nameExtenstion.Ptr(), | ||
1587 | _hashSize); | ||
1588 | } | ||
1589 | */ | ||
1458 | 1590 | ||
1459 | RINOK(hb_Glob.SetMethods( | 1591 | if (!methods.IsEmpty()) |
1592 | { | ||
1593 | RINOK(hb_Glob.SetMethods( | ||
1460 | EXTERNAL_CODECS_LOC_VARS | 1594 | EXTERNAL_CODECS_LOC_VARS |
1461 | methods)) | 1595 | methods)) |
1596 | } | ||
1462 | 1597 | ||
1463 | Z7_DECL_CMyComPtr_QI_FROM( | 1598 | Z7_DECL_CMyComPtr_QI_FROM( |
1464 | IArchiveUpdateCallbackFile, | 1599 | IArchiveUpdateCallbackFile, |
@@ -1553,9 +1688,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1553 | { | 1688 | { |
1554 | hb_Use = &hb_Loc; | 1689 | hb_Use = &hb_Loc; |
1555 | CMethodId id; | 1690 | CMethodId id; |
1556 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id)) | 1691 | AString methodName = hp.Method; |
1692 | Convert_TagName_to_MethodName(methodName); | ||
1693 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, id)) | ||
1557 | { | 1694 | { |
1558 | methods_loc.Add(UString(hp.Method)); | 1695 | methods_loc.Add(UString(methodName)); |
1559 | RINOK(hb_Loc.SetMethods( | 1696 | RINOK(hb_Loc.SetMethods( |
1560 | EXTERNAL_CODECS_LOC_VARS | 1697 | EXTERNAL_CODECS_LOC_VARS |
1561 | methods_loc)) | 1698 | methods_loc)) |
@@ -1565,7 +1702,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1565 | } | 1702 | } |
1566 | else if (methods.IsEmpty()) | 1703 | else if (methods.IsEmpty()) |
1567 | { | 1704 | { |
1568 | AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size()); | 1705 | AddDefaultMethod(methods_loc, |
1706 | _method_for_Extraction.IsEmpty() ? NULL : | ||
1707 | _method_for_Extraction.Ptr(), | ||
1708 | (unsigned)hp.Hash.Size()); | ||
1569 | if (!methods_loc.IsEmpty()) | 1709 | if (!methods_loc.IsEmpty()) |
1570 | { | 1710 | { |
1571 | hb_Use = &hb_Loc; | 1711 | hb_Use = &hb_Loc; |
@@ -1613,7 +1753,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1613 | Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; | 1753 | Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; |
1614 | if (isSupportedMode | 1754 | if (isSupportedMode |
1615 | && res_SetMethods != E_NOTIMPL | 1755 | && res_SetMethods != E_NOTIMPL |
1616 | && hb_Use->Hashers.Size() > 0 | 1756 | && !hb_Use->Hashers.IsEmpty() |
1617 | ) | 1757 | ) |
1618 | { | 1758 | { |
1619 | const CHasherState &hs = hb_Use->Hashers[0]; | 1759 | const CHasherState &hs = hb_Use->Hashers[0]; |
@@ -1766,10 +1906,6 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1766 | methods.Add(_methods[k]); | 1906 | methods.Add(_methods[k]); |
1767 | } | 1907 | } |
1768 | } | 1908 | } |
1769 | else if (_crcSize_WasSet) | ||
1770 | { | ||
1771 | AddDefaultMethod(methods, _crcSize); | ||
1772 | } | ||
1773 | else | 1909 | else |
1774 | { | 1910 | { |
1775 | Z7_DECL_CMyComPtr_QI_FROM( | 1911 | Z7_DECL_CMyComPtr_QI_FROM( |
@@ -1781,12 +1917,23 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1781 | RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) | 1917 | RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) |
1782 | if (prop.vt == VT_BSTR) | 1918 | if (prop.vt == VT_BSTR) |
1783 | { | 1919 | { |
1784 | const UString method = GetMethod_from_FileName(prop.bstrVal); | 1920 | AString method; |
1921 | /* const bool isKnownMethod = */ GetMethod_from_FileName(prop.bstrVal, method); | ||
1785 | if (!method.IsEmpty()) | 1922 | if (!method.IsEmpty()) |
1786 | methods.Add(method); | 1923 | { |
1924 | AddDefaultMethod(methods, method, _crcSize_WasSet ? _crcSize : 0); | ||
1925 | if (methods.IsEmpty()) | ||
1926 | return E_NOTIMPL; | ||
1927 | } | ||
1787 | } | 1928 | } |
1788 | } | 1929 | } |
1789 | } | 1930 | } |
1931 | if (methods.IsEmpty() && _crcSize_WasSet) | ||
1932 | { | ||
1933 | AddDefaultMethod(methods, | ||
1934 | NULL, // name | ||
1935 | _crcSize); | ||
1936 | } | ||
1790 | 1937 | ||
1791 | RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) | 1938 | RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) |
1792 | 1939 | ||
@@ -2030,6 +2177,15 @@ HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) | |||
2030 | } | 2177 | } |
2031 | 2178 | ||
2032 | 2179 | ||
2180 | void CHandler::InitProps() | ||
2181 | { | ||
2182 | _supportWindowsBackslash = true; | ||
2183 | _crcSize_WasSet = false; | ||
2184 | _crcSize = 4; | ||
2185 | _methods.Clear(); | ||
2186 | _options.Init_HashOptionsLocal(); | ||
2187 | } | ||
2188 | |||
2033 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) | 2189 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) |
2034 | { | 2190 | { |
2035 | COM_TRY_BEGIN | 2191 | COM_TRY_BEGIN |
@@ -2076,11 +2232,32 @@ void Codecs_AddHashArcHandler(CCodecs *codecs) | |||
2076 | 2232 | ||
2077 | // ubuntu uses "SHA256SUMS" file | 2233 | // ubuntu uses "SHA256SUMS" file |
2078 | item.AddExts(UString ( | 2234 | item.AddExts(UString ( |
2079 | "sha256 sha512 sha224 sha384 sha1 sha md5" | 2235 | "sha256" |
2080 | // "b2sum" | 2236 | " sha512" |
2081 | " crc32 crc64" | 2237 | " sha384" |
2082 | " asc" | 2238 | " sha224" |
2239 | " sha512-224" | ||
2240 | " sha512-256" | ||
2241 | " sha3-224" | ||
2242 | " sha3-256" | ||
2243 | " sha3-384" | ||
2244 | " sha3-512" | ||
2245 | // " shake128" | ||
2246 | // " shake256" | ||
2247 | " sha1" | ||
2248 | " sha2" | ||
2249 | " sha3" | ||
2250 | " sha" | ||
2251 | " md5" | ||
2252 | " blake2s" | ||
2253 | " blake2b" | ||
2254 | " blake2sp" | ||
2255 | " xxh64" | ||
2256 | " crc32" | ||
2257 | " crc64" | ||
2083 | " cksum" | 2258 | " cksum" |
2259 | " asc" | ||
2260 | // " b2sum" | ||
2084 | ), | 2261 | ), |
2085 | UString()); | 2262 | UString()); |
2086 | 2263 | ||
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h index 1e9dbf4..b8f867f 100644 --- a/CPP/7zip/UI/Common/HashCalc.h +++ b/CPP/7zip/UI/Common/HashCalc.h | |||
@@ -279,32 +279,25 @@ Z7_CLASS_IMP_CHandler_IInArchive_3( | |||
279 | bool _isArc; | 279 | bool _isArc; |
280 | bool _supportWindowsBackslash; | 280 | bool _supportWindowsBackslash; |
281 | bool _crcSize_WasSet; | 281 | bool _crcSize_WasSet; |
282 | UInt64 _phySize; | ||
283 | CObjectVector<CHashPair> HashPairs; | ||
284 | UString _nameExtenstion; | ||
285 | // UString _method_fromName; | ||
286 | AString _pgpMethod; | ||
287 | bool _is_CksumMode; | 282 | bool _is_CksumMode; |
288 | bool _is_PgpMethod; | 283 | bool _is_PgpMethod; |
289 | bool _is_ZeroMode; | 284 | bool _is_ZeroMode; |
290 | bool _are_there_Tags; | 285 | bool _are_there_Tags; |
291 | bool _are_there_Dirs; | 286 | bool _are_there_Dirs; |
287 | bool _is_KnownMethod_in_FileName; | ||
292 | bool _hashSize_Defined; | 288 | bool _hashSize_Defined; |
293 | unsigned _hashSize; | 289 | unsigned _hashSize; |
294 | UInt32 _crcSize; | 290 | UInt32 _crcSize; |
291 | UInt64 _phySize; | ||
292 | CObjectVector<CHashPair> HashPairs; | ||
295 | UStringVector _methods; | 293 | UStringVector _methods; |
294 | AString _method_from_FileName; | ||
295 | AString _pgpMethod; | ||
296 | AString _method_for_Extraction; | ||
296 | CHashOptionsLocal _options; | 297 | CHashOptionsLocal _options; |
297 | 298 | ||
298 | void ClearVars(); | 299 | void ClearVars(); |
299 | 300 | void InitProps(); | |
300 | void InitProps() | ||
301 | { | ||
302 | _supportWindowsBackslash = true; | ||
303 | _crcSize_WasSet = false; | ||
304 | _crcSize = 4; | ||
305 | _methods.Clear(); | ||
306 | _options.Init_HashOptionsLocal(); | ||
307 | } | ||
308 | 301 | ||
309 | bool CanUpdate() const | 302 | bool CanUpdate() const |
310 | { | 303 | { |
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 6bf53ea..943435a 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp | |||
@@ -170,7 +170,7 @@ void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) | |||
170 | if (i < addExts.Size()) | 170 | if (i < addExts.Size()) |
171 | { | 171 | { |
172 | extInfo.AddExt = addExts[i]; | 172 | extInfo.AddExt = addExts[i]; |
173 | if (extInfo.AddExt == L"*") | 173 | if (extInfo.AddExt.IsEqualTo("*")) |
174 | extInfo.AddExt.Empty(); | 174 | extInfo.AddExt.Empty(); |
175 | } | 175 | } |
176 | Exts.Add(extInfo); | 176 | Exts.Add(extInfo); |
@@ -931,8 +931,8 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma | |||
931 | const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); | 931 | const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); |
932 | if (name.IsEmpty()) | 932 | if (name.IsEmpty()) |
933 | return false; | 933 | return false; |
934 | int index = FindFormatForArchiveType(name); | 934 | const int index = FindFormatForArchiveType(name); |
935 | if (index < 0 && name != L"*") | 935 | if (index < 0 && !name.IsEqualTo("*")) |
936 | { | 936 | { |
937 | formatIndices.Clear(); | 937 | formatIndices.Clear(); |
938 | return false; | 938 | return false; |
diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp index 2f86838..ad16e36 100644 --- a/CPP/7zip/UI/Common/TempFiles.cpp +++ b/CPP/7zip/UI/Common/TempFiles.cpp | |||
@@ -13,7 +13,8 @@ void CTempFiles::Clear() | |||
13 | { | 13 | { |
14 | while (!Paths.IsEmpty()) | 14 | while (!Paths.IsEmpty()) |
15 | { | 15 | { |
16 | NDir::DeleteFileAlways(Paths.Back()); | 16 | if (NeedDeleteFiles) |
17 | NDir::DeleteFileAlways(Paths.Back()); | ||
17 | Paths.DeleteBack(); | 18 | Paths.DeleteBack(); |
18 | } | 19 | } |
19 | } | 20 | } |
diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h index dd4ac20..83c741f 100644 --- a/CPP/7zip/UI/Common/TempFiles.h +++ b/CPP/7zip/UI/Common/TempFiles.h | |||
@@ -10,6 +10,9 @@ class CTempFiles | |||
10 | void Clear(); | 10 | void Clear(); |
11 | public: | 11 | public: |
12 | FStringVector Paths; | 12 | FStringVector Paths; |
13 | bool NeedDeleteFiles; | ||
14 | |||
15 | CTempFiles(): NeedDeleteFiles(true) {} | ||
13 | ~CTempFiles() { Clear(); } | 16 | ~CTempFiles() { Clear(); } |
14 | }; | 17 | }; |
15 | 18 | ||
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index ed48605..1c2754e 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp | |||
@@ -474,7 +474,7 @@ static HRESULT Compress( | |||
474 | 474 | ||
475 | CArcToDoStat stat2; | 475 | CArcToDoStat stat2; |
476 | 476 | ||
477 | if (options.RenamePairs.Size() != 0) | 477 | if (options.RenameMode || options.RenamePairs.Size() != 0) |
478 | { | 478 | { |
479 | FOR_VECTOR (i, arcItems) | 479 | FOR_VECTOR (i, arcItems) |
480 | { | 480 | { |
@@ -1096,6 +1096,30 @@ typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW; | |||
1096 | #endif // _WIN32 | 1096 | #endif // _WIN32 |
1097 | 1097 | ||
1098 | 1098 | ||
1099 | struct C_CopyFileProgress_to_IUpdateCallbackUI2 Z7_final: | ||
1100 | public ICopyFileProgress | ||
1101 | { | ||
1102 | IUpdateCallbackUI2 *Callback; | ||
1103 | HRESULT CallbackResult; | ||
1104 | // bool Disable_Break; | ||
1105 | |||
1106 | virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override | ||
1107 | { | ||
1108 | const HRESULT res = Callback->MoveArc_Progress(total, current); | ||
1109 | CallbackResult = res; | ||
1110 | // if (Disable_Break && res == E_ABORT) res = S_OK; | ||
1111 | return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL; | ||
1112 | } | ||
1113 | |||
1114 | C_CopyFileProgress_to_IUpdateCallbackUI2( | ||
1115 | IUpdateCallbackUI2 *callback) : | ||
1116 | Callback(callback), | ||
1117 | CallbackResult(S_OK) | ||
1118 | // , Disable_Break(false) | ||
1119 | {} | ||
1120 | }; | ||
1121 | |||
1122 | |||
1099 | HRESULT UpdateArchive( | 1123 | HRESULT UpdateArchive( |
1100 | CCodecs *codecs, | 1124 | CCodecs *codecs, |
1101 | const CObjectVector<COpenType> &types, | 1125 | const CObjectVector<COpenType> &types, |
@@ -1311,7 +1335,7 @@ HRESULT UpdateArchive( | |||
1311 | return E_NOTIMPL; | 1335 | return E_NOTIMPL; |
1312 | } | 1336 | } |
1313 | 1337 | ||
1314 | bool thereIsInArchive = arcLink.IsOpen; | 1338 | const bool thereIsInArchive = arcLink.IsOpen; |
1315 | if (!thereIsInArchive && renameMode) | 1339 | if (!thereIsInArchive && renameMode) |
1316 | return E_FAIL; | 1340 | return E_FAIL; |
1317 | 1341 | ||
@@ -1588,7 +1612,14 @@ HRESULT UpdateArchive( | |||
1588 | multiStreams.DisableDeletion(); | 1612 | multiStreams.DisableDeletion(); |
1589 | RINOK(multiStreams.Destruct()) | 1613 | RINOK(multiStreams.Destruct()) |
1590 | 1614 | ||
1591 | tempFiles.Paths.Clear(); | 1615 | // here we disable deleting of temp archives. |
1616 | // note: archive moving can fail, or it can be interrupted, | ||
1617 | // if we move new temp update from another volume. | ||
1618 | // And we still want to keep temp archive in that case, | ||
1619 | // because we will have deleted original archive. | ||
1620 | tempFiles.NeedDeleteFiles = false; | ||
1621 | // tempFiles.Paths.Clear(); | ||
1622 | |||
1592 | if (createTempFile) | 1623 | if (createTempFile) |
1593 | { | 1624 | { |
1594 | try | 1625 | try |
@@ -1603,16 +1634,29 @@ HRESULT UpdateArchive( | |||
1603 | if (!DeleteFileAlways(us2fs(arcPath))) | 1634 | if (!DeleteFileAlways(us2fs(arcPath))) |
1604 | return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); | 1635 | return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); |
1605 | } | 1636 | } |
1606 | 1637 | ||
1607 | if (!MyMoveFile(tempPath, us2fs(arcPath))) | 1638 | UInt64 totalArcSize = 0; |
1639 | { | ||
1640 | NFind::CFileInfo fi; | ||
1641 | if (fi.Find(tempPath)) | ||
1642 | totalArcSize = fi.Size; | ||
1643 | } | ||
1644 | RINOK(callback->MoveArc_Start(fs2us(tempPath), arcPath, | ||
1645 | totalArcSize, BoolToInt(thereIsInArchive))) | ||
1646 | |||
1647 | C_CopyFileProgress_to_IUpdateCallbackUI2 prox(callback); | ||
1648 | // if we update archive, we have removed original archive. | ||
1649 | // So if we break archive moving, we will have only temporary archive. | ||
1650 | // We can disable breaking here: | ||
1651 | // prox.Disable_Break = thereIsInArchive; | ||
1652 | |||
1653 | if (!MyMoveFile_with_Progress(tempPath, us2fs(arcPath), &prox)) | ||
1608 | { | 1654 | { |
1609 | errorInfo.SystemError = ::GetLastError(); | 1655 | errorInfo.SystemError = ::GetLastError(); |
1610 | errorInfo.Message = "cannot move the file"; | 1656 | errorInfo.Message = "cannot move the file"; |
1611 | if (errorInfo.SystemError == ERROR_INVALID_PARAMETER) | 1657 | if (errorInfo.SystemError == ERROR_INVALID_PARAMETER) |
1612 | { | 1658 | { |
1613 | NFind::CFileInfo fi; | 1659 | if (totalArcSize > (UInt32)(Int32)-1) |
1614 | if (fi.Find(tempPath) && | ||
1615 | fi.Size > (UInt32)(Int32)-1) | ||
1616 | { | 1660 | { |
1617 | // bool isFsDetected = false; | 1661 | // bool isFsDetected = false; |
1618 | // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected) | 1662 | // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected) |
@@ -1622,10 +1666,20 @@ HRESULT UpdateArchive( | |||
1622 | } | 1666 | } |
1623 | } | 1667 | } |
1624 | } | 1668 | } |
1669 | // if there was no input archive, and we have operation breaking. | ||
1670 | // then we can remove temporary archive, because we still have original uncompressed files. | ||
1671 | if (!thereIsInArchive | ||
1672 | && prox.CallbackResult == E_ABORT) | ||
1673 | tempFiles.NeedDeleteFiles = true; | ||
1625 | errorInfo.FileNames.Add(tempPath); | 1674 | errorInfo.FileNames.Add(tempPath); |
1626 | errorInfo.FileNames.Add(us2fs(arcPath)); | 1675 | errorInfo.FileNames.Add(us2fs(arcPath)); |
1676 | RINOK(prox.CallbackResult) | ||
1627 | return errorInfo.Get_HRESULT_Error(); | 1677 | return errorInfo.Get_HRESULT_Error(); |
1628 | } | 1678 | } |
1679 | |||
1680 | // MoveArc_Finish() can return delayed user break (E_ABORT) status, | ||
1681 | // if callback callee ignored interruption to finish archive creation operation. | ||
1682 | RINOK(callback->MoveArc_Finish()) | ||
1629 | 1683 | ||
1630 | /* | 1684 | /* |
1631 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) | 1685 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) |
@@ -1866,7 +1920,7 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
1866 | if (NFind::DoesDirExist(phyPath)) | 1920 | if (NFind::DoesDirExist(phyPath)) |
1867 | { | 1921 | { |
1868 | RINOK(callback->DeletingAfterArchiving(phyPath, true)) | 1922 | RINOK(callback->DeletingAfterArchiving(phyPath, true)) |
1869 | RemoveDir(phyPath); | 1923 | RemoveDirAlways_if_Empty(phyPath); |
1870 | } | 1924 | } |
1871 | } | 1925 | } |
1872 | 1926 | ||
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h index a9459ff..ae141e5 100644 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h | |||
@@ -12,8 +12,6 @@ | |||
12 | #include "UpdateAction.h" | 12 | #include "UpdateAction.h" |
13 | #include "UpdateCallback.h" | 13 | #include "UpdateCallback.h" |
14 | 14 | ||
15 | #include "DirItem.h" | ||
16 | |||
17 | enum EArcNameMode | 15 | enum EArcNameMode |
18 | { | 16 | { |
19 | k_ArcNameMode_Smart, | 17 | k_ArcNameMode_Smart, |
@@ -96,6 +94,7 @@ struct CUpdateOptions | |||
96 | 94 | ||
97 | bool DeleteAfterCompressing; | 95 | bool DeleteAfterCompressing; |
98 | bool SetArcMTime; | 96 | bool SetArcMTime; |
97 | bool RenameMode; | ||
99 | 98 | ||
100 | CBoolPair NtSecurity; | 99 | CBoolPair NtSecurity; |
101 | CBoolPair AltStreams; | 100 | CBoolPair AltStreams; |
@@ -141,6 +140,7 @@ struct CUpdateOptions | |||
141 | 140 | ||
142 | DeleteAfterCompressing(false), | 141 | DeleteAfterCompressing(false), |
143 | SetArcMTime(false), | 142 | SetArcMTime(false), |
143 | RenameMode(false), | ||
144 | 144 | ||
145 | ArcNameMode(k_ArcNameMode_Smart), | 145 | ArcNameMode(k_ArcNameMode_Smart), |
146 | PathMode(NWildcard::k_RelatPath) | 146 | PathMode(NWildcard::k_RelatPath) |
@@ -195,6 +195,9 @@ Z7_PURE_INTERFACES_BEGIN | |||
195 | virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \ | 195 | virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \ |
196 | virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \ | 196 | virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \ |
197 | virtual HRESULT FinishDeletingAfterArchiving() x \ | 197 | virtual HRESULT FinishDeletingAfterArchiving() x \ |
198 | virtual HRESULT MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode) x \ | ||
199 | virtual HRESULT MoveArc_Progress(UInt64 total, UInt64 current) x \ | ||
200 | virtual HRESULT MoveArc_Finish() x \ | ||
198 | 201 | ||
199 | DECLARE_INTERFACE(IUpdateCallbackUI2): | 202 | DECLARE_INTERFACE(IUpdateCallbackUI2): |
200 | public IUpdateCallbackUI, | 203 | public IUpdateCallbackUI, |
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index d3ee639..e2f1866 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "../../../Windows/PropVariant.h" | 32 | #include "../../../Windows/PropVariant.h" |
33 | 33 | ||
34 | #include "../../Common/StreamObjects.h" | 34 | #include "../../Common/StreamObjects.h" |
35 | #include "../../Archive/Common/ItemNameUtils.h" | ||
35 | 36 | ||
36 | #include "UpdateCallback.h" | 37 | #include "UpdateCallback.h" |
37 | 38 | ||
@@ -306,7 +307,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con | |||
306 | 307 | ||
307 | #if defined(_WIN32) && !defined(UNDER_CE) | 308 | #if defined(_WIN32) && !defined(UNDER_CE) |
308 | 309 | ||
309 | static UString GetRelativePath(const UString &to, const UString &from) | 310 | static UString GetRelativePath(const UString &to, const UString &from, bool isWSL) |
310 | { | 311 | { |
311 | UStringVector partsTo, partsFrom; | 312 | UStringVector partsTo, partsFrom; |
312 | SplitPathToParts(to, partsTo); | 313 | SplitPathToParts(to, partsTo); |
@@ -324,11 +325,12 @@ static UString GetRelativePath(const UString &to, const UString &from) | |||
324 | 325 | ||
325 | if (i == 0) | 326 | if (i == 0) |
326 | { | 327 | { |
327 | #ifdef _WIN32 | 328 | #ifdef _WIN32 |
328 | if (NName::IsDrivePath(to) || | 329 | if (isWSL || |
329 | NName::IsDrivePath(from)) | 330 | (NName::IsDrivePath(to) || |
331 | NName::IsDrivePath(from))) | ||
330 | return to; | 332 | return to; |
331 | #endif | 333 | #endif |
332 | } | 334 | } |
333 | 335 | ||
334 | UString s; | 336 | UString s; |
@@ -373,54 +375,87 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
373 | return S_OK; | 375 | return S_OK; |
374 | } | 376 | } |
375 | 377 | ||
376 | #if !defined(UNDER_CE) | 378 | #if !defined(UNDER_CE) |
377 | |||
378 | if (up.DirIndex >= 0) | 379 | if (up.DirIndex >= 0) |
379 | { | 380 | { |
380 | const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; | 381 | const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; |
381 | 382 | if (di.ReparseData.Size()) | |
382 | #ifdef _WIN32 | ||
383 | // if (di.IsDir()) | ||
384 | { | 383 | { |
384 | #ifdef _WIN32 | ||
385 | CReparseAttr attr; | 385 | CReparseAttr attr; |
386 | if (attr.Parse(di.ReparseData, di.ReparseData.Size())) | 386 | if (attr.Parse(di.ReparseData, di.ReparseData.Size())) |
387 | { | 387 | { |
388 | const UString simpleName = attr.GetPath(); | 388 | UString path = attr.GetPath(); |
389 | if (!attr.IsSymLink_WSL() && attr.IsRelative_Win()) | 389 | if (!path.IsEmpty()) |
390 | prop = simpleName; | ||
391 | else | ||
392 | { | 390 | { |
393 | const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); | 391 | bool isWSL = attr.IsSymLink_WSL(); |
394 | FString fullPath; | 392 | if (isWSL) |
395 | if (NDir::MyGetFullPathName(phyPath, fullPath)) | 393 | NArchive::NItemName::ReplaceToWinSlashes(path, true); // useBackslashReplacement |
394 | // it's expected that (path) now uses windows slashes. | ||
395 | // CReparseAttr::IsRelative_Win() returns true if FLAG_RELATIVE is set | ||
396 | // CReparseAttr::IsRelative_Win() returns true for "\dir1\path" | ||
397 | // but we want to store real relative paths without "\" root prefix. | ||
398 | // so we parse path instead of IsRelative_Win() calling. | ||
399 | if (// attr.IsRelative_Win() || | ||
400 | (isWSL ? | ||
401 | IS_PATH_SEPAR(path[0]) : | ||
402 | NName::IsAbsolutePath(path))) | ||
396 | { | 403 | { |
397 | prop = GetRelativePath(simpleName, fs2us(fullPath)); | 404 | // (path) is abolute path or relative to root: "\path" |
405 | // we try to convert (path) to relative path for writing to archive. | ||
406 | const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); | ||
407 | FString fullPath; | ||
408 | if (NDir::MyGetFullPathName(phyPath, fullPath)) | ||
409 | { | ||
410 | if (IS_PATH_SEPAR(path[0]) && | ||
411 | !IS_PATH_SEPAR(path[1])) | ||
412 | { | ||
413 | // path is relative to root of (fullPath): "\path" | ||
414 | const unsigned prefixSize = NName::GetRootPrefixSize(fullPath); | ||
415 | if (prefixSize) | ||
416 | { | ||
417 | path.DeleteFrontal(1); | ||
418 | path.Insert(0, fs2us(fullPath.Left(prefixSize))); | ||
419 | // we have changed "\" prefix to drive prefix "c:\" in (path). | ||
420 | // (path) is Windows path now. | ||
421 | isWSL = false; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | path = GetRelativePath(path, fs2us(fullPath), isWSL); | ||
398 | } | 426 | } |
427 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
428 | // 7-Zip's TAR handler in Windows replaces windows slashes to linux slashes. | ||
429 | // so we can return any slashes to TAR handler. | ||
430 | // or we can convert to linux slashes here, | ||
431 | // because input IInArchive handler uses linux slashes for kpidSymLink. | ||
432 | // path.Replace(WCHAR_PATH_SEPARATOR, L'/'); | ||
433 | #endif | ||
434 | if (!path.IsEmpty()) | ||
435 | prop = path; | ||
399 | } | 436 | } |
400 | prop.Detach(value); | ||
401 | return S_OK; | ||
402 | } | 437 | } |
403 | } | 438 | #else // ! _WIN32 |
404 | |||
405 | #else // _WIN32 | ||
406 | |||
407 | if (di.ReparseData.Size() != 0) | ||
408 | { | ||
409 | AString utf; | 439 | AString utf; |
410 | utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); | 440 | utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); |
411 | 441 | #if 0 // 0 - for debug | |
442 | // it's expected that link data uses system codepage. | ||
443 | // fs2us() ignores conversion errors. But we want correct path | ||
444 | UString us (fs2us(utf)); | ||
445 | #else | ||
412 | UString us; | 446 | UString us; |
413 | if (ConvertUTF8ToUnicode(utf, us)) | 447 | if (ConvertUTF8ToUnicode(utf, us)) |
448 | #endif | ||
414 | { | 449 | { |
415 | prop = us; | 450 | if (!us.IsEmpty()) |
416 | prop.Detach(value); | 451 | prop = us; |
417 | return S_OK; | ||
418 | } | 452 | } |
453 | #endif // ! _WIN32 | ||
419 | } | 454 | } |
420 | 455 | prop.Detach(value); | |
421 | #endif // _WIN32 | 456 | return S_OK; |
422 | } | 457 | } |
423 | #endif // !defined(UNDER_CE) | 458 | #endif // !defined(UNDER_CE) |
424 | } | 459 | } |
425 | else if (propID == kpidHardLink) | 460 | else if (propID == kpidHardLink) |
426 | { | 461 | { |
@@ -428,7 +463,12 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
428 | { | 463 | { |
429 | const CKeyKeyValPair &pair = _map[_hardIndex_To]; | 464 | const CKeyKeyValPair &pair = _map[_hardIndex_To]; |
430 | const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; | 465 | const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; |
431 | prop = DirItems->GetLogPath((unsigned)up2.DirIndex); | 466 | const UString path = DirItems->GetLogPath((unsigned)up2.DirIndex); |
467 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
468 | // 7-Zip's TAR handler in Windows replaces windows slashes to linux slashes. | ||
469 | // path.Replace(WCHAR_PATH_SEPARATOR, L'/'); | ||
470 | #endif | ||
471 | prop = path; | ||
432 | prop.Detach(value); | 472 | prop.Detach(value); |
433 | return S_OK; | 473 | return S_OK; |
434 | } | 474 | } |
@@ -438,7 +478,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
438 | return S_OK; | 478 | return S_OK; |
439 | } | 479 | } |
440 | } | 480 | } |
441 | } | 481 | } // if (up.NewData) |
442 | 482 | ||
443 | if (up.IsAnti | 483 | if (up.IsAnti |
444 | && propID != kpidIsDir | 484 | && propID != kpidIsDir |
diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp index cfec635..a492967 100644 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp | |||
@@ -63,24 +63,22 @@ HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) | |||
63 | NWorkDir::CInfo workDirInfo; | 63 | NWorkDir::CInfo workDirInfo; |
64 | workDirInfo.Load(); | 64 | workDirInfo.Load(); |
65 | FString namePart; | 65 | FString namePart; |
66 | const FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); | 66 | FString path = GetWorkDir(workDirInfo, originalPath, namePart); |
67 | CreateComplexDir(workDir); | 67 | CreateComplexDir(path); |
68 | path += namePart; | ||
68 | _outStreamSpec = new COutFileStream; | 69 | _outStreamSpec = new COutFileStream; |
69 | OutStream = _outStreamSpec; | 70 | OutStream = _outStreamSpec; |
70 | if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) | 71 | if (!_tempFile.Create(path, &_outStreamSpec->File)) |
71 | { | ||
72 | return GetLastError_noZero_HRESULT(); | 72 | return GetLastError_noZero_HRESULT(); |
73 | } | ||
74 | _originalPath = originalPath; | 73 | _originalPath = originalPath; |
75 | return S_OK; | 74 | return S_OK; |
76 | } | 75 | } |
77 | 76 | ||
78 | HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) | 77 | HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal, |
78 | NWindows::NFile::NDir::ICopyFileProgress *progress) | ||
79 | { | 79 | { |
80 | OutStream.Release(); | 80 | OutStream.Release(); |
81 | if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) | 81 | if (!_tempFile.MoveTo(_originalPath, deleteOriginal, progress)) |
82 | { | ||
83 | return GetLastError_noZero_HRESULT(); | 82 | return GetLastError_noZero_HRESULT(); |
84 | } | ||
85 | return S_OK; | 83 | return S_OK; |
86 | } | 84 | } |
diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h index d32ab9d..fed8c4a 100644 --- a/CPP/7zip/UI/Common/WorkDir.h +++ b/CPP/7zip/UI/Common/WorkDir.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); | 12 | FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); |
13 | 13 | ||
14 | class CWorkDirTempFile | 14 | class CWorkDirTempFile MY_UNCOPYABLE |
15 | { | 15 | { |
16 | FString _originalPath; | 16 | FString _originalPath; |
17 | NWindows::NFile::NDir::CTempFile _tempFile; | 17 | NWindows::NFile::NDir::CTempFile _tempFile; |
@@ -19,8 +19,12 @@ class CWorkDirTempFile | |||
19 | public: | 19 | public: |
20 | CMyComPtr<IOutStream> OutStream; | 20 | CMyComPtr<IOutStream> OutStream; |
21 | 21 | ||
22 | const FString &Get_OriginalFilePath() const { return _originalPath; } | ||
23 | const FString &Get_TempFilePath() const { return _tempFile.GetPath(); } | ||
24 | |||
22 | HRESULT CreateTempFile(const FString &originalPath); | 25 | HRESULT CreateTempFile(const FString &originalPath); |
23 | HRESULT MoveToOriginal(bool deleteOriginal); | 26 | HRESULT MoveToOriginal(bool deleteOriginal, |
27 | NWindows::NFile::NDir::ICopyFileProgress *progress = NULL); | ||
24 | }; | 28 | }; |
25 | 29 | ||
26 | #endif | 30 | #endif |
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 73c56cf..936b888 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp | |||
@@ -45,8 +45,8 @@ static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value) | |||
45 | 45 | ||
46 | static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value) | 46 | static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value) |
47 | { | 47 | { |
48 | if (key.QueryValue(name, value) != ERROR_SUCCESS) | 48 | value = (UInt32)(Int32)-1; |
49 | value = (UInt32)(Int32)-1; | 49 | key.GetValue_UInt32_IfOk(name, value); |
50 | } | 50 | } |
51 | 51 | ||
52 | 52 | ||
@@ -59,7 +59,7 @@ static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) | |||
59 | static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val) | 59 | static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val) |
60 | { | 60 | { |
61 | bool oldVal = false; | 61 | bool oldVal = false; |
62 | if (key.GetValue_IfOk(name, oldVal) == ERROR_SUCCESS) | 62 | if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS) |
63 | if (val == oldVal) | 63 | if (val == oldVal) |
64 | return; | 64 | return; |
65 | key.SetValue(name, val); | 65 | key.SetValue(name, val); |
@@ -76,13 +76,13 @@ static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoo | |||
76 | static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) | 76 | static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) |
77 | { | 77 | { |
78 | b.Val = false; | 78 | b.Val = false; |
79 | b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); | 79 | b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); |
80 | } | 80 | } |
81 | 81 | ||
82 | static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) | 82 | static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) |
83 | { | 83 | { |
84 | b.Val = true; | 84 | b.Val = true; |
85 | b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); | 85 | b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); |
86 | } | 86 | } |
87 | 87 | ||
88 | namespace NExtract | 88 | namespace NExtract |
@@ -155,12 +155,12 @@ void CInfo::Load() | |||
155 | 155 | ||
156 | key.GetValue_Strings(kPathHistory, Paths); | 156 | key.GetValue_Strings(kPathHistory, Paths); |
157 | UInt32 v; | 157 | UInt32 v; |
158 | if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) | 158 | if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) |
159 | { | 159 | { |
160 | PathMode = (NPathMode::EEnum)v; | 160 | PathMode = (NPathMode::EEnum)v; |
161 | PathMode_Force = true; | 161 | PathMode_Force = true; |
162 | } | 162 | } |
163 | if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) | 163 | if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) |
164 | { | 164 | { |
165 | OverwriteMode = (NOverwriteMode::EEnum)v; | 165 | OverwriteMode = (NOverwriteMode::EEnum)v; |
166 | OverwriteMode_Force = true; | 166 | OverwriteMode_Force = true; |
@@ -181,7 +181,7 @@ bool Read_ShowPassword() | |||
181 | bool showPassword = false; | 181 | bool showPassword = false; |
182 | if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) | 182 | if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) |
183 | return showPassword; | 183 | return showPassword; |
184 | key.GetValue_IfOk(kShowPassword, showPassword); | 184 | key.GetValue_bool_IfOk(kShowPassword, showPassword); |
185 | return showPassword; | 185 | return showPassword; |
186 | } | 186 | } |
187 | 187 | ||
@@ -189,13 +189,10 @@ UInt32 Read_LimitGB() | |||
189 | { | 189 | { |
190 | CS_LOCK | 190 | CS_LOCK |
191 | CKey key; | 191 | CKey key; |
192 | UInt32 v = (UInt32)(Int32)-1; | ||
192 | if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) | 193 | if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) |
193 | { | 194 | key.GetValue_UInt32_IfOk(kMemLimit, v); |
194 | UInt32 v; | 195 | return v; |
195 | if (key.QueryValue(kMemLimit, v) == ERROR_SUCCESS) | ||
196 | return v; | ||
197 | } | ||
198 | return (UInt32)(Int32)-1; | ||
199 | } | 196 | } |
200 | 197 | ||
201 | } | 198 | } |
@@ -371,9 +368,9 @@ void CInfo::Load() | |||
371 | UString a; | 368 | UString a; |
372 | if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) | 369 | if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) |
373 | ArcType = a; | 370 | ArcType = a; |
374 | key.GetValue_IfOk(kLevel, Level); | 371 | key.GetValue_UInt32_IfOk(kLevel, Level); |
375 | key.GetValue_IfOk(kShowPassword, ShowPassword); | 372 | key.GetValue_bool_IfOk(kShowPassword, ShowPassword); |
376 | key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders); | 373 | key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders); |
377 | } | 374 | } |
378 | 375 | ||
379 | 376 | ||
@@ -517,7 +514,7 @@ void CInfo::Load() | |||
517 | return; | 514 | return; |
518 | 515 | ||
519 | UInt32 dirType; | 516 | UInt32 dirType; |
520 | if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS) | 517 | if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS) |
521 | return; | 518 | return; |
522 | switch (dirType) | 519 | switch (dirType) |
523 | { | 520 | { |
@@ -535,7 +532,7 @@ void CInfo::Load() | |||
535 | if (Mode == NMode::kSpecified) | 532 | if (Mode == NMode::kSpecified) |
536 | Mode = NMode::kSystem; | 533 | Mode = NMode::kSystem; |
537 | } | 534 | } |
538 | key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly); | 535 | key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly); |
539 | } | 536 | } |
540 | 537 | ||
541 | } | 538 | } |
@@ -598,5 +595,5 @@ void CContextMenuInfo::Load() | |||
598 | 595 | ||
599 | Key_Get_UInt32(key, kWriteZoneId, WriteZone); | 596 | Key_Get_UInt32(key, kWriteZoneId, WriteZone); |
600 | 597 | ||
601 | Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); | 598 | Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); |
602 | } | 599 | } |
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp index 9e4c040..a184ffb 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.cpp +++ b/CPP/7zip/UI/Console/ConsoleClose.cpp | |||
@@ -16,7 +16,7 @@ | |||
16 | namespace NConsoleClose { | 16 | namespace NConsoleClose { |
17 | 17 | ||
18 | unsigned g_BreakCounter = 0; | 18 | unsigned g_BreakCounter = 0; |
19 | static const unsigned kBreakAbortThreshold = 2; | 19 | static const unsigned kBreakAbortThreshold = 3; |
20 | 20 | ||
21 | #ifdef _WIN32 | 21 | #ifdef _WIN32 |
22 | 22 | ||
@@ -28,8 +28,7 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType) | |||
28 | return TRUE; | 28 | return TRUE; |
29 | } | 29 | } |
30 | 30 | ||
31 | g_BreakCounter++; | 31 | if (++g_BreakCounter < kBreakAbortThreshold) |
32 | if (g_BreakCounter < kBreakAbortThreshold) | ||
33 | return TRUE; | 32 | return TRUE; |
34 | return FALSE; | 33 | return FALSE; |
35 | /* | 34 | /* |
@@ -47,7 +46,7 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType) | |||
47 | CCtrlHandlerSetter::CCtrlHandlerSetter() | 46 | CCtrlHandlerSetter::CCtrlHandlerSetter() |
48 | { | 47 | { |
49 | if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) | 48 | if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) |
50 | throw "SetConsoleCtrlHandler fails"; | 49 | throw 1019; // "SetConsoleCtrlHandler fails"; |
51 | } | 50 | } |
52 | 51 | ||
53 | CCtrlHandlerSetter::~CCtrlHandlerSetter() | 52 | CCtrlHandlerSetter::~CCtrlHandlerSetter() |
@@ -63,8 +62,7 @@ CCtrlHandlerSetter::~CCtrlHandlerSetter() | |||
63 | 62 | ||
64 | static void HandlerRoutine(int) | 63 | static void HandlerRoutine(int) |
65 | { | 64 | { |
66 | g_BreakCounter++; | 65 | if (++g_BreakCounter < kBreakAbortThreshold) |
67 | if (g_BreakCounter < kBreakAbortThreshold) | ||
68 | return; | 66 | return; |
69 | exit(EXIT_FAILURE); | 67 | exit(EXIT_FAILURE); |
70 | } | 68 | } |
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h index 25c5d0c..b0d99b4 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.h +++ b/CPP/7zip/UI/Console/ConsoleClose.h | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | namespace NConsoleClose { | 6 | namespace NConsoleClose { |
7 | 7 | ||
8 | class CCtrlBreakException {}; | 8 | // class CCtrlBreakException {}; |
9 | 9 | ||
10 | #ifdef UNDER_CE | 10 | #ifdef UNDER_CE |
11 | 11 | ||
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index f59d4c1..b127631 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | |||
@@ -928,7 +928,7 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) | |||
928 | if (result == E_ABORT | 928 | if (result == E_ABORT |
929 | || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)) | 929 | || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)) |
930 | return result; | 930 | return result; |
931 | NumArcsWithError++; | 931 | NumArcsWithError++; |
932 | 932 | ||
933 | if (_se) | 933 | if (_se) |
934 | { | 934 | { |
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index dabd696..90e00a4 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp | |||
@@ -908,9 +908,12 @@ int Main2( | |||
908 | 908 | ||
909 | if (options.EnableHeaders) | 909 | if (options.EnableHeaders) |
910 | { | 910 | { |
911 | ShowCopyrightAndHelp(g_StdStream, false); | 911 | if (g_StdStream) |
912 | if (!parser.Parse1Log.IsEmpty()) | 912 | { |
913 | *g_StdStream << parser.Parse1Log; | 913 | ShowCopyrightAndHelp(g_StdStream, false); |
914 | if (!parser.Parse1Log.IsEmpty()) | ||
915 | *g_StdStream << parser.Parse1Log; | ||
916 | } | ||
914 | } | 917 | } |
915 | 918 | ||
916 | parser.Parse2(options); | 919 | parser.Parse2(options); |
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp index 602ab64..490950b 100644 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp | |||
@@ -140,11 +140,13 @@ int Z7_CDECL main | |||
140 | PrintError(kMemoryExceptionMessage); | 140 | PrintError(kMemoryExceptionMessage); |
141 | return (NExitCode::kMemoryError); | 141 | return (NExitCode::kMemoryError); |
142 | } | 142 | } |
143 | /* | ||
143 | catch(const NConsoleClose::CCtrlBreakException &) | 144 | catch(const NConsoleClose::CCtrlBreakException &) |
144 | { | 145 | { |
145 | PrintError(kUserBreakMessage); | 146 | PrintError(kUserBreakMessage); |
146 | return (NExitCode::kUserBreak); | 147 | return (NExitCode::kUserBreak); |
147 | } | 148 | } |
149 | */ | ||
148 | catch(const CMessagePathException &e) | 150 | catch(const CMessagePathException &e) |
149 | { | 151 | { |
150 | PrintError(kException_CmdLine_Error_Message); | 152 | PrintError(kException_CmdLine_Error_Message); |
diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h index 46988a5..379aa1b 100644 --- a/CPP/7zip/UI/Console/PercentPrinter.h +++ b/CPP/7zip/UI/Console/PercentPrinter.h | |||
@@ -26,6 +26,13 @@ struct CPercentPrinterState | |||
26 | 26 | ||
27 | class CPercentPrinter: public CPercentPrinterState | 27 | class CPercentPrinter: public CPercentPrinterState |
28 | { | 28 | { |
29 | public: | ||
30 | CStdOutStream *_so; | ||
31 | bool DisablePrint; | ||
32 | bool NeedFlush; | ||
33 | unsigned MaxLen; | ||
34 | |||
35 | private: | ||
29 | UInt32 _tickStep; | 36 | UInt32 _tickStep; |
30 | DWORD _prevTick; | 37 | DWORD _prevTick; |
31 | 38 | ||
@@ -41,18 +48,13 @@ class CPercentPrinter: public CPercentPrinterState | |||
41 | void GetPercents(); | 48 | void GetPercents(); |
42 | 49 | ||
43 | public: | 50 | public: |
44 | CStdOutStream *_so; | ||
45 | |||
46 | bool DisablePrint; | ||
47 | bool NeedFlush; | ||
48 | unsigned MaxLen; | ||
49 | 51 | ||
50 | CPercentPrinter(UInt32 tickStep = 200): | 52 | CPercentPrinter(UInt32 tickStep = 200): |
51 | _tickStep(tickStep), | ||
52 | _prevTick(0), | ||
53 | DisablePrint(false), | 53 | DisablePrint(false), |
54 | NeedFlush(true), | 54 | NeedFlush(true), |
55 | MaxLen(80 - 1) | 55 | MaxLen(80 - 1), |
56 | _tickStep(tickStep), | ||
57 | _prevTick(0) | ||
56 | {} | 58 | {} |
57 | 59 | ||
58 | ~CPercentPrinter(); | 60 | ~CPercentPrinter(); |
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index 3e79645..5185d5c 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | |||
@@ -361,6 +361,119 @@ HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) | |||
361 | } | 361 | } |
362 | 362 | ||
363 | 363 | ||
364 | |||
365 | HRESULT CUpdateCallbackConsole::MoveArc_UpdateStatus() | ||
366 | { | ||
367 | if (NeedPercents()) | ||
368 | { | ||
369 | AString &s = _percent.Command; | ||
370 | s = " : "; | ||
371 | s.Add_UInt64(_arcMoving_percents); | ||
372 | s.Add_Char('%'); | ||
373 | const bool totalDefined = (_arcMoving_total != 0 && _arcMoving_total != (UInt64)(Int64)-1); | ||
374 | if (_arcMoving_current != 0 || totalDefined) | ||
375 | { | ||
376 | s += " : "; | ||
377 | s.Add_UInt64(_arcMoving_current >> 20); | ||
378 | s += " MiB"; | ||
379 | } | ||
380 | if (totalDefined) | ||
381 | { | ||
382 | s += " / "; | ||
383 | s.Add_UInt64((_arcMoving_total + ((1 << 20) - 1)) >> 20); | ||
384 | s += " MiB"; | ||
385 | } | ||
386 | s += " : temporary archive moving ..."; | ||
387 | _percent.Print(); | ||
388 | } | ||
389 | |||
390 | // we ignore single Ctrl-C, if (_arcMoving_updateMode) mode | ||
391 | // because we want to get good final archive instead of temp archive. | ||
392 | if (NConsoleClose::g_BreakCounter == 1 && _arcMoving_updateMode) | ||
393 | return S_OK; | ||
394 | return CheckBreak(); | ||
395 | } | ||
396 | |||
397 | |||
398 | HRESULT CUpdateCallbackConsole::MoveArc_Start( | ||
399 | const wchar_t *srcTempPath, const wchar_t *destFinalPath, | ||
400 | UInt64 size, Int32 updateMode) | ||
401 | { | ||
402 | #if 0 // 1 : for debug | ||
403 | if (LogLevel > 0 && _so) | ||
404 | { | ||
405 | ClosePercents_for_so(); | ||
406 | *_so << "Temporary archive moving:" << endl; | ||
407 | _tempU = srcTempPath; | ||
408 | _so->Normalize_UString_Path(_tempU); | ||
409 | _so->PrintUString(_tempU, _tempA); | ||
410 | *_so << endl; | ||
411 | _tempU = destFinalPath; | ||
412 | _so->Normalize_UString_Path(_tempU); | ||
413 | _so->PrintUString(_tempU, _tempA); | ||
414 | *_so << endl; | ||
415 | } | ||
416 | #else | ||
417 | UNUSED_VAR(srcTempPath) | ||
418 | UNUSED_VAR(destFinalPath) | ||
419 | #endif | ||
420 | |||
421 | _arcMoving_updateMode = updateMode; | ||
422 | _arcMoving_total = size; | ||
423 | _arcMoving_current = 0; | ||
424 | _arcMoving_percents = 0; | ||
425 | return MoveArc_UpdateStatus(); | ||
426 | } | ||
427 | |||
428 | |||
429 | HRESULT CUpdateCallbackConsole::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize) | ||
430 | { | ||
431 | #if 0 // 1 : for debug | ||
432 | if (_so) | ||
433 | { | ||
434 | ClosePercents_for_so(); | ||
435 | *_so << totalSize << " : " << currentSize << endl; | ||
436 | } | ||
437 | #endif | ||
438 | |||
439 | UInt64 percents = 0; | ||
440 | if (totalSize != 0) | ||
441 | { | ||
442 | if (totalSize < ((UInt64)1 << 57)) | ||
443 | percents = currentSize * 100 / totalSize; | ||
444 | else | ||
445 | percents = currentSize / (totalSize / 100); | ||
446 | } | ||
447 | |||
448 | #ifdef _WIN32 | ||
449 | // Sleep(300); // for debug | ||
450 | #endif | ||
451 | // totalSize = (UInt64)(Int64)-1; // for debug | ||
452 | |||
453 | if (percents == _arcMoving_percents) | ||
454 | return CheckBreak(); | ||
455 | _arcMoving_current = currentSize; | ||
456 | _arcMoving_total = totalSize; | ||
457 | _arcMoving_percents = percents; | ||
458 | return MoveArc_UpdateStatus(); | ||
459 | } | ||
460 | |||
461 | |||
462 | HRESULT CUpdateCallbackConsole::MoveArc_Finish() | ||
463 | { | ||
464 | // _arcMoving_percents = 0; | ||
465 | if (NeedPercents()) | ||
466 | { | ||
467 | _percent.Command.Empty(); | ||
468 | _percent.Print(); | ||
469 | } | ||
470 | // it can return delayed user break (E_ABORT) status, | ||
471 | // if it ignored single CTRL+C in MoveArc_Progress(). | ||
472 | return CheckBreak(); | ||
473 | } | ||
474 | |||
475 | |||
476 | |||
364 | HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) | 477 | HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) |
365 | { | 478 | { |
366 | if (LogLevel > 0 && _so) | 479 | if (LogLevel > 0 && _so) |
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h index 276edba..a386371 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h | |||
@@ -29,30 +29,31 @@ struct CErrorPathCodes | |||
29 | 29 | ||
30 | class CCallbackConsoleBase | 30 | class CCallbackConsoleBase |
31 | { | 31 | { |
32 | protected: | 32 | void CommonError(const FString &path, DWORD systemError, bool isWarning); |
33 | CPercentPrinter _percent; | ||
34 | 33 | ||
34 | protected: | ||
35 | CStdOutStream *_so; | 35 | CStdOutStream *_so; |
36 | CStdOutStream *_se; | 36 | CStdOutStream *_se; |
37 | 37 | ||
38 | void CommonError(const FString &path, DWORD systemError, bool isWarning); | ||
39 | // void CommonError(const char *message); | ||
40 | |||
41 | HRESULT ScanError_Base(const FString &path, DWORD systemError); | 38 | HRESULT ScanError_Base(const FString &path, DWORD systemError); |
42 | HRESULT OpenFileError_Base(const FString &name, DWORD systemError); | 39 | HRESULT OpenFileError_Base(const FString &name, DWORD systemError); |
43 | HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); | 40 | HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); |
44 | 41 | ||
45 | public: | 42 | public: |
46 | bool NeedPercents() const { return _percent._so != NULL; } | ||
47 | |||
48 | bool StdOutMode; | 43 | bool StdOutMode; |
49 | |||
50 | bool NeedFlush; | 44 | bool NeedFlush; |
51 | unsigned PercentsNameLevel; | 45 | unsigned PercentsNameLevel; |
52 | unsigned LogLevel; | 46 | unsigned LogLevel; |
53 | 47 | ||
48 | protected: | ||
54 | AString _tempA; | 49 | AString _tempA; |
55 | UString _tempU; | 50 | UString _tempU; |
51 | CPercentPrinter _percent; | ||
52 | |||
53 | public: | ||
54 | CErrorPathCodes FailedFiles; | ||
55 | CErrorPathCodes ScanErrors; | ||
56 | UInt64 NumNonOpenFiles; | ||
56 | 57 | ||
57 | CCallbackConsoleBase(): | 58 | CCallbackConsoleBase(): |
58 | StdOutMode(false), | 59 | StdOutMode(false), |
@@ -62,6 +63,7 @@ public: | |||
62 | NumNonOpenFiles(0) | 63 | NumNonOpenFiles(0) |
63 | {} | 64 | {} |
64 | 65 | ||
66 | bool NeedPercents() const { return _percent._so != NULL; } | ||
65 | void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } | 67 | void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } |
66 | 68 | ||
67 | void Init( | 69 | void Init( |
@@ -90,10 +92,6 @@ public: | |||
90 | _percent.ClosePrint(false); | 92 | _percent.ClosePrint(false); |
91 | } | 93 | } |
92 | 94 | ||
93 | CErrorPathCodes FailedFiles; | ||
94 | CErrorPathCodes ScanErrors; | ||
95 | UInt64 NumNonOpenFiles; | ||
96 | |||
97 | HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog); | 95 | HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog); |
98 | 96 | ||
99 | // void PrintInfoLine(const UString &s); | 97 | // void PrintInfoLine(const UString &s); |
@@ -109,6 +107,14 @@ class CUpdateCallbackConsole Z7_final: | |||
109 | Z7_IFACE_IMP(IUpdateCallbackUI) | 107 | Z7_IFACE_IMP(IUpdateCallbackUI) |
110 | Z7_IFACE_IMP(IDirItemsCallback) | 108 | Z7_IFACE_IMP(IDirItemsCallback) |
111 | Z7_IFACE_IMP(IUpdateCallbackUI2) | 109 | Z7_IFACE_IMP(IUpdateCallbackUI2) |
110 | |||
111 | HRESULT MoveArc_UpdateStatus(); | ||
112 | |||
113 | UInt64 _arcMoving_total; | ||
114 | UInt64 _arcMoving_current; | ||
115 | UInt64 _arcMoving_percents; | ||
116 | Int32 _arcMoving_updateMode; | ||
117 | |||
112 | public: | 118 | public: |
113 | bool DeleteMessageWasShown; | 119 | bool DeleteMessageWasShown; |
114 | 120 | ||
@@ -119,7 +125,11 @@ public: | |||
119 | #endif | 125 | #endif |
120 | 126 | ||
121 | CUpdateCallbackConsole(): | 127 | CUpdateCallbackConsole(): |
122 | DeleteMessageWasShown(false) | 128 | _arcMoving_total(0) |
129 | , _arcMoving_current(0) | ||
130 | , _arcMoving_percents(0) | ||
131 | , _arcMoving_updateMode(0) | ||
132 | , DeleteMessageWasShown(false) | ||
123 | #ifndef Z7_NO_CRYPTO | 133 | #ifndef Z7_NO_CRYPTO |
124 | , PasswordIsDefined(false) | 134 | , PasswordIsDefined(false) |
125 | , AskPassword(false) | 135 | , AskPassword(false) |
diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile index a20b0cc..d449b38 100644 --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile | |||
@@ -59,10 +59,10 @@ COMPRESS_OBJS = \ | |||
59 | C_OBJS = $(C_OBJS) \ | 59 | C_OBJS = $(C_OBJS) \ |
60 | $O\Alloc.obj \ | 60 | $O\Alloc.obj \ |
61 | $O\CpuArch.obj \ | 61 | $O\CpuArch.obj \ |
62 | $O\Sort.obj \ | ||
63 | $O\Threads.obj \ | 62 | $O\Threads.obj \ |
64 | 63 | ||
65 | !include "../../Crc.mak" | 64 | !include "../../Crc.mak" |
65 | !include "../../Sort.mak" | ||
66 | !include "Console.mak" | 66 | !include "Console.mak" |
67 | 67 | ||
68 | !include "../../7zip.mak" | 68 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index fab3493..0630d78 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp | |||
@@ -295,9 +295,13 @@ static const CHashCommand g_HashCommands[] = | |||
295 | { | 295 | { |
296 | { CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" }, | 296 | { CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" }, |
297 | { CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" }, | 297 | { CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" }, |
298 | { CZipContextMenu::kHash_XXH64, "XXH64", "XXH64" }, | 298 | { CZipContextMenu::kHash_XXH64, "XXH64", "XXH64" }, |
299 | { CZipContextMenu::kHash_MD5, "MD5", "MD5" }, | ||
299 | { CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" }, | 300 | { CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" }, |
300 | { CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" }, | 301 | { CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" }, |
302 | { CZipContextMenu::kHash_SHA384, "SHA-384", "SHA384" }, | ||
303 | { CZipContextMenu::kHash_SHA512, "SHA-512", "SHA512" }, | ||
304 | { CZipContextMenu::kHash_SHA3_256, "SHA3-256", "SHA3-256" }, | ||
301 | { CZipContextMenu::kHash_BLAKE2SP, "BLAKE2sp", "BLAKE2sp" }, | 305 | { CZipContextMenu::kHash_BLAKE2SP, "BLAKE2sp", "BLAKE2sp" }, |
302 | { CZipContextMenu::kHash_All, "*", "*" }, | 306 | { CZipContextMenu::kHash_All, "*", "*" }, |
303 | { CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" }, | 307 | { CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" }, |
@@ -1338,8 +1342,12 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi) | |||
1338 | case kHash_CRC32: | 1342 | case kHash_CRC32: |
1339 | case kHash_CRC64: | 1343 | case kHash_CRC64: |
1340 | case kHash_XXH64: | 1344 | case kHash_XXH64: |
1345 | case kHash_MD5: | ||
1341 | case kHash_SHA1: | 1346 | case kHash_SHA1: |
1342 | case kHash_SHA256: | 1347 | case kHash_SHA256: |
1348 | case kHash_SHA384: | ||
1349 | case kHash_SHA512: | ||
1350 | case kHash_SHA3_256: | ||
1343 | case kHash_BLAKE2SP: | 1351 | case kHash_BLAKE2SP: |
1344 | case kHash_All: | 1352 | case kHash_All: |
1345 | case kHash_Generate_SHA256: | 1353 | case kHash_Generate_SHA256: |
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index a68ba9d..2759967 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h | |||
@@ -88,8 +88,12 @@ public: | |||
88 | kHash_CRC32, | 88 | kHash_CRC32, |
89 | kHash_CRC64, | 89 | kHash_CRC64, |
90 | kHash_XXH64, | 90 | kHash_XXH64, |
91 | kHash_MD5, | ||
91 | kHash_SHA1, | 92 | kHash_SHA1, |
92 | kHash_SHA256, | 93 | kHash_SHA256, |
94 | kHash_SHA384, | ||
95 | kHash_SHA512, | ||
96 | kHash_SHA3_256, | ||
93 | kHash_BLAKE2SP, | 97 | kHash_BLAKE2SP, |
94 | kHash_All, | 98 | kHash_All, |
95 | kHash_Generate_SHA256, | 99 | kHash_Generate_SHA256, |
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile index 3901d6b..311d70e 100644 --- a/CPP/7zip/UI/Explorer/makefile +++ b/CPP/7zip/UI/Explorer/makefile | |||
@@ -72,7 +72,7 @@ FM_OBJS = \ | |||
72 | 72 | ||
73 | C_OBJS = \ | 73 | C_OBJS = \ |
74 | $O\CpuArch.obj \ | 74 | $O\CpuArch.obj \ |
75 | $O\Sort.obj \ | ||
76 | $O\Threads.obj \ | 75 | $O\Threads.obj \ |
77 | 76 | ||
77 | !include "../../Sort.mak" | ||
78 | !include "../../7zip.mak" | 78 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 211dde8..962af97 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp | |||
@@ -116,15 +116,16 @@ Z7_CLASS_IMP_COM_3( | |||
116 | // DWORD m_StartTickValue; | 116 | // DWORD m_StartTickValue; |
117 | bool m_MessageBoxIsShown; | 117 | bool m_MessageBoxIsShown; |
118 | 118 | ||
119 | CProgressBox _progressBox; | ||
120 | |||
121 | bool _numFilesTotalDefined; | 119 | bool _numFilesTotalDefined; |
122 | bool _numBytesTotalDefined; | 120 | bool _numBytesTotalDefined; |
123 | |||
124 | public: | 121 | public: |
125 | bool PasswordIsDefined; | 122 | bool PasswordIsDefined; |
126 | UString Password; | 123 | UString Password; |
127 | 124 | ||
125 | private: | ||
126 | CProgressBox _progressBox; | ||
127 | public: | ||
128 | |||
128 | COpenArchiveCallback() | 129 | COpenArchiveCallback() |
129 | {} | 130 | {} |
130 | 131 | ||
diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index ed61ccc..3c33d8e 100644 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp | |||
@@ -281,7 +281,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, | |||
281 | return valueDefault; | 281 | return valueDefault; |
282 | 282 | ||
283 | UInt32 value; | 283 | UInt32 value; |
284 | if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) | 284 | if (regKey.GetValue_UInt32_IfOk(valueName, value) != ERROR_SUCCESS) |
285 | return valueDefault; | 285 | return valueDefault; |
286 | 286 | ||
287 | return value; | 287 | return value; |
@@ -295,7 +295,7 @@ bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, | |||
295 | return valueDefault; | 295 | return valueDefault; |
296 | 296 | ||
297 | bool value; | 297 | bool value; |
298 | if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) | 298 | if (regKey.GetValue_bool_IfOk(valueName, value) != ERROR_SUCCESS) |
299 | return valueDefault; | 299 | return valueDefault; |
300 | 300 | ||
301 | return value; | 301 | return value; |
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index 2d31b8a..b7f91d6 100644 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp | |||
@@ -61,7 +61,6 @@ static void MyGetFileTime(IFolderFolder *folder, UInt32 itemIndex, | |||
61 | } | 61 | } |
62 | 62 | ||
63 | #define kDotsReplaceString "[[..]]" | 63 | #define kDotsReplaceString "[[..]]" |
64 | #define kDotsReplaceStringU L"[[..]]" | ||
65 | 64 | ||
66 | static void CopyStrLimited(char *dest, const AString &src, unsigned len) | 65 | static void CopyStrLimited(char *dest, const AString &src, unsigned len) |
67 | { | 66 | { |
@@ -84,7 +83,7 @@ void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) | |||
84 | throw 272340; | 83 | throw 272340; |
85 | 84 | ||
86 | AString oemString (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); | 85 | AString oemString (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); |
87 | if (oemString == "..") | 86 | if (oemString.IsEqualTo("..")) |
88 | oemString = kDotsReplaceString; | 87 | oemString = kDotsReplaceString; |
89 | 88 | ||
90 | COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString); | 89 | COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString); |
@@ -193,7 +192,7 @@ void CPlugin::EnterToDirectory(const UString &dirName) | |||
193 | { | 192 | { |
194 | CMyComPtr<IFolderFolder> newFolder; | 193 | CMyComPtr<IFolderFolder> newFolder; |
195 | UString s = dirName; | 194 | UString s = dirName; |
196 | if (dirName == kDotsReplaceStringU) | 195 | if (dirName.IsEqualTo(kDotsReplaceString)) |
197 | s = ".."; | 196 | s = ".."; |
198 | _folder->BindToFolder(s, &newFolder); | 197 | _folder->BindToFolder(s, &newFolder); |
199 | if (!newFolder) | 198 | if (!newFolder) |
@@ -209,12 +208,12 @@ void CPlugin::EnterToDirectory(const UString &dirName) | |||
209 | int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) | 208 | int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) |
210 | { | 209 | { |
211 | UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP); | 210 | UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP); |
212 | if (path == WSTRING_PATH_SEPARATOR) | 211 | if (path.IsEqualTo(STRING_PATH_SEPARATOR)) |
213 | { | 212 | { |
214 | _folder.Release(); | 213 | _folder.Release(); |
215 | m_ArchiveHandler->BindToRootFolder(&_folder); | 214 | m_ArchiveHandler->BindToRootFolder(&_folder); |
216 | } | 215 | } |
217 | else if (path == L"..") | 216 | else if (path.IsEqualTo("..")) |
218 | { | 217 | { |
219 | CMyComPtr<IFolderFolder> newFolder; | 218 | CMyComPtr<IFolderFolder> newFolder; |
220 | _folder->BindToParentFolder(&newFolder); | 219 | _folder->BindToParentFolder(&newFolder); |
diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h index 6e8b487..f6b36c4 100644 --- a/CPP/7zip/UI/Far/ProgressBox.h +++ b/CPP/7zip/UI/Far/ProgressBox.h | |||
@@ -45,7 +45,12 @@ class CProgressBox: public CPercentPrinterState | |||
45 | DWORD _prevElapsedSec; | 45 | DWORD _prevElapsedSec; |
46 | 46 | ||
47 | bool _wasPrinted; | 47 | bool _wasPrinted; |
48 | public: | ||
49 | bool UseBytesForPercents; | ||
50 | DWORD StartTick; | ||
51 | unsigned MaxLen; | ||
48 | 52 | ||
53 | private: | ||
49 | UString _tempU; | 54 | UString _tempU; |
50 | UString _name1U; | 55 | UString _name1U; |
51 | UString _name2U; | 56 | UString _name2U; |
@@ -64,15 +69,12 @@ class CProgressBox: public CPercentPrinterState | |||
64 | void ReduceString(const UString &src, AString &dest); | 69 | void ReduceString(const UString &src, AString &dest); |
65 | 70 | ||
66 | public: | 71 | public: |
67 | DWORD StartTick; | ||
68 | bool UseBytesForPercents; | ||
69 | unsigned MaxLen; | ||
70 | 72 | ||
71 | CProgressBox(UInt32 tickStep = 200): | 73 | CProgressBox(UInt32 tickStep = 200): |
72 | _tickStep(tickStep), | 74 | _tickStep(tickStep), |
73 | _prevTick(0), | 75 | _prevTick(0), |
74 | StartTick(0), | ||
75 | UseBytesForPercents(true), | 76 | UseBytesForPercents(true), |
77 | StartTick(0), | ||
76 | MaxLen(60) | 78 | MaxLen(60) |
77 | {} | 79 | {} |
78 | 80 | ||
diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp index 94f0a47..16702d3 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp | |||
@@ -210,6 +210,96 @@ Z7_COM7F_IMF(CUpdateCallback100Imp::ReportUpdateOperation(UInt32 op, const wchar | |||
210 | } | 210 | } |
211 | 211 | ||
212 | 212 | ||
213 | HRESULT CUpdateCallback100Imp::MoveArc_UpdateStatus() | ||
214 | { | ||
215 | MT_LOCK | ||
216 | |||
217 | if (_percent) | ||
218 | { | ||
219 | AString s; | ||
220 | s.Add_UInt64(_arcMoving_percents); | ||
221 | // status.Add_Space(); | ||
222 | s.Add_Char('%'); | ||
223 | const bool totalDefined = (_arcMoving_total != 0 && _arcMoving_total != (UInt64)(Int64)-1); | ||
224 | if (_arcMoving_current != 0 || totalDefined) | ||
225 | { | ||
226 | s += " : "; | ||
227 | s.Add_UInt64(_arcMoving_current >> 20); | ||
228 | s += " MiB"; | ||
229 | } | ||
230 | if (totalDefined) | ||
231 | { | ||
232 | s += " / "; | ||
233 | s.Add_UInt64((_arcMoving_total + ((1 << 20) - 1)) >> 20); | ||
234 | s += " MiB"; | ||
235 | } | ||
236 | s += " : temporary archive moving ..."; | ||
237 | _percent->Command = s; | ||
238 | _percent->Print(); | ||
239 | } | ||
240 | |||
241 | return CheckBreak2(); | ||
242 | } | ||
243 | |||
244 | |||
245 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Start(const wchar_t *srcTempPath, const wchar_t * /* destFinalPath */ , UInt64 size, Int32 /* updateMode */)) | ||
246 | { | ||
247 | MT_LOCK | ||
248 | |||
249 | _arcMoving_total = size; | ||
250 | _arcMoving_current = 0; | ||
251 | _arcMoving_percents = 0; | ||
252 | // _arcMoving_updateMode = updateMode; | ||
253 | // _name2 = fs2us(destFinalPath); | ||
254 | if (_percent) | ||
255 | _percent->FileName = srcTempPath; | ||
256 | return MoveArc_UpdateStatus(); | ||
257 | } | ||
258 | |||
259 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) | ||
260 | { | ||
261 | UInt64 percents = 0; | ||
262 | if (totalSize != 0) | ||
263 | { | ||
264 | if (totalSize < ((UInt64)1 << 57)) | ||
265 | percents = currentSize * 100 / totalSize; | ||
266 | else | ||
267 | percents = currentSize / (totalSize / 100); | ||
268 | } | ||
269 | |||
270 | #ifdef _WIN32 | ||
271 | // Sleep(300); // for debug | ||
272 | #endif | ||
273 | if (percents == _arcMoving_percents) | ||
274 | return CheckBreak2(); | ||
275 | _arcMoving_total = totalSize; | ||
276 | _arcMoving_current = currentSize; | ||
277 | _arcMoving_percents = percents; | ||
278 | // if (_arcMoving_percents > 100) return E_FAIL; | ||
279 | return MoveArc_UpdateStatus(); | ||
280 | } | ||
281 | |||
282 | |||
283 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Finish()) | ||
284 | { | ||
285 | // _arcMoving_percents = 0; | ||
286 | if (_percent) | ||
287 | { | ||
288 | _percent->Command.Empty(); | ||
289 | _percent->FileName.Empty(); | ||
290 | _percent->Print(); | ||
291 | } | ||
292 | return CheckBreak2(); | ||
293 | } | ||
294 | |||
295 | |||
296 | Z7_COM7F_IMF(CUpdateCallback100Imp::Before_ArcReopen()) | ||
297 | { | ||
298 | // fixme: we can use Clear_Stop_Status() here | ||
299 | return CheckBreak2(); | ||
300 | } | ||
301 | |||
302 | |||
213 | extern HRESULT GetPassword(UString &password); | 303 | extern HRESULT GetPassword(UString &password); |
214 | 304 | ||
215 | Z7_COM7F_IMF(CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)) | 305 | Z7_COM7F_IMF(CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)) |
diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h index 4ec5eed..8d2c8b8 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.h +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h | |||
@@ -11,10 +11,11 @@ | |||
11 | 11 | ||
12 | #include "ProgressBox.h" | 12 | #include "ProgressBox.h" |
13 | 13 | ||
14 | Z7_CLASS_IMP_COM_6( | 14 | Z7_CLASS_IMP_COM_7( |
15 | CUpdateCallback100Imp | 15 | CUpdateCallback100Imp |
16 | , IFolderArchiveUpdateCallback | 16 | , IFolderArchiveUpdateCallback |
17 | , IFolderArchiveUpdateCallback2 | 17 | , IFolderArchiveUpdateCallback2 |
18 | , IFolderArchiveUpdateCallback_MoveArc | ||
18 | , IFolderScanProgress | 19 | , IFolderScanProgress |
19 | , ICryptoGetTextPassword2 | 20 | , ICryptoGetTextPassword2 |
20 | , ICryptoGetTextPassword | 21 | , ICryptoGetTextPassword |
@@ -25,6 +26,15 @@ Z7_CLASS_IMP_COM_6( | |||
25 | // CMyComPtr<IInFolderArchive> _archiveHandler; | 26 | // CMyComPtr<IInFolderArchive> _archiveHandler; |
26 | CProgressBox *_percent; | 27 | CProgressBox *_percent; |
27 | // UInt64 _total; | 28 | // UInt64 _total; |
29 | |||
30 | HRESULT MoveArc_UpdateStatus(); | ||
31 | |||
32 | private: | ||
33 | UInt64 _arcMoving_total; | ||
34 | UInt64 _arcMoving_current; | ||
35 | UInt64 _arcMoving_percents; | ||
36 | // Int32 _arcMoving_updateMode; | ||
37 | |||
28 | public: | 38 | public: |
29 | bool PasswordIsDefined; | 39 | bool PasswordIsDefined; |
30 | UString Password; | 40 | UString Password; |
@@ -38,6 +48,10 @@ public: | |||
38 | _percent = progressBox; | 48 | _percent = progressBox; |
39 | PasswordIsDefined = false; | 49 | PasswordIsDefined = false; |
40 | Password.Empty(); | 50 | Password.Empty(); |
51 | _arcMoving_total = 0; | ||
52 | _arcMoving_current = 0; | ||
53 | _arcMoving_percents = 0; | ||
54 | // _arcMoving_updateMode = 0; | ||
41 | } | 55 | } |
42 | }; | 56 | }; |
43 | 57 | ||
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile index a66f9d7..7bc166b 100644 --- a/CPP/7zip/UI/Far/makefile +++ b/CPP/7zip/UI/Far/makefile | |||
@@ -99,9 +99,9 @@ COMPRESS_OBJS = \ | |||
99 | C_OBJS = \ | 99 | C_OBJS = \ |
100 | $O\Alloc.obj \ | 100 | $O\Alloc.obj \ |
101 | $O\CpuArch.obj \ | 101 | $O\CpuArch.obj \ |
102 | $O\Sort.obj \ | ||
103 | $O\Threads.obj \ | 102 | $O\Threads.obj \ |
104 | 103 | ||
105 | !include "../../Crc.mak" | 104 | !include "../../Crc.mak" |
105 | !include "../../Sort.mak" | ||
106 | 106 | ||
107 | !include "../../7zip.mak" | 107 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index 06c2e8b..5b7d616 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp | |||
@@ -402,11 +402,17 @@ void CApp::Save() | |||
402 | // Save_ShowDeleted(ShowDeletedFiles); | 402 | // Save_ShowDeleted(ShowDeletedFiles); |
403 | } | 403 | } |
404 | 404 | ||
405 | void CApp::Release() | 405 | void CApp::ReleaseApp() |
406 | { | 406 | { |
407 | // 24.09: ReleasePanel() will stop panel timer processing. | ||
408 | // but we want to stop timer processing for all panels | ||
409 | // before ReleasePanel() calling. | ||
410 | unsigned i; | ||
411 | for (i = 0; i < kNumPanelsMax; i++) | ||
412 | Panels[i].Disable_Processing_Timer_Notify_StatusBar(); | ||
407 | // It's for unloading COM dll's: don't change it. | 413 | // It's for unloading COM dll's: don't change it. |
408 | for (unsigned i = 0; i < kNumPanelsMax; i++) | 414 | for (i = 0; i < kNumPanelsMax; i++) |
409 | Panels[i].Release(); | 415 | Panels[i].ReleasePanel(); |
410 | } | 416 | } |
411 | 417 | ||
412 | // reduces path to part that exists on disk (or root prefix of path) | 418 | // reduces path to part that exists on disk (or root prefix of path) |
@@ -644,7 +650,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex) | |||
644 | destPath += correctName; | 650 | destPath += correctName; |
645 | 651 | ||
646 | #if defined(_WIN32) && !defined(UNDER_CE) | 652 | #if defined(_WIN32) && !defined(UNDER_CE) |
647 | if (destPath.Len() > 0 && destPath[0] == '\\') | 653 | if (destPath.Len() != 0 && destPath[0] == '\\') |
648 | if (destPath.Len() == 1 || destPath[1] != '\\') | 654 | if (destPath.Len() == 1 || destPath[1] != '\\') |
649 | { | 655 | { |
650 | srcPanel.MessageBox_Error_UnsupportOperation(); | 656 | srcPanel.MessageBox_Error_UnsupportOperation(); |
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index 1e20532..cf74d6a 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h | |||
@@ -109,7 +109,7 @@ public: | |||
109 | HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes); | 109 | HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes); |
110 | void Read(); | 110 | void Read(); |
111 | void Save(); | 111 | void Save(); |
112 | void Release(); | 112 | void ReleaseApp(); |
113 | 113 | ||
114 | // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); } | 114 | // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); } |
115 | void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); } | 115 | void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); } |
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index 6ec6065..da25969 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp | |||
@@ -2,7 +2,6 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | |||
6 | #include "../../../Common/ComTry.h" | 5 | #include "../../../Common/ComTry.h" |
7 | #include "../../../Common/IntToString.h" | 6 | #include "../../../Common/IntToString.h" |
8 | #include "../../../Common/Lang.h" | 7 | #include "../../../Common/Lang.h" |
@@ -27,11 +26,11 @@ | |||
27 | #include "ExtractCallback.h" | 26 | #include "ExtractCallback.h" |
28 | #include "FormatUtils.h" | 27 | #include "FormatUtils.h" |
29 | #include "LangUtils.h" | 28 | #include "LangUtils.h" |
29 | #include "MemDialog.h" | ||
30 | #include "OverwriteDialog.h" | 30 | #include "OverwriteDialog.h" |
31 | #ifndef Z7_NO_CRYPTO | 31 | #ifndef Z7_NO_CRYPTO |
32 | #include "PasswordDialog.h" | 32 | #include "PasswordDialog.h" |
33 | #endif | 33 | #endif |
34 | #include "MemDialog.h" | ||
35 | #include "PropertyName.h" | 34 | #include "PropertyName.h" |
36 | 35 | ||
37 | using namespace NWindows; | 36 | using namespace NWindows; |
@@ -44,9 +43,9 @@ CExtractCallbackImp::~CExtractCallbackImp() {} | |||
44 | 43 | ||
45 | void CExtractCallbackImp::Init() | 44 | void CExtractCallbackImp::Init() |
46 | { | 45 | { |
47 | _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING); | 46 | LangString(IDS_PROGRESS_EXTRACTING, _lang_Extracting); |
48 | _lang_Testing = LangString(IDS_PROGRESS_TESTING); | 47 | LangString(IDS_PROGRESS_TESTING, _lang_Testing); |
49 | _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING); | 48 | LangString(IDS_PROGRESS_SKIPPING, _lang_Skipping); |
50 | _lang_Reading = "Reading"; | 49 | _lang_Reading = "Reading"; |
51 | 50 | ||
52 | NumArchiveErrors = 0; | 51 | NumArchiveErrors = 0; |
@@ -107,19 +106,19 @@ HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *by | |||
107 | { | 106 | { |
108 | if (files) | 107 | if (files) |
109 | { | 108 | { |
110 | _totalFilesDefined = true; | 109 | _totalFiles_Defined = true; |
111 | // res = ProgressDialog->Sync.Set_NumFilesTotal(*files); | 110 | // res = ProgressDialog->Sync.Set_NumFilesTotal(*files); |
112 | } | 111 | } |
113 | else | 112 | else |
114 | _totalFilesDefined = false; | 113 | _totalFiles_Defined = false; |
115 | 114 | ||
116 | if (bytes) | 115 | if (bytes) |
117 | { | 116 | { |
118 | _totalBytesDefined = true; | 117 | _totalBytes_Defined = true; |
119 | ProgressDialog->Sync.Set_NumBytesTotal(*bytes); | 118 | ProgressDialog->Sync.Set_NumBytesTotal(*bytes); |
120 | } | 119 | } |
121 | else | 120 | else |
122 | _totalBytesDefined = false; | 121 | _totalBytes_Defined = false; |
123 | } | 122 | } |
124 | 123 | ||
125 | return res; | 124 | return res; |
@@ -217,7 +216,7 @@ Z7_COM7F_IMF(CExtractCallbackImp::AskOverwrite( | |||
217 | dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder; | 216 | dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder; |
218 | 217 | ||
219 | ProgressDialog->WaitCreating(); | 218 | ProgressDialog->WaitCreating(); |
220 | INT_PTR writeAnswer = dialog.Create(*ProgressDialog); | 219 | const INT_PTR writeAnswer = dialog.Create(*ProgressDialog); |
221 | 220 | ||
222 | switch (writeAnswer) | 221 | switch (writeAnswer) |
223 | { | 222 | { |
@@ -478,10 +477,10 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) | |||
478 | 477 | ||
479 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsIds); i++) | 478 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsIds); i++) |
480 | { | 479 | { |
481 | UInt32 f = ((UInt32)1 << i); | 480 | const UInt32 f = (UInt32)1 << i; |
482 | if ((errorFlags & f) == 0) | 481 | if ((errorFlags & f) == 0) |
483 | continue; | 482 | continue; |
484 | UInt32 id = k_ErrorFlagsIds[i]; | 483 | const UInt32 id = k_ErrorFlagsIds[i]; |
485 | UString m = LangString(id); | 484 | UString m = LangString(id); |
486 | if (m.IsEmpty()) | 485 | if (m.IsEmpty()) |
487 | continue; | 486 | continue; |
@@ -512,8 +511,8 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) | |||
512 | 511 | ||
513 | static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) | 512 | static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) |
514 | { | 513 | { |
515 | UInt32 errorFlags = er.GetErrorFlags(); | 514 | const UInt32 errorFlags = er.GetErrorFlags(); |
516 | UInt32 warningFlags = er.GetWarningFlags(); | 515 | const UInt32 warningFlags = er.GetWarningFlags(); |
517 | 516 | ||
518 | if (errorFlags != 0) | 517 | if (errorFlags != 0) |
519 | AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); | 518 | AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); |
@@ -524,7 +523,7 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) | |||
524 | if (warningFlags != 0) | 523 | if (warningFlags != 0) |
525 | { | 524 | { |
526 | s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); | 525 | s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); |
527 | s += ":"; | 526 | s.Add_Colon(); |
528 | s.Add_LF(); | 527 | s.Add_LF(); |
529 | AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); | 528 | AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); |
530 | } | 529 | } |
@@ -852,34 +851,35 @@ Z7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name, | |||
852 | _newVirtFileWasAdded = false; | 851 | _newVirtFileWasAdded = false; |
853 | _hashStream_WasUsed = false; | 852 | _hashStream_WasUsed = false; |
854 | _needUpdateStat = false; | 853 | _needUpdateStat = false; |
854 | _isFolder = IntToBool(isDir); | ||
855 | _curSize_Defined = false; | ||
856 | _curSize = 0; | ||
855 | 857 | ||
856 | if (_hashStream) | 858 | if (_hashStream) |
857 | _hashStream->ReleaseStream(); | 859 | _hashStream->ReleaseStream(); |
858 | 860 | ||
859 | GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); | ||
860 | |||
861 | if (!ProcessAltStreams && _isAltStream) | ||
862 | return S_OK; | ||
863 | |||
864 | _filePath = name; | 861 | _filePath = name; |
865 | _isFolder = IntToBool(isDir); | ||
866 | _curSize = 0; | ||
867 | _curSize_Defined = false; | ||
868 | 862 | ||
869 | UInt64 size = 0; | 863 | UInt64 size = 0; |
870 | bool sizeDefined; | 864 | bool size_Defined; |
871 | { | 865 | { |
872 | NCOM::CPropVariant prop; | 866 | NCOM::CPropVariant prop; |
873 | RINOK(getProp->GetProp(kpidSize, &prop)) | 867 | RINOK(getProp->GetProp(kpidSize, &prop)) |
874 | sizeDefined = ConvertPropVariantToUInt64(prop, size); | 868 | size_Defined = ConvertPropVariantToUInt64(prop, size); |
875 | } | 869 | } |
876 | 870 | if (size_Defined) | |
877 | if (sizeDefined) | ||
878 | { | 871 | { |
879 | _curSize = size; | 872 | _curSize = size; |
880 | _curSize_Defined = true; | 873 | _curSize_Defined = true; |
881 | } | 874 | } |
882 | 875 | ||
876 | GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); | ||
877 | if (!ProcessAltStreams && _isAltStream) | ||
878 | return S_OK; | ||
879 | |||
880 | if (isDir) // we don't support dir items extraction in this code | ||
881 | return S_OK; | ||
882 | |||
883 | if (askExtractMode != NArchive::NExtract::NAskMode::kExtract && | 883 | if (askExtractMode != NArchive::NExtract::NAskMode::kExtract && |
884 | askExtractMode != NArchive::NExtract::NAskMode::kTest) | 884 | askExtractMode != NArchive::NExtract::NAskMode::kTest) |
885 | return S_OK; | 885 | return S_OK; |
@@ -890,40 +890,64 @@ Z7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name, | |||
890 | 890 | ||
891 | if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract) | 891 | if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract) |
892 | { | 892 | { |
893 | CVirtFile &file = VirtFileSystemSpec->AddNewFile(); | 893 | if (!VirtFileSystemSpec->Files.IsEmpty()) |
894 | VirtFileSystemSpec->MaxTotalAllocSize -= VirtFileSystemSpec->Files.Back().Data.Size(); | ||
895 | CVirtFile &file = VirtFileSystemSpec->Files.AddNew(); | ||
894 | _newVirtFileWasAdded = true; | 896 | _newVirtFileWasAdded = true; |
895 | file.Name = name; | 897 | // file.IsDir = _isFolder; |
896 | file.IsDir = IntToBool(isDir); | ||
897 | file.IsAltStream = _isAltStream; | 898 | file.IsAltStream = _isAltStream; |
898 | file.Size = 0; | 899 | file.WrittenSize = 0; |
900 | file.ExpectedSize = 0; | ||
901 | if (size_Defined) | ||
902 | file.ExpectedSize = size; | ||
899 | 903 | ||
900 | RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined)) | 904 | if (VirtFileSystemSpec->Index_of_MainExtractedFile_in_Files < 0) |
901 | RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined)) | 905 | if (!file.IsAltStream || VirtFileSystemSpec->IsAltStreamFile) |
902 | RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined)) | 906 | VirtFileSystemSpec->Index_of_MainExtractedFile_in_Files = |
907 | (int)(VirtFileSystemSpec->Files.Size() - 1); | ||
903 | 908 | ||
904 | NCOM::CPropVariant prop; | 909 | /* if we open only AltStream, then (name) contains only name without "fileName:" prefix */ |
905 | RINOK(getProp->GetProp(kpidAttrib, &prop)) | 910 | file.BaseName = name; |
906 | if (prop.vt == VT_UI4) | 911 | |
912 | if (file.IsAltStream | ||
913 | && !VirtFileSystemSpec->IsAltStreamFile | ||
914 | && file.BaseName.IsPrefixedBy_NoCase(VirtFileSystemSpec->FileName)) | ||
907 | { | 915 | { |
908 | file.Attrib = prop.ulVal; | 916 | const unsigned colonPos = VirtFileSystemSpec->FileName.Len(); |
909 | file.AttribDefined = true; | 917 | if (file.BaseName[colonPos] == ':') |
918 | { | ||
919 | file.ColonWasUsed = true; | ||
920 | file.AltStreamName = name + (size_t)colonPos + 1; | ||
921 | file.BaseName.DeleteFrom(colonPos); | ||
922 | if (Is_ZoneId_StreamName(file.AltStreamName)) | ||
923 | { | ||
924 | if (VirtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files < 0) | ||
925 | VirtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files = | ||
926 | (int)(VirtFileSystemSpec->Files.Size() - 1); | ||
927 | } | ||
928 | } | ||
929 | } | ||
930 | RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTime_Defined)) | ||
931 | RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATime_Defined)) | ||
932 | RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTime_Defined)) | ||
933 | { | ||
934 | NCOM::CPropVariant prop; | ||
935 | RINOK(getProp->GetProp(kpidAttrib, &prop)) | ||
936 | if (prop.vt == VT_UI4) | ||
937 | { | ||
938 | file.Attrib = prop.ulVal; | ||
939 | file.Attrib_Defined = true; | ||
940 | } | ||
910 | } | 941 | } |
911 | // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY; | ||
912 | |||
913 | file.ExpectedSize = 0; | ||
914 | if (sizeDefined) | ||
915 | file.ExpectedSize = size; | ||
916 | outStreamLoc = VirtFileSystem; | 942 | outStreamLoc = VirtFileSystem; |
917 | } | 943 | } |
918 | 944 | ||
919 | if (_hashStream) | 945 | if (_hashStream) |
920 | { | 946 | { |
921 | { | 947 | _hashStream->SetStream(outStreamLoc); |
922 | _hashStream->SetStream(outStreamLoc); | 948 | outStreamLoc = _hashStream; |
923 | outStreamLoc = _hashStream; | 949 | _hashStream->Init(true); |
924 | _hashStream->Init(true); | 950 | _hashStream_WasUsed = true; |
925 | _hashStream_WasUsed = true; | ||
926 | } | ||
927 | } | 951 | } |
928 | 952 | ||
929 | if (outStreamLoc) | 953 | if (outStreamLoc) |
@@ -1077,10 +1101,10 @@ Z7_COM7F_IMF(CExtractCallbackImp::RequestMemoryUse( | |||
1077 | // if (indexType == NArchive::NEventIndexType::kNoIndex) | 1101 | // if (indexType == NArchive::NEventIndexType::kNoIndex) |
1078 | if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) || | 1102 | if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) || |
1079 | (flags & NRequestMemoryUseFlags::k_Report_SkipArc)) | 1103 | (flags & NRequestMemoryUseFlags::k_Report_SkipArc)) |
1080 | s += LangString(IDS_MSG_ARC_UNPACKING_WAS_SKIPPED); | 1104 | AddLangString(s, IDS_MSG_ARC_UNPACKING_WAS_SKIPPED); |
1081 | /* | 1105 | /* |
1082 | else | 1106 | else |
1083 | s += LangString(IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED); | 1107 | AddLangString(, IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED); |
1084 | */ | 1108 | */ |
1085 | AddError_Message_ShowArcPath(s); | 1109 | AddError_Message_ShowArcPath(s); |
1086 | } | 1110 | } |
@@ -1093,88 +1117,154 @@ Z7_COM7F_IMF(CExtractCallbackImp::RequestMemoryUse( | |||
1093 | } | 1117 | } |
1094 | 1118 | ||
1095 | 1119 | ||
1096 | |||
1097 | // static const UInt32 kBlockSize = ((UInt32)1 << 31); | ||
1098 | |||
1099 | Z7_COM7F_IMF(CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)) | 1120 | Z7_COM7F_IMF(CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)) |
1100 | { | 1121 | { |
1101 | if (processedSize) | 1122 | if (processedSize) |
1102 | *processedSize = 0; | 1123 | *processedSize = 0; |
1103 | if (size == 0) | 1124 | if (size == 0) |
1104 | return S_OK; | 1125 | return S_OK; |
1105 | if (!_fileMode) | 1126 | if (!_wasSwitchedToFsMode) |
1106 | { | 1127 | { |
1107 | CVirtFile &file = Files.Back(); | 1128 | CVirtFile &file = Files.Back(); |
1108 | size_t rem = file.Data.Size() - (size_t)file.Size; | 1129 | const size_t rem = file.Data.Size() - file.WrittenSize; |
1109 | bool useMem = true; | 1130 | bool useMem = true; |
1110 | if (rem < size) | 1131 | if (rem < size) |
1111 | { | 1132 | { |
1112 | UInt64 b = 0; | 1133 | UInt64 b = 0; |
1113 | if (file.Data.Size() == 0) | 1134 | if (file.Data.Size() == 0) |
1114 | b = file.ExpectedSize; | 1135 | b = file.ExpectedSize; |
1115 | UInt64 a = file.Size + size; | 1136 | UInt64 a = (UInt64)file.WrittenSize + size; |
1116 | if (b < a) | 1137 | if (b < a) |
1117 | b = a; | 1138 | b = a; |
1118 | a = (UInt64)file.Data.Size() * 2; | 1139 | a = (UInt64)file.Data.Size() * 2; |
1119 | if (b < a) | 1140 | if (b < a) |
1120 | b = a; | 1141 | b = a; |
1121 | useMem = false; | 1142 | useMem = false; |
1122 | const size_t b_sizet = (size_t)b; | 1143 | if (b <= MaxTotalAllocSize) |
1123 | if (b == b_sizet && b <= MaxTotalAllocSize) | 1144 | useMem = file.Data.ReAlloc_KeepData((size_t)b, file.WrittenSize); |
1124 | useMem = file.Data.ReAlloc_KeepData(b_sizet, (size_t)file.Size); | ||
1125 | } | 1145 | } |
1146 | |||
1147 | #if 0 // 1 for debug : FLUSHING TO FS | ||
1148 | useMem = false; | ||
1149 | #endif | ||
1150 | |||
1126 | if (useMem) | 1151 | if (useMem) |
1127 | { | 1152 | { |
1128 | memcpy(file.Data + file.Size, data, size); | 1153 | memcpy(file.Data + file.WrittenSize, data, size); |
1129 | file.Size += size; | 1154 | file.WrittenSize += size; |
1130 | if (processedSize) | 1155 | if (processedSize) |
1131 | *processedSize = (UInt32)size; | 1156 | *processedSize = (UInt32)size; |
1132 | return S_OK; | 1157 | return S_OK; |
1133 | } | 1158 | } |
1134 | _fileMode = true; | 1159 | _wasSwitchedToFsMode = true; |
1160 | } | ||
1161 | |||
1162 | if (!_newVirtFileStream_IsReadyToWrite) // we check for _newVirtFileStream_IsReadyToWrite to optimize execution | ||
1163 | { | ||
1164 | RINOK(FlushToDisk(false)) | ||
1135 | } | 1165 | } |
1136 | RINOK(FlushToDisk(false)) | 1166 | |
1137 | return _outFileStream.Interface()->Write(data, size, processedSize); | 1167 | if (_needWriteToRealFile) |
1168 | return _outFileStream.Interface()->Write(data, size, processedSize); | ||
1169 | if (processedSize) | ||
1170 | *processedSize = size; | ||
1171 | return S_OK; | ||
1138 | } | 1172 | } |
1139 | 1173 | ||
1140 | 1174 | ||
1141 | HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) | 1175 | HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) |
1142 | { | 1176 | { |
1143 | _outFileStream.Create_if_Empty(); | ||
1144 | while (_numFlushed < Files.Size()) | 1177 | while (_numFlushed < Files.Size()) |
1145 | { | 1178 | { |
1146 | const CVirtFile &file = Files[_numFlushed]; | 1179 | CVirtFile &file = Files[_numFlushed]; |
1147 | const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name)); | 1180 | const FString basePath = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.BaseName)); |
1148 | if (!_fileIsOpen) | 1181 | FString path = basePath; |
1182 | |||
1183 | if (file.ColonWasUsed) | ||
1149 | { | 1184 | { |
1150 | if (!_outFileStream->Create_NEW(path)) | 1185 | if (ZoneBuf.Size() != 0 |
1186 | && Is_ZoneId_StreamName(file.AltStreamName)) | ||
1151 | { | 1187 | { |
1152 | // do we need to release stream here? | 1188 | // it's expected that |
1153 | // _outFileStream.Release(); | 1189 | // CArchiveExtractCallback::GetStream() have excluded |
1154 | return E_FAIL; | 1190 | // ZoneId alt stream from extraction already. |
1155 | // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); | 1191 | // But we exclude alt stream extraction here too. |
1192 | _numFlushed++; | ||
1193 | continue; | ||
1156 | } | 1194 | } |
1157 | _fileIsOpen = true; | 1195 | path.Add_Colon(); |
1158 | RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size)) | 1196 | path += us2fs(Get_Correct_FsFile_Name(file.AltStreamName)); |
1159 | } | 1197 | } |
1198 | |||
1199 | if (!_newVirtFileStream_IsReadyToWrite) | ||
1200 | { | ||
1201 | if (file.ColonWasUsed) | ||
1202 | { | ||
1203 | NFind::CFileInfo parentFi; | ||
1204 | if (parentFi.Find(basePath) | ||
1205 | && parentFi.IsReadOnly()) | ||
1206 | { | ||
1207 | _altStream_NeedRestore_Attrib_bool = true; | ||
1208 | _altStream_NeedRestore_AttribVal = parentFi.Attrib; | ||
1209 | NDir::SetFileAttrib(basePath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); | ||
1210 | } | ||
1211 | } | ||
1212 | _outFileStream.Create_if_Empty(); | ||
1213 | _needWriteToRealFile = _outFileStream->Create_NEW(path); | ||
1214 | if (!_needWriteToRealFile) | ||
1215 | { | ||
1216 | if (!file.ColonWasUsed) | ||
1217 | return GetLastError_noZero_HRESULT(); // it's main file and we can't ignore such error. | ||
1218 | // (file.ColonWasUsed == true) | ||
1219 | // So it's additional alt stream. | ||
1220 | // And we ignore file creation error for additional alt stream. | ||
1221 | // ShowErrorMessage(UString("Can't create file ") + fs2us(path)); | ||
1222 | } | ||
1223 | _newVirtFileStream_IsReadyToWrite = true; | ||
1224 | // _openFilePath = path; | ||
1225 | HRESULT hres = S_OK; | ||
1226 | if (_needWriteToRealFile) | ||
1227 | hres = WriteStream(_outFileStream, file.Data, file.WrittenSize); | ||
1228 | // we free allocated memory buffer after data flushing: | ||
1229 | file.WrittenSize = 0; | ||
1230 | file.Data.Free(); | ||
1231 | RINOK(hres) | ||
1232 | } | ||
1233 | |||
1160 | if (_numFlushed == Files.Size() - 1 && !closeLast) | 1234 | if (_numFlushed == Files.Size() - 1 && !closeLast) |
1161 | break; | 1235 | break; |
1162 | if (file.CTimeDefined || | 1236 | |
1163 | file.ATimeDefined || | 1237 | if (_needWriteToRealFile) |
1164 | file.MTimeDefined) | 1238 | { |
1165 | _outFileStream->SetTime( | 1239 | if (file.CTime_Defined || |
1166 | file.CTimeDefined ? &file.CTime : NULL, | 1240 | file.ATime_Defined || |
1167 | file.ATimeDefined ? &file.ATime : NULL, | 1241 | file.MTime_Defined) |
1168 | file.MTimeDefined ? &file.MTime : NULL); | 1242 | _outFileStream->SetTime( |
1169 | _outFileStream->Close(); | 1243 | file.CTime_Defined ? &file.CTime : NULL, |
1244 | file.ATime_Defined ? &file.ATime : NULL, | ||
1245 | file.MTime_Defined ? &file.MTime : NULL); | ||
1246 | _outFileStream->Close(); | ||
1247 | } | ||
1248 | |||
1170 | _numFlushed++; | 1249 | _numFlushed++; |
1171 | _fileIsOpen = false; | 1250 | _newVirtFileStream_IsReadyToWrite = false; |
1172 | 1251 | ||
1173 | if (ZoneBuf.Size() != 0) | 1252 | if (_needWriteToRealFile) |
1174 | WriteZoneFile_To_BaseFile(path, ZoneBuf); | 1253 | { |
1175 | 1254 | if (!file.ColonWasUsed | |
1176 | if (file.AttribDefined) | 1255 | && ZoneBuf.Size() != 0) |
1177 | NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib); | 1256 | WriteZoneFile_To_BaseFile(path, ZoneBuf); |
1257 | if (file.Attrib_Defined) | ||
1258 | NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib); | ||
1259 | // _openFilePath.Empty(); | ||
1260 | _needWriteToRealFile = false; | ||
1261 | } | ||
1262 | |||
1263 | if (_altStream_NeedRestore_Attrib_bool) | ||
1264 | { | ||
1265 | _altStream_NeedRestore_Attrib_bool = false; | ||
1266 | NDir::SetFileAttrib(basePath, _altStream_NeedRestore_AttribVal); | ||
1267 | } | ||
1178 | } | 1268 | } |
1179 | return S_OK; | 1269 | return S_OK; |
1180 | } | 1270 | } |
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h index 5c459aa..8b4dcb3 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h | |||
@@ -25,10 +25,6 @@ | |||
25 | 25 | ||
26 | #include "ProgressDialog2.h" | 26 | #include "ProgressDialog2.h" |
27 | 27 | ||
28 | #ifdef Z7_LANG | ||
29 | // #include "LangUtils.h" | ||
30 | #endif | ||
31 | |||
32 | #ifndef Z7_SFX | 28 | #ifndef Z7_SFX |
33 | 29 | ||
34 | class CGrowBuf | 30 | class CGrowBuf |
@@ -39,12 +35,24 @@ class CGrowBuf | |||
39 | Z7_CLASS_NO_COPY(CGrowBuf) | 35 | Z7_CLASS_NO_COPY(CGrowBuf) |
40 | 36 | ||
41 | public: | 37 | public: |
38 | void Free() | ||
39 | { | ||
40 | MyFree(_items); | ||
41 | _items = NULL; | ||
42 | _size = 0; | ||
43 | } | ||
44 | |||
45 | // newSize >= keepSize | ||
42 | bool ReAlloc_KeepData(size_t newSize, size_t keepSize) | 46 | bool ReAlloc_KeepData(size_t newSize, size_t keepSize) |
43 | { | 47 | { |
44 | void *buf = MyAlloc(newSize); | 48 | void *buf = NULL; |
45 | if (!buf) | 49 | if (newSize) |
46 | return false; | 50 | { |
47 | if (keepSize != 0) | 51 | buf = MyAlloc(newSize); |
52 | if (!buf) | ||
53 | return false; | ||
54 | } | ||
55 | if (keepSize) | ||
48 | memcpy(buf, _items, keepSize); | 56 | memcpy(buf, _items, keepSize); |
49 | MyFree(_items); | 57 | MyFree(_items); |
50 | _items = (Byte *)buf; | 58 | _items = (Byte *)buf; |
@@ -60,23 +68,27 @@ public: | |||
60 | size_t Size() const { return _size; } | 68 | size_t Size() const { return _size; } |
61 | }; | 69 | }; |
62 | 70 | ||
71 | |||
63 | struct CVirtFile | 72 | struct CVirtFile |
64 | { | 73 | { |
65 | CGrowBuf Data; | 74 | CGrowBuf Data; |
66 | 75 | ||
67 | UInt64 Size; // real size | 76 | UInt64 ExpectedSize; // size from props request. 0 if unknown |
68 | UInt64 ExpectedSize; // the size from props request. 0 if unknown | 77 | size_t WrittenSize; // size of written data in (Data) buffer |
69 | 78 | // use (WrittenSize) only if (CVirtFileSystem::_newVirtFileStream_IsReadyToWrite == false) | |
70 | UString Name; | 79 | UString BaseName; // original name of file inside archive, |
71 | 80 | // It's not path. So any path separators | |
72 | bool CTimeDefined; | 81 | // should be treated as part of name (or as incorrect chars) |
73 | bool ATimeDefined; | 82 | UString AltStreamName; |
74 | bool MTimeDefined; | 83 | |
75 | bool AttribDefined; | 84 | bool CTime_Defined; |
85 | bool ATime_Defined; | ||
86 | bool MTime_Defined; | ||
87 | bool Attrib_Defined; | ||
76 | 88 | ||
77 | bool IsDir; | 89 | // bool IsDir; |
78 | bool IsAltStream; | 90 | bool IsAltStream; |
79 | 91 | bool ColonWasUsed; | |
80 | DWORD Attrib; | 92 | DWORD Attrib; |
81 | 93 | ||
82 | FILETIME CTime; | 94 | FILETIME CTime; |
@@ -84,82 +96,82 @@ struct CVirtFile | |||
84 | FILETIME MTime; | 96 | FILETIME MTime; |
85 | 97 | ||
86 | CVirtFile(): | 98 | CVirtFile(): |
87 | CTimeDefined(false), | 99 | CTime_Defined(false), |
88 | ATimeDefined(false), | 100 | ATime_Defined(false), |
89 | MTimeDefined(false), | 101 | MTime_Defined(false), |
90 | AttribDefined(false), | 102 | Attrib_Defined(false), |
91 | IsDir(false), | 103 | // IsDir(false), |
92 | IsAltStream(false) {} | 104 | IsAltStream(false), |
105 | ColonWasUsed(false) | ||
106 | {} | ||
93 | }; | 107 | }; |
94 | 108 | ||
95 | 109 | ||
110 | /* | ||
111 | We use CVirtFileSystem only for single file extraction: | ||
112 | It supports the following cases and names: | ||
113 | - "fileName" : single file | ||
114 | - "fileName" item (main base file) and additional "fileName:altStream" items | ||
115 | - "altStream" : single item without "fileName:" prefix. | ||
116 | If file is flushed to disk, it uses Get_Correct_FsFile_Name(name). | ||
117 | */ | ||
118 | |||
96 | Z7_CLASS_IMP_NOQIB_1( | 119 | Z7_CLASS_IMP_NOQIB_1( |
97 | CVirtFileSystem, | 120 | CVirtFileSystem, |
98 | ISequentialOutStream | 121 | ISequentialOutStream |
99 | ) | 122 | ) |
100 | UInt64 _totalAllocSize; | ||
101 | |||
102 | size_t _pos; | ||
103 | unsigned _numFlushed; | 123 | unsigned _numFlushed; |
104 | bool _fileIsOpen; | 124 | public: |
105 | bool _fileMode; | 125 | bool IsAltStreamFile; // in: |
126 | // = true, if extracting file is alt stream without "fileName:" prefix. | ||
127 | // = false, if extracting file is normal file, but additional | ||
128 | // alt streams "fileName:altStream" items are possible. | ||
129 | private: | ||
130 | bool _newVirtFileStream_IsReadyToWrite; // it can non real file (if can't open alt stream) | ||
131 | bool _needWriteToRealFile; // we need real writing to open file. | ||
132 | bool _wasSwitchedToFsMode; | ||
133 | bool _altStream_NeedRestore_Attrib_bool; | ||
134 | DWORD _altStream_NeedRestore_AttribVal; | ||
135 | |||
106 | CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream; | 136 | CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream; |
107 | public: | 137 | public: |
108 | CObjectVector<CVirtFile> Files; | 138 | CObjectVector<CVirtFile> Files; |
109 | UInt64 MaxTotalAllocSize; | 139 | size_t MaxTotalAllocSize; // remain size, including Files.Back() |
110 | FString DirPrefix; | 140 | FString DirPrefix; // files will be flushed to this FS directory. |
141 | UString FileName; // name of file that will be extracted. | ||
142 | // it can be name of alt stream without "fileName:" prefix, if (IsAltStreamFile == trye). | ||
143 | // we use that name to detect altStream part in "FileName:altStream". | ||
111 | CByteBuffer ZoneBuf; | 144 | CByteBuffer ZoneBuf; |
145 | int Index_of_MainExtractedFile_in_Files; // out: index in Files. == -1, if expected file was not extracted | ||
146 | int Index_of_ZoneBuf_AltStream_in_Files; // out: index in Files. == -1, if no zonbuf alt stream | ||
147 | |||
112 | 148 | ||
113 | 149 | CVirtFileSystem() | |
114 | CVirtFile &AddNewFile() | ||
115 | { | 150 | { |
116 | if (!Files.IsEmpty()) | 151 | _numFlushed = 0; |
117 | { | 152 | IsAltStreamFile = false; |
118 | MaxTotalAllocSize -= Files.Back().Data.Size(); | 153 | _newVirtFileStream_IsReadyToWrite = false; |
119 | } | 154 | _needWriteToRealFile = false; |
120 | return Files.AddNew(); | 155 | _wasSwitchedToFsMode = false; |
156 | _altStream_NeedRestore_Attrib_bool = false; | ||
157 | MaxTotalAllocSize = (size_t)0 - 1; | ||
158 | Index_of_MainExtractedFile_in_Files = -1; | ||
159 | Index_of_ZoneBuf_AltStream_in_Files = -1; | ||
121 | } | 160 | } |
161 | |||
162 | bool WasStreamFlushedToFS() const { return _wasSwitchedToFsMode; } | ||
163 | |||
122 | HRESULT CloseMemFile() | 164 | HRESULT CloseMemFile() |
123 | { | 165 | { |
124 | if (_fileMode) | 166 | if (_wasSwitchedToFsMode) |
125 | { | 167 | return FlushToDisk(true); // closeLast |
126 | return FlushToDisk(true); | ||
127 | } | ||
128 | CVirtFile &file = Files.Back(); | 168 | CVirtFile &file = Files.Back(); |
129 | if (file.Data.Size() != file.Size) | 169 | if (file.Data.Size() != file.WrittenSize) |
130 | { | 170 | file.Data.ReAlloc_KeepData(file.WrittenSize, file.WrittenSize); |
131 | file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size); | ||
132 | } | ||
133 | return S_OK; | 171 | return S_OK; |
134 | } | 172 | } |
135 | 173 | ||
136 | bool IsStreamInMem() const | ||
137 | { | ||
138 | if (_fileMode) | ||
139 | return false; | ||
140 | if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir) | ||
141 | return false; | ||
142 | return true; | ||
143 | } | ||
144 | |||
145 | size_t GetMemStreamWrittenSize() const { return _pos; } | ||
146 | |||
147 | CVirtFileSystem(): | ||
148 | MaxTotalAllocSize((UInt64)0 - 1) | ||
149 | {} | ||
150 | |||
151 | void Init() | ||
152 | { | ||
153 | _totalAllocSize = 0; | ||
154 | _fileMode = false; | ||
155 | _pos = 0; | ||
156 | _numFlushed = 0; | ||
157 | _fileIsOpen = false; | ||
158 | } | ||
159 | |||
160 | HRESULT CloseFile(const FString &path); | ||
161 | HRESULT FlushToDisk(bool closeLast); | 174 | HRESULT FlushToDisk(bool closeLast); |
162 | size_t GetPos() const { return _pos; } | ||
163 | }; | 175 | }; |
164 | 176 | ||
165 | #endif | 177 | #endif |
@@ -217,12 +229,12 @@ class CExtractCallbackImp Z7_final: | |||
217 | 229 | ||
218 | bool _needWriteArchivePath; | 230 | bool _needWriteArchivePath; |
219 | bool _isFolder; | 231 | bool _isFolder; |
220 | bool _totalFilesDefined; | 232 | bool _totalFiles_Defined; |
221 | bool _totalBytesDefined; | 233 | bool _totalBytes_Defined; |
222 | public: | 234 | public: |
223 | bool MultiArcMode; | 235 | bool MultiArcMode; |
224 | bool ProcessAltStreams; | 236 | bool ProcessAltStreams; |
225 | bool StreamMode; | 237 | bool StreamMode; // set to true, if you want the callee to call GetStream7() |
226 | bool ThereAreMessageErrors; | 238 | bool ThereAreMessageErrors; |
227 | bool Src_Is_IO_FS_Folder; | 239 | bool Src_Is_IO_FS_Folder; |
228 | 240 | ||
@@ -246,9 +258,17 @@ private: | |||
246 | bool _skipArc; | 258 | bool _skipArc; |
247 | #endif | 259 | #endif |
248 | 260 | ||
261 | public: | ||
262 | bool YesToAll; | ||
263 | bool TestMode; | ||
264 | |||
265 | UInt32 NumArchiveErrors; | ||
266 | NExtract::NOverwriteMode::EEnum OverwriteMode; | ||
267 | |||
268 | private: | ||
249 | UString _currentArchivePath; | 269 | UString _currentArchivePath; |
250 | UString _currentFilePath; | 270 | UString _currentFilePath; |
251 | UString _filePath; | 271 | UString _filePath; // virtual path than will be sent via IFolderExtractToStreamCallback |
252 | 272 | ||
253 | #ifndef Z7_SFX | 273 | #ifndef Z7_SFX |
254 | UInt64 _curSize; | 274 | UInt64 _curSize; |
@@ -266,12 +286,6 @@ public: | |||
266 | UInt64 NumFiles; | 286 | UInt64 NumFiles; |
267 | #endif | 287 | #endif |
268 | 288 | ||
269 | UInt32 NumArchiveErrors; | ||
270 | NExtract::NOverwriteMode::EEnum OverwriteMode; | ||
271 | |||
272 | bool YesToAll; | ||
273 | bool TestMode; | ||
274 | |||
275 | #ifndef Z7_NO_CRYPTO | 289 | #ifndef Z7_NO_CRYPTO |
276 | UString Password; | 290 | UString Password; |
277 | #endif | 291 | #endif |
@@ -283,8 +297,8 @@ public: | |||
283 | UString _lang_Empty; | 297 | UString _lang_Empty; |
284 | 298 | ||
285 | CExtractCallbackImp(): | 299 | CExtractCallbackImp(): |
286 | _totalFilesDefined(false) | 300 | _totalFiles_Defined(false) |
287 | , _totalBytesDefined(false) | 301 | , _totalBytes_Defined(false) |
288 | , MultiArcMode(false) | 302 | , MultiArcMode(false) |
289 | , ProcessAltStreams(true) | 303 | , ProcessAltStreams(true) |
290 | , StreamMode(false) | 304 | , StreamMode(false) |
@@ -297,11 +311,13 @@ public: | |||
297 | #ifndef Z7_SFX | 311 | #ifndef Z7_SFX |
298 | , _remember(false) | 312 | , _remember(false) |
299 | , _skipArc(false) | 313 | , _skipArc(false) |
300 | , _hashCalc(NULL) | ||
301 | #endif | 314 | #endif |
302 | , OverwriteMode(NExtract::NOverwriteMode::kAsk) | ||
303 | , YesToAll(false) | 315 | , YesToAll(false) |
304 | , TestMode(false) | 316 | , TestMode(false) |
317 | , OverwriteMode(NExtract::NOverwriteMode::kAsk) | ||
318 | #ifndef Z7_SFX | ||
319 | , _hashCalc(NULL) | ||
320 | #endif | ||
305 | {} | 321 | {} |
306 | 322 | ||
307 | ~CExtractCallbackImp(); | 323 | ~CExtractCallbackImp(); |
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index fe4f2bd..b2f4c2b 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp | |||
@@ -63,8 +63,8 @@ bool g_LargePagesMode = false; | |||
63 | static bool g_Maximized = false; | 63 | static bool g_Maximized = false; |
64 | 64 | ||
65 | extern | 65 | extern |
66 | UInt64 g_RAM_Size; | 66 | size_t g_RAM_Size; |
67 | UInt64 g_RAM_Size; | 67 | size_t g_RAM_Size; |
68 | 68 | ||
69 | #ifdef _WIN32 | 69 | #ifdef _WIN32 |
70 | extern | 70 | extern |
@@ -651,7 +651,7 @@ static int WINAPI WinMain2(int nCmdShow) | |||
651 | SplitStringToTwoStrings(commandsString, paramString, tailString); | 651 | SplitStringToTwoStrings(commandsString, paramString, tailString); |
652 | paramString.Trim(); | 652 | paramString.Trim(); |
653 | tailString.Trim(); | 653 | tailString.Trim(); |
654 | if (tailString.IsPrefixedBy(L"-t")) | 654 | if (tailString.IsPrefixedBy("-t")) |
655 | g_ArcFormat = tailString.Ptr(2); | 655 | g_ArcFormat = tailString.Ptr(2); |
656 | 656 | ||
657 | /* | 657 | /* |
@@ -1025,8 +1025,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
1025 | break; | 1025 | break; |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | case WM_DESTROY: | 1028 | case WM_CLOSE: |
1029 | { | 1029 | { |
1030 | // why do we use WA_INACTIVE here ? | ||
1031 | SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd); | ||
1032 | g_ExitEventLauncher.Exit(false); | ||
1030 | // ::DragAcceptFiles(hWnd, FALSE); | 1033 | // ::DragAcceptFiles(hWnd, FALSE); |
1031 | RevokeDragDrop(hWnd); | 1034 | RevokeDragDrop(hWnd); |
1032 | g_App._dropTarget.Release(); | 1035 | g_App._dropTarget.Release(); |
@@ -1034,12 +1037,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
1034 | if (g_WindowWasCreated) | 1037 | if (g_WindowWasCreated) |
1035 | g_App.Save(); | 1038 | g_App.Save(); |
1036 | 1039 | ||
1037 | g_App.Release(); | 1040 | g_App.ReleaseApp(); |
1038 | 1041 | ||
1039 | if (g_WindowWasCreated) | 1042 | if (g_WindowWasCreated) |
1040 | SaveWindowInfo(hWnd); | 1043 | SaveWindowInfo(hWnd); |
1041 | 1044 | ||
1042 | g_ExitEventLauncher.Exit(true); | 1045 | g_ExitEventLauncher.Exit(true); |
1046 | // default DefWindowProc will call DestroyWindow / WM_DESTROY | ||
1047 | break; | ||
1048 | } | ||
1049 | |||
1050 | case WM_DESTROY: | ||
1051 | { | ||
1043 | PostQuitMessage(0); | 1052 | PostQuitMessage(0); |
1044 | break; | 1053 | break; |
1045 | } | 1054 | } |
diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 8fcb507..4712192 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp | |||
@@ -309,15 +309,13 @@ void ReloadLang() | |||
309 | { | 309 | { |
310 | g_Lang.Clear(); | 310 | g_Lang.Clear(); |
311 | ReadRegLang(g_LangID); | 311 | ReadRegLang(g_LangID); |
312 | #ifndef _UNICODE | 312 | if (g_LangID.IsEmpty()) |
313 | if (g_IsNT) | ||
314 | #endif | ||
315 | { | 313 | { |
316 | if (g_LangID.IsEmpty()) | 314 | #ifndef _UNICODE |
317 | { | 315 | if (g_IsNT) |
316 | #endif | ||
318 | OpenDefaultLang(); | 317 | OpenDefaultLang(); |
319 | return; | 318 | return; |
320 | } | ||
321 | } | 319 | } |
322 | if (g_LangID.Len() > 1 || g_LangID[0] != L'-') | 320 | if (g_LangID.Len() > 1 || g_LangID[0] != L'-') |
323 | { | 321 | { |
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index 0f24761..a92ee4d 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp | |||
@@ -45,28 +45,24 @@ static bool GetSymLink(CFSTR path, CReparseAttr &attr, UString &errorMessage) | |||
45 | CByteBuffer buf; | 45 | CByteBuffer buf; |
46 | if (!NIO::GetReparseData(path, buf, NULL)) | 46 | if (!NIO::GetReparseData(path, buf, NULL)) |
47 | return false; | 47 | return false; |
48 | |||
49 | if (!attr.Parse(buf, buf.Size())) | 48 | if (!attr.Parse(buf, buf.Size())) |
50 | { | 49 | { |
51 | SetLastError(attr.ErrorCode); | 50 | SetLastError(attr.ErrorCode); |
52 | return false; | 51 | return false; |
53 | } | 52 | } |
54 | |||
55 | CByteBuffer data2; | 53 | CByteBuffer data2; |
56 | if (!FillLinkData(data2, attr.GetPath(), | 54 | FillLinkData(data2, attr.GetPath(), |
57 | !attr.IsMountPoint(), attr.IsSymLink_WSL())) | 55 | !attr.IsMountPoint(), attr.IsSymLink_WSL()); |
56 | if (data2.Size() == 0) | ||
58 | { | 57 | { |
59 | errorMessage = "Cannot reproduce reparse point"; | 58 | errorMessage = "Cannot reproduce reparse point"; |
60 | return false; | 59 | return false; |
61 | } | 60 | } |
62 | 61 | if (data2 != buf) | |
63 | if (data2.Size() != buf.Size() || | ||
64 | memcmp(data2, buf, buf.Size()) != 0) | ||
65 | { | 62 | { |
66 | errorMessage = "mismatch for reproduced reparse point"; | 63 | errorMessage = "mismatch for reproduced reparse point"; |
67 | return false; | 64 | return false; |
68 | } | 65 | } |
69 | |||
70 | return true; | 66 | return true; |
71 | } | 67 | } |
72 | 68 | ||
@@ -113,8 +109,8 @@ bool CLinkDialog::OnInit() | |||
113 | const bool res = GetSymLink(us2fs(FilePath), attr, error); | 109 | const bool res = GetSymLink(us2fs(FilePath), attr, error); |
114 | if (!res && error.IsEmpty()) | 110 | if (!res && error.IsEmpty()) |
115 | { | 111 | { |
116 | DWORD lastError = GetLastError(); | 112 | const DWORD lastError = GetLastError(); |
117 | if (lastError != 0) | 113 | if (lastError) |
118 | error = NError::MyFormatMessage(lastError); | 114 | error = NError::MyFormatMessage(lastError); |
119 | } | 115 | } |
120 | 116 | ||
@@ -319,10 +315,10 @@ void CLinkDialog::OnButton_Link() | |||
319 | return; | 315 | return; |
320 | } | 316 | } |
321 | 317 | ||
322 | const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); | ||
323 | |||
324 | CByteBuffer data; | 318 | CByteBuffer data; |
325 | if (!FillLinkData(data, to, isSymLink, isWSL)) | 319 | const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); |
320 | FillLinkData(data, to, isSymLink, isWSL); | ||
321 | if (data.Size() == 0) | ||
326 | { | 322 | { |
327 | ShowError(L"Incorrect link"); | 323 | ShowError(L"Incorrect link"); |
328 | return; | 324 | return; |
@@ -386,6 +382,9 @@ void CApp::Link() | |||
386 | path = destPanel.GetFsPath(); | 382 | path = destPanel.GetFsPath(); |
387 | } | 383 | } |
388 | 384 | ||
385 | CSelectedState srcSelState; | ||
386 | srcPanel.SaveSelectedState(srcSelState); | ||
387 | |||
389 | CLinkDialog dlg; | 388 | CLinkDialog dlg; |
390 | dlg.CurDirPrefix = fsPrefix; | 389 | dlg.CurDirPrefix = fsPrefix; |
391 | dlg.FilePath = srcPath + itemName; | 390 | dlg.FilePath = srcPath + itemName; |
@@ -394,7 +393,10 @@ void CApp::Link() | |||
394 | if (dlg.Create(srcPanel.GetParent()) != IDOK) | 393 | if (dlg.Create(srcPanel.GetParent()) != IDOK) |
395 | return; | 394 | return; |
396 | 395 | ||
397 | // fix it: we should refresh panel with changed link | 396 | // we refresh srcPanel to show changes in "Link" (kpidNtReparse) column. |
397 | // maybe we should refresh another panel also? | ||
398 | if (srcPanel._visibleColumns.FindItem_for_PropID(kpidNtReparse) >= 0) | ||
399 | srcPanel.RefreshListCtrl(srcSelState); | ||
398 | 400 | ||
399 | RefreshTitleAlways(); | 401 | RefreshTitleAlways(); |
400 | } | 402 | } |
diff --git a/CPP/7zip/UI/FileManager/MemDialog.cpp b/CPP/7zip/UI/FileManager/MemDialog.cpp index 1ba717e..5d26d3a 100644 --- a/CPP/7zip/UI/FileManager/MemDialog.cpp +++ b/CPP/7zip/UI/FileManager/MemDialog.cpp | |||
@@ -55,13 +55,13 @@ static void AddSize_GB(UString &s, UInt32 size_GB, UInt32 id) | |||
55 | AddLangString(s, id); | 55 | AddLangString(s, id); |
56 | } | 56 | } |
57 | 57 | ||
58 | void CMemDialog::AddInfoMessage_To_String(UString &s, UInt64 *ramSize_GB) | 58 | void CMemDialog::AddInfoMessage_To_String(UString &s, const UInt32 *ramSize_GB) |
59 | { | 59 | { |
60 | AddLangString(s, IDS_MEM_REQUIRES_BIG_MEM); | 60 | AddLangString(s, IDS_MEM_REQUIRES_BIG_MEM); |
61 | AddSize_GB(s, Required_GB, IDS_MEM_REQUIRED_MEM_SIZE); | 61 | AddSize_GB(s, Required_GB, IDS_MEM_REQUIRED_MEM_SIZE); |
62 | AddSize_GB(s, Limit_GB, IDS_MEM_CURRENT_MEM_LIMIT); | 62 | AddSize_GB(s, Limit_GB, IDS_MEM_CURRENT_MEM_LIMIT); |
63 | if (ramSize_GB) | 63 | if (ramSize_GB) |
64 | AddSize_GB(s, (UInt32)*ramSize_GB, IDS_MEM_RAM_SIZE); | 64 | AddSize_GB(s, *ramSize_GB, IDS_MEM_RAM_SIZE); |
65 | if (!FilePath.IsEmpty()) | 65 | if (!FilePath.IsEmpty()) |
66 | { | 66 | { |
67 | s.Add_LF(); | 67 | s.Add_LF(); |
@@ -88,11 +88,11 @@ bool CMemDialog::OnInit() | |||
88 | 88 | ||
89 | // m_Action.Attach(GetItem(IDC_MEM_ACTION)); | 89 | // m_Action.Attach(GetItem(IDC_MEM_ACTION)); |
90 | 90 | ||
91 | UInt64 ramSize = (UInt64)sizeof(size_t) << 29; | 91 | size_t ramSize = (size_t)sizeof(size_t) << 29; |
92 | const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize); | 92 | const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize); |
93 | // ramSize *= 10; // for debug | 93 | // ramSize *= 10; // for debug |
94 | 94 | ||
95 | UInt64 ramSize_GB = (ramSize + (1u << 29)) >> 30; | 95 | UInt32 ramSize_GB = (UInt32)(((UInt64)ramSize + (1u << 29)) >> 30); |
96 | if (ramSize_GB == 0) | 96 | if (ramSize_GB == 0) |
97 | ramSize_GB = 1; | 97 | ramSize_GB = 1; |
98 | 98 | ||
@@ -121,7 +121,7 @@ bool CMemDialog::OnInit() | |||
121 | if (ramSize_defined) | 121 | if (ramSize_defined) |
122 | { | 122 | { |
123 | s += " / "; | 123 | s += " / "; |
124 | s.Add_UInt64(ramSize_GB); | 124 | s.Add_UInt32(ramSize_GB); |
125 | s += " GB (RAM)"; | 125 | s += " GB (RAM)"; |
126 | } | 126 | } |
127 | SetItemText(IDT_MEM_GB, s); | 127 | SetItemText(IDT_MEM_GB, s); |
diff --git a/CPP/7zip/UI/FileManager/MemDialog.h b/CPP/7zip/UI/FileManager/MemDialog.h index 79de658..67f6b33 100644 --- a/CPP/7zip/UI/FileManager/MemDialog.h +++ b/CPP/7zip/UI/FileManager/MemDialog.h | |||
@@ -30,7 +30,7 @@ public: | |||
30 | UString ArcPath; | 30 | UString ArcPath; |
31 | UString FilePath; | 31 | UString FilePath; |
32 | 32 | ||
33 | void AddInfoMessage_To_String(UString &s, UInt64 *ramSize_GB = NULL); | 33 | void AddInfoMessage_To_String(UString &s, const UInt32 *ramSize_GB = NULL); |
34 | 34 | ||
35 | CMemDialog(): | 35 | CMemDialog(): |
36 | NeedSave(false), | 36 | NeedSave(false), |
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index 51b8648..f190929 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp | |||
@@ -764,8 +764,12 @@ bool ExecuteFileCommand(unsigned id) | |||
764 | case IDM_CRC32: g_App.CalculateCrc("CRC32"); break; | 764 | case IDM_CRC32: g_App.CalculateCrc("CRC32"); break; |
765 | case IDM_CRC64: g_App.CalculateCrc("CRC64"); break; | 765 | case IDM_CRC64: g_App.CalculateCrc("CRC64"); break; |
766 | case IDM_XXH64: g_App.CalculateCrc("XXH64"); break; | 766 | case IDM_XXH64: g_App.CalculateCrc("XXH64"); break; |
767 | case IDM_MD5: g_App.CalculateCrc("MD5"); break; | ||
767 | case IDM_SHA1: g_App.CalculateCrc("SHA1"); break; | 768 | case IDM_SHA1: g_App.CalculateCrc("SHA1"); break; |
768 | case IDM_SHA256: g_App.CalculateCrc("SHA256"); break; | 769 | case IDM_SHA256: g_App.CalculateCrc("SHA256"); break; |
770 | case IDM_SHA384: g_App.CalculateCrc("SHA384"); break; | ||
771 | case IDM_SHA512: g_App.CalculateCrc("SHA512"); break; | ||
772 | case IDM_SHA3_256: g_App.CalculateCrc("SHA3-256"); break; | ||
769 | case IDM_BLAKE2SP: g_App.CalculateCrc("BLAKE2sp"); break; | 773 | case IDM_BLAKE2SP: g_App.CalculateCrc("BLAKE2sp"); break; |
770 | 774 | ||
771 | case IDM_DIFF: g_App.DiffFiles(); break; | 775 | case IDM_DIFF: g_App.DiffFiles(); break; |
@@ -807,8 +811,8 @@ bool OnMenuCommand(HWND hWnd, unsigned id) | |||
807 | { | 811 | { |
808 | // File | 812 | // File |
809 | case IDCLOSE: | 813 | case IDCLOSE: |
810 | SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd); | 814 | // SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd); |
811 | g_ExitEventLauncher.Exit(false); | 815 | // g_ExitEventLauncher.Exit(false); |
812 | SendMessage(hWnd, WM_CLOSE, 0, 0); | 816 | SendMessage(hWnd, WM_CLOSE, 0, 0); |
813 | break; | 817 | break; |
814 | 818 | ||
diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp index 5b6df50..e3cb2ec 100644 --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp | |||
@@ -27,7 +27,7 @@ HRESULT COpenArchiveCallback::Open_SetTotal(const UInt64 *numFiles, const UInt64 | |||
27 | ProgressDialog.Sync.Set_NumFilesTotal(numFiles ? *numFiles : (UInt64)(Int64)-1); | 27 | ProgressDialog.Sync.Set_NumFilesTotal(numFiles ? *numFiles : (UInt64)(Int64)-1); |
28 | // if (numFiles) | 28 | // if (numFiles) |
29 | { | 29 | { |
30 | ProgressDialog.Sync.Set_BytesProgressMode(numFiles == NULL); | 30 | ProgressDialog.Sync.Set_FilesProgressMode(numFiles != NULL); |
31 | } | 31 | } |
32 | if (numBytes) | 32 | if (numBytes) |
33 | ProgressDialog.Sync.Set_NumBytesTotal(*numBytes); | 33 | ProgressDialog.Sync.Set_NumBytesTotal(*numBytes); |
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index f3fb38e..84bd88c 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp | |||
@@ -7,8 +7,8 @@ | |||
7 | #include "../../../Common/IntToString.h" | 7 | #include "../../../Common/IntToString.h" |
8 | #include "../../../Common/StringConvert.h" | 8 | #include "../../../Common/StringConvert.h" |
9 | 9 | ||
10 | #include "../../../Windows/FileName.h" | ||
11 | #include "../../../Windows/ErrorMsg.h" | 10 | #include "../../../Windows/ErrorMsg.h" |
11 | #include "../../../Windows/FileName.h" | ||
12 | #include "../../../Windows/PropVariant.h" | 12 | #include "../../../Windows/PropVariant.h" |
13 | #include "../../../Windows/Thread.h" | 13 | #include "../../../Windows/Thread.h" |
14 | 14 | ||
@@ -49,8 +49,9 @@ static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT }; | |||
49 | 49 | ||
50 | extern HINSTANCE g_hInstance; | 50 | extern HINSTANCE g_hInstance; |
51 | 51 | ||
52 | void CPanel::Release() | 52 | void CPanel::ReleasePanel() |
53 | { | 53 | { |
54 | Disable_Processing_Timer_Notify_StatusBar(); | ||
54 | // It's for unloading COM dll's: don't change it. | 55 | // It's for unloading COM dll's: don't change it. |
55 | CloseOpenFolders(); | 56 | CloseOpenFolders(); |
56 | _sevenZipContextMenu.Release(); | 57 | _sevenZipContextMenu.Release(); |
@@ -893,7 +894,7 @@ void CPanel::SetListViewMode(UInt32 index) | |||
893 | void CPanel::ChangeFlatMode() | 894 | void CPanel::ChangeFlatMode() |
894 | { | 895 | { |
895 | _flatMode = !_flatMode; | 896 | _flatMode = !_flatMode; |
896 | if (_parentFolders.Size() > 0) | 897 | if (!_parentFolders.IsEmpty()) |
897 | _flatModeForArc = _flatMode; | 898 | _flatModeForArc = _flatMode; |
898 | else | 899 | else |
899 | _flatModeForDisk = _flatMode; | 900 | _flatModeForDisk = _flatMode; |
@@ -904,7 +905,7 @@ void CPanel::ChangeFlatMode() | |||
904 | void CPanel::Change_ShowNtfsStrems_Mode() | 905 | void CPanel::Change_ShowNtfsStrems_Mode() |
905 | { | 906 | { |
906 | _showNtfsStrems_Mode = !_showNtfsStrems_Mode; | 907 | _showNtfsStrems_Mode = !_showNtfsStrems_Mode; |
907 | if (_parentFolders.Size() > 0) | 908 | if (!_parentFolders.IsEmpty()) |
908 | _showNtfsStrems_ModeForArc = _showNtfsStrems_Mode; | 909 | _showNtfsStrems_ModeForArc = _showNtfsStrems_Mode; |
909 | else | 910 | else |
910 | _showNtfsStrems_ModeForDisk = _showNtfsStrems_Mode; | 911 | _showNtfsStrems_ModeForDisk = _showNtfsStrems_Mode; |
@@ -1006,7 +1007,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &operatedIndices, UStringV | |||
1006 | 1007 | ||
1007 | void CPanel::ExtractArchives() | 1008 | void CPanel::ExtractArchives() |
1008 | { | 1009 | { |
1009 | if (_parentFolders.Size() > 0) | 1010 | if (!_parentFolders.IsEmpty()) |
1010 | { | 1011 | { |
1011 | _panelCallback->OnCopy(false, false); | 1012 | _panelCallback->OnCopy(false, false); |
1012 | return; | 1013 | return; |
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 1b708f7..9ef0926 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h | |||
@@ -162,32 +162,39 @@ struct CTempFileInfo | |||
162 | NWindows::NFile::NDir::RemoveDir(FolderPath); | 162 | NWindows::NFile::NDir::RemoveDir(FolderPath); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const | 165 | bool WasChanged_from_TempFileInfo(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const |
166 | { | 166 | { |
167 | return newFileInfo.Size != FileInfo.Size || | 167 | return newFileInfo.Size != FileInfo.Size || |
168 | CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; | 168 | CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; |
169 | } | 169 | } |
170 | }; | 170 | }; |
171 | 171 | ||
172 | |||
172 | struct CFolderLink: public CTempFileInfo | 173 | struct CFolderLink: public CTempFileInfo |
173 | { | 174 | { |
174 | bool IsVirtual; | 175 | bool IsVirtual; // == true (if archive was open via IInStream): |
176 | // archive was open from another archive, | ||
177 | // archive size meets the size conditions derived from g_RAM_Size. | ||
178 | // VirtFileSystem was used | ||
179 | // archive was fully extracted to memory. | ||
175 | bool UsePassword; | 180 | bool UsePassword; |
176 | NWindows::NDLL::CLibrary Library; | 181 | NWindows::NDLL::CLibrary Library; |
177 | CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0]) | 182 | CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0]) |
178 | UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level) | 183 | UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level) |
179 | UString Password; | 184 | UString Password; |
180 | |||
181 | UString VirtualPath; // without tail slash | 185 | UString VirtualPath; // without tail slash |
182 | CFolderLink(): IsVirtual(false), UsePassword(false) {} | 186 | CByteBuffer ZoneBuf; // ZoneBuf for virtaul stream (IsVirtual) |
183 | 187 | ||
184 | bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const | 188 | CFolderLink(): IsVirtual(false), UsePassword(false) {} |
189 | bool WasChanged_from_FolderLink(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const | ||
185 | { | 190 | { |
186 | return IsVirtual || CTempFileInfo::WasChanged(newFileInfo); | 191 | // we call it, if we have two real files. |
192 | // if archive was virtual, it means that we have updated that virtual to real file. | ||
193 | return IsVirtual || CTempFileInfo::WasChanged_from_TempFileInfo(newFileInfo); | ||
187 | } | 194 | } |
188 | |||
189 | }; | 195 | }; |
190 | 196 | ||
197 | |||
191 | enum MyMessages | 198 | enum MyMessages |
192 | { | 199 | { |
193 | // we can use WM_USER, since we have defined new window class. | 200 | // we can use WM_USER, since we have defined new window class. |
@@ -268,13 +275,14 @@ struct CCopyToOptions | |||
268 | 275 | ||
269 | bool NeedRegistryZone; | 276 | bool NeedRegistryZone; |
270 | NExtract::NZoneIdMode::EEnum ZoneIdMode; | 277 | NExtract::NZoneIdMode::EEnum ZoneIdMode; |
278 | CByteBuffer ZoneBuf; | ||
271 | 279 | ||
272 | UString folder; | 280 | UString folder; |
273 | 281 | ||
274 | UStringVector hashMethods; | 282 | UStringVector hashMethods; |
275 | 283 | ||
276 | CVirtFileSystem *VirtFileSystemSpec; | 284 | CVirtFileSystem *VirtFileSystemSpec; |
277 | ISequentialOutStream *VirtFileSystem; | 285 | // ISequentialOutStream *VirtFileSystem; |
278 | 286 | ||
279 | CCopyToOptions(): | 287 | CCopyToOptions(): |
280 | streamMode(false), | 288 | streamMode(false), |
@@ -285,8 +293,8 @@ struct CCopyToOptions | |||
285 | showErrorMessages(false), | 293 | showErrorMessages(false), |
286 | NeedRegistryZone(true), | 294 | NeedRegistryZone(true), |
287 | ZoneIdMode(NExtract::NZoneIdMode::kNone), | 295 | ZoneIdMode(NExtract::NZoneIdMode::kNone), |
288 | VirtFileSystemSpec(NULL), | 296 | VirtFileSystemSpec(NULL) |
289 | VirtFileSystem(NULL) | 297 | // , VirtFileSystem(NULL) |
290 | {} | 298 | {} |
291 | }; | 299 | }; |
292 | 300 | ||
@@ -310,11 +318,60 @@ struct COpenResult | |||
310 | 318 | ||
311 | class CPanel Z7_final: public NWindows::NControl::CWindow2 | 319 | class CPanel Z7_final: public NWindows::NControl::CWindow2 |
312 | { | 320 | { |
321 | bool _thereAre_ListView_Items; | ||
322 | // bool _virtualMode; | ||
323 | bool _enableItemChangeNotify; | ||
324 | bool _thereAreDeletedItems; | ||
325 | bool _markDeletedItems; | ||
326 | bool _dontShowMode; | ||
327 | bool _needSaveInfo; | ||
328 | |||
329 | public: | ||
330 | bool PanelCreated; | ||
331 | bool _mySelectMode; | ||
332 | bool _showDots; | ||
333 | bool _showRealFileIcons; | ||
334 | bool _flatMode; | ||
335 | bool _flatModeForArc; | ||
336 | bool _flatModeForDisk; | ||
337 | bool _selectionIsDefined; | ||
338 | // bool _showNtfsStrems_Mode; | ||
339 | // bool _showNtfsStrems_ModeForDisk; | ||
340 | // bool _showNtfsStrems_ModeForArc; | ||
341 | |||
342 | bool _selectMark; | ||
343 | bool _lastFocusedIsList; | ||
344 | |||
345 | bool _processTimer; | ||
346 | bool _processNotify; | ||
347 | bool _processStatusBar; | ||
348 | |||
349 | public: | ||
350 | bool _ascending; | ||
351 | PROPID _sortID; | ||
352 | // int _sortIndex; | ||
353 | Int32 _isRawSortProp; | ||
354 | |||
355 | CMyListView _listView; | ||
356 | CPanelCallback *_panelCallback; | ||
357 | |||
358 | private: | ||
359 | |||
313 | // CExtToIconMap _extToIconMap; | 360 | // CExtToIconMap _extToIconMap; |
314 | UINT _baseID; | 361 | UINT _baseID; |
315 | unsigned _comboBoxID; | 362 | unsigned _comboBoxID; |
316 | UINT _statusBarID; | 363 | UINT _statusBarID; |
317 | 364 | ||
365 | public: | ||
366 | DWORD _exStyle; | ||
367 | // CUIntVector _realIndices; | ||
368 | int _timestampLevel; | ||
369 | UInt32 _listViewMode; | ||
370 | int _xSize; | ||
371 | private: | ||
372 | int _startGroupSelect; | ||
373 | int _prevFocusedItem; | ||
374 | |||
318 | CAppState *_appState; | 375 | CAppState *_appState; |
319 | 376 | ||
320 | virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam, LRESULT &result) Z7_override; | 377 | virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam, LRESULT &result) Z7_override; |
@@ -351,22 +408,7 @@ class CPanel Z7_final: public NWindows::NControl::CWindow2 | |||
351 | bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result); | 408 | bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result); |
352 | 409 | ||
353 | 410 | ||
354 | public: | ||
355 | HWND _mainWindow; | ||
356 | CPanelCallback *_panelCallback; | ||
357 | |||
358 | // void SysIconsWereChanged() { _extToIconMap.Clear(); } | ||
359 | |||
360 | void DeleteItems(bool toRecycleBin); | ||
361 | void CreateFolder(); | ||
362 | void CreateFile(); | ||
363 | bool CorrectFsPath(const UString &path, UString &result); | ||
364 | // bool IsPathForPlugin(const UString &path); | ||
365 | |||
366 | private: | ||
367 | |||
368 | void ChangeWindowSize(int xSize, int ySize); | 411 | void ChangeWindowSize(int xSize, int ySize); |
369 | |||
370 | HRESULT InitColumns(); | 412 | HRESULT InitColumns(); |
371 | void DeleteColumn(unsigned index); | 413 | void DeleteColumn(unsigned index); |
372 | void AddColumn(const CPropColumn &prop); | 414 | void AddColumn(const CPropColumn &prop); |
@@ -379,20 +421,13 @@ private: | |||
379 | void OnInsert(); | 421 | void OnInsert(); |
380 | // void OnUpWithShift(); | 422 | // void OnUpWithShift(); |
381 | // void OnDownWithShift(); | 423 | // void OnDownWithShift(); |
382 | public: | ||
383 | void UpdateSelection(); | ||
384 | void SelectSpec(bool selectMode); | ||
385 | void SelectByType(bool selectMode); | ||
386 | void SelectAll(bool selectMode); | ||
387 | void InvertSelection(); | ||
388 | private: | ||
389 | |||
390 | // UString GetFileType(UInt32 index); | 424 | // UString GetFileType(UInt32 index); |
391 | LRESULT SetItemText(LVITEMW &item); | 425 | LRESULT SetItemText(LVITEMW &item); |
392 | |||
393 | // CRecordVector<PROPID> m_ColumnsPropIDs; | 426 | // CRecordVector<PROPID> m_ColumnsPropIDs; |
394 | 427 | ||
395 | public: | 428 | public: |
429 | HWND _mainWindow; | ||
430 | |||
396 | NWindows::NControl::CReBar _headerReBar; | 431 | NWindows::NControl::CReBar _headerReBar; |
397 | NWindows::NControl::CToolBar _headerToolBar; | 432 | NWindows::NControl::CToolBar _headerToolBar; |
398 | NWindows::NControl:: | 433 | NWindows::NControl:: |
@@ -405,42 +440,57 @@ public: | |||
405 | UStringVector ComboBoxPaths; | 440 | UStringVector ComboBoxPaths; |
406 | // CMyComboBox _headerComboBox; | 441 | // CMyComboBox _headerComboBox; |
407 | CMyComboBoxEdit _comboBoxEdit; | 442 | CMyComboBoxEdit _comboBoxEdit; |
408 | CMyListView _listView; | ||
409 | bool _thereAre_ListView_Items; | ||
410 | NWindows::NControl::CStatusBar _statusBar; | 443 | NWindows::NControl::CStatusBar _statusBar; |
411 | bool _lastFocusedIsList; | ||
412 | // NWindows::NControl::CStatusBar _statusBar2; | 444 | // NWindows::NControl::CStatusBar _statusBar2; |
413 | 445 | ||
414 | DWORD _exStyle; | 446 | CBoolVector _selectedStatusVector; |
415 | bool _showDots; | 447 | CSelectedState _selectedState; |
416 | bool _showRealFileIcons; | ||
417 | // bool _virtualMode; | ||
418 | // CUIntVector _realIndices; | ||
419 | bool _enableItemChangeNotify; | ||
420 | bool _mySelectMode; | ||
421 | 448 | ||
422 | int _timestampLevel; | 449 | UString _currentFolderPrefix; |
450 | |||
451 | CObjectVector<CFolderLink> _parentFolders; | ||
452 | NWindows::NDLL::CLibrary _library; | ||
453 | |||
454 | CMyComPtr<IFolderFolder> _folder; | ||
455 | CBoolVector _isDirVector; | ||
456 | CMyComPtr<IFolderCompare> _folderCompare; | ||
457 | CMyComPtr<IFolderGetItemName> _folderGetItemName; | ||
458 | CMyComPtr<IArchiveGetRawProps> _folderRawProps; | ||
459 | CMyComPtr<IFolderAltStreams> _folderAltStreams; | ||
460 | CMyComPtr<IFolderOperations> _folderOperations; | ||
423 | 461 | ||
462 | // for drag and drop highliting | ||
463 | int m_DropHighlighted_SelectionIndex; | ||
464 | // int m_SubFolderIndex; // realIndex of item in m_Panel list (if drop cursor to that item) | ||
465 | UString m_DropHighlighted_SubFolderName; // name of folder in m_Panel list (if drop cursor to that folder) | ||
466 | |||
467 | // CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex; | ||
468 | UStringVector _fastFolders; | ||
469 | |||
470 | UString _typeIDString; | ||
471 | CListViewInfo _listViewInfo; | ||
472 | |||
473 | CPropColumns _columns; | ||
474 | CPropColumns _visibleColumns; | ||
475 | |||
476 | CMyComPtr<IContextMenu> _sevenZipContextMenu; | ||
477 | CMyComPtr<IContextMenu> _systemContextMenu; | ||
478 | |||
479 | void UpdateSelection(); | ||
480 | void SelectSpec(bool selectMode); | ||
481 | void SelectByType(bool selectMode); | ||
482 | void SelectAll(bool selectMode); | ||
483 | void InvertSelection(); | ||
424 | 484 | ||
425 | void RedrawListItems() | 485 | void RedrawListItems() |
426 | { | 486 | { |
427 | _listView.RedrawAllItems(); | 487 | _listView.RedrawAllItems(); |
428 | } | 488 | } |
429 | |||
430 | |||
431 | CBoolVector _selectedStatusVector; | ||
432 | |||
433 | CSelectedState _selectedState; | ||
434 | bool _thereAreDeletedItems; | ||
435 | bool _markDeletedItems; | ||
436 | |||
437 | bool PanelCreated; | ||
438 | |||
439 | void DeleteListItems() | 489 | void DeleteListItems() |
440 | { | 490 | { |
441 | if (_thereAre_ListView_Items) | 491 | if (_thereAre_ListView_Items) |
442 | { | 492 | { |
443 | bool b = _enableItemChangeNotify; | 493 | const bool b = _enableItemChangeNotify; |
444 | _enableItemChangeNotify = false; | 494 | _enableItemChangeNotify = false; |
445 | _listView.DeleteAllItems(); | 495 | _listView.DeleteAllItems(); |
446 | _thereAre_ListView_Items = false; | 496 | _thereAre_ListView_Items = false; |
@@ -448,6 +498,15 @@ public: | |||
448 | } | 498 | } |
449 | } | 499 | } |
450 | 500 | ||
501 | // void SysIconsWereChanged() { _extToIconMap.Clear(); } | ||
502 | |||
503 | void DeleteItems(bool toRecycleBin); | ||
504 | void CreateFolder(); | ||
505 | void CreateFile(); | ||
506 | bool CorrectFsPath(const UString &path, UString &result); | ||
507 | // bool IsPathForPlugin(const UString &path); | ||
508 | |||
509 | |||
451 | HWND GetParent() const; | 510 | HWND GetParent() const; |
452 | 511 | ||
453 | UInt32 GetRealIndex(const LVITEMW &item) const | 512 | UInt32 GetRealIndex(const LVITEMW &item) const |
@@ -471,46 +530,8 @@ public: | |||
471 | return (unsigned)param; | 530 | return (unsigned)param; |
472 | } | 531 | } |
473 | 532 | ||
474 | UInt32 _listViewMode; | ||
475 | int _xSize; | ||
476 | |||
477 | bool _flatMode; | ||
478 | bool _flatModeForDisk; | ||
479 | bool _flatModeForArc; | ||
480 | |||
481 | // bool _showNtfsStrems_Mode; | ||
482 | // bool _showNtfsStrems_ModeForDisk; | ||
483 | // bool _showNtfsStrems_ModeForArc; | ||
484 | |||
485 | bool _dontShowMode; | ||
486 | |||
487 | |||
488 | UString _currentFolderPrefix; | ||
489 | |||
490 | CObjectVector<CFolderLink> _parentFolders; | ||
491 | NWindows::NDLL::CLibrary _library; | ||
492 | |||
493 | CMyComPtr<IFolderFolder> _folder; | ||
494 | CBoolVector _isDirVector; | ||
495 | CMyComPtr<IFolderCompare> _folderCompare; | ||
496 | CMyComPtr<IFolderGetItemName> _folderGetItemName; | ||
497 | CMyComPtr<IArchiveGetRawProps> _folderRawProps; | ||
498 | CMyComPtr<IFolderAltStreams> _folderAltStreams; | ||
499 | CMyComPtr<IFolderOperations> _folderOperations; | ||
500 | |||
501 | |||
502 | // for drag and drop highliting | ||
503 | int m_DropHighlighted_SelectionIndex; | ||
504 | // int m_SubFolderIndex; // realIndex of item in m_Panel list (if drop cursor to that item) | ||
505 | UString m_DropHighlighted_SubFolderName; // name of folder in m_Panel list (if drop cursor to that folder) | ||
506 | |||
507 | void ReleaseFolder(); | 533 | void ReleaseFolder(); |
508 | void SetNewFolder(IFolderFolder *newFolder); | 534 | void SetNewFolder(IFolderFolder *newFolder); |
509 | |||
510 | // CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex; | ||
511 | |||
512 | UStringVector _fastFolders; | ||
513 | |||
514 | void GetSelectedNames(UStringVector &selectedNames); | 535 | void GetSelectedNames(UStringVector &selectedNames); |
515 | void SaveSelectedState(CSelectedState &s); | 536 | void SaveSelectedState(CSelectedState &s); |
516 | HRESULT RefreshListCtrl(const CSelectedState &s); | 537 | HRESULT RefreshListCtrl(const CSelectedState &s); |
@@ -575,61 +596,44 @@ public: | |||
575 | 596 | ||
576 | CPanel() : | 597 | CPanel() : |
577 | _thereAre_ListView_Items(false), | 598 | _thereAre_ListView_Items(false), |
578 | _exStyle(0), | 599 | // _virtualMode(false), |
579 | _showDots(false), | ||
580 | _showRealFileIcons(false), | ||
581 | // _virtualMode(flase), | ||
582 | _enableItemChangeNotify(true), | 600 | _enableItemChangeNotify(true), |
583 | _mySelectMode(false), | ||
584 | _timestampLevel(kTimestampPrintLevel_MIN), | ||
585 | |||
586 | _thereAreDeletedItems(false), | 601 | _thereAreDeletedItems(false), |
587 | _markDeletedItems(true), | 602 | _markDeletedItems(true), |
588 | PanelCreated(false), | 603 | _dontShowMode(false), |
589 | 604 | _needSaveInfo(false), | |
590 | _listViewMode(3), | ||
591 | _xSize(300), | ||
592 | 605 | ||
606 | PanelCreated(false), | ||
607 | _mySelectMode(false), | ||
608 | _showDots(false), | ||
609 | _showRealFileIcons(false), | ||
593 | _flatMode(false), | 610 | _flatMode(false), |
594 | _flatModeForDisk(false), | ||
595 | _flatModeForArc(false), | 611 | _flatModeForArc(false), |
596 | 612 | _flatModeForDisk(false), | |
613 | _selectionIsDefined(false), | ||
597 | // _showNtfsStrems_Mode(false), | 614 | // _showNtfsStrems_Mode(false), |
598 | // _showNtfsStrems_ModeForDisk(false), | 615 | // _showNtfsStrems_ModeForDisk(false), |
599 | // _showNtfsStrems_ModeForArc(false), | 616 | // _showNtfsStrems_ModeForArc(false), |
600 | 617 | ||
601 | _dontShowMode(false), | 618 | _exStyle(0), |
602 | 619 | _timestampLevel(kTimestampPrintLevel_MIN), | |
603 | m_DropHighlighted_SelectionIndex(-1), | 620 | _listViewMode(3), |
604 | 621 | _xSize(300), | |
605 | _needSaveInfo(false), | ||
606 | _startGroupSelect(0), | 622 | _startGroupSelect(0), |
607 | _selectionIsDefined(false) | 623 | m_DropHighlighted_SelectionIndex(-1) |
608 | {} | 624 | {} |
609 | 625 | ||
626 | ~CPanel() Z7_DESTRUCTOR_override; | ||
627 | |||
628 | void ReleasePanel(); | ||
629 | |||
610 | void SetExtendedStyle() | 630 | void SetExtendedStyle() |
611 | { | 631 | { |
612 | if (_listView) | 632 | if (_listView) |
613 | _listView.SetExtendedListViewStyle(_exStyle); | 633 | _listView.SetExtendedListViewStyle(_exStyle); |
614 | } | 634 | } |
615 | 635 | ||
616 | |||
617 | bool _needSaveInfo; | ||
618 | UString _typeIDString; | ||
619 | CListViewInfo _listViewInfo; | ||
620 | |||
621 | CPropColumns _columns; | ||
622 | CPropColumns _visibleColumns; | ||
623 | |||
624 | PROPID _sortID; | ||
625 | // int _sortIndex; | ||
626 | bool _ascending; | ||
627 | Int32 _isRawSortProp; | ||
628 | |||
629 | void SetSortRawStatus(); | 636 | void SetSortRawStatus(); |
630 | |||
631 | void Release(); | ||
632 | ~CPanel() Z7_DESTRUCTOR_override; | ||
633 | void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate); | 637 | void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate); |
634 | bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result); | 638 | bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result); |
635 | void ShowColumnsContextMenu(int x, int y); | 639 | void ShowColumnsContextMenu(int x, int y); |
@@ -638,9 +642,6 @@ public: | |||
638 | void OnReload(bool onTimer = false); | 642 | void OnReload(bool onTimer = false); |
639 | bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos); | 643 | bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos); |
640 | 644 | ||
641 | CMyComPtr<IContextMenu> _sevenZipContextMenu; | ||
642 | CMyComPtr<IContextMenu> _systemContextMenu; | ||
643 | |||
644 | HRESULT CreateShellContextMenu( | 645 | HRESULT CreateShellContextMenu( |
645 | const CRecordVector<UInt32> &operatedIndices, | 646 | const CRecordVector<UInt32> &operatedIndices, |
646 | CMyComPtr<IContextMenu> &systemContextMenu); | 647 | CMyComPtr<IContextMenu> &systemContextMenu); |
@@ -672,12 +673,6 @@ public: | |||
672 | void EditCopy(); | 673 | void EditCopy(); |
673 | void EditPaste(); | 674 | void EditPaste(); |
674 | 675 | ||
675 | int _startGroupSelect; | ||
676 | |||
677 | bool _selectionIsDefined; | ||
678 | bool _selectMark; | ||
679 | int _prevFocusedItem; | ||
680 | |||
681 | 676 | ||
682 | // void SortItems(int index); | 677 | // void SortItems(int index); |
683 | void SortItemsWithPropID(PROPID propID); | 678 | void SortItemsWithPropID(PROPID propID); |
@@ -716,8 +711,8 @@ public: | |||
716 | } | 711 | } |
717 | 712 | ||
718 | // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } | 713 | // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } |
719 | bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; } | 714 | bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix.IsEqualTo("\\\\.\\"); } |
720 | bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; } | 715 | bool IsSuperDrivesPrefix() const { return _currentFolderPrefix.IsEqualTo("\\\\?\\"); } |
721 | 716 | ||
722 | /* | 717 | /* |
723 | c:\Dir | 718 | c:\Dir |
@@ -751,9 +746,12 @@ public: | |||
751 | bool IsThereReadOnlyFolder() const; | 746 | bool IsThereReadOnlyFolder() const; |
752 | bool CheckBeforeUpdate(UINT resourceID); | 747 | bool CheckBeforeUpdate(UINT resourceID); |
753 | 748 | ||
754 | bool _processTimer; | 749 | void Disable_Processing_Timer_Notify_StatusBar() |
755 | bool _processNotify; | 750 | { |
756 | bool _processStatusBar; | 751 | _processTimer = false; |
752 | _processNotify = false; | ||
753 | _processStatusBar = false; | ||
754 | } | ||
757 | 755 | ||
758 | class CDisableTimerProcessing | 756 | class CDisableTimerProcessing |
759 | { | 757 | { |
@@ -926,6 +924,7 @@ public: | |||
926 | void ExtractArchives(); | 924 | void ExtractArchives(); |
927 | void TestArchives(); | 925 | void TestArchives(); |
928 | 926 | ||
927 | void Get_ZoneId_Stream_from_ParentFolders(CByteBuffer &buf); | ||
929 | 928 | ||
930 | HRESULT CopyTo(CCopyToOptions &options, | 929 | HRESULT CopyTo(CCopyToOptions &options, |
931 | const CRecordVector<UInt32> &indices, | 930 | const CRecordVector<UInt32> &indices, |
@@ -939,7 +938,7 @@ public: | |||
939 | { | 938 | { |
940 | bool usePassword = false; | 939 | bool usePassword = false; |
941 | UString password; | 940 | UString password; |
942 | if (_parentFolders.Size() > 0) | 941 | if (!_parentFolders.IsEmpty()) |
943 | { | 942 | { |
944 | const CFolderLink &fl = _parentFolders.Back(); | 943 | const CFolderLink &fl = _parentFolders.Back(); |
945 | usePassword = fl.UsePassword; | 944 | usePassword = fl.UsePassword; |
@@ -978,6 +977,7 @@ public: | |||
978 | UString GetItemsInfoString(const CRecordVector<UInt32> &indices); | 977 | UString GetItemsInfoString(const CRecordVector<UInt32> &indices); |
979 | }; | 978 | }; |
980 | 979 | ||
980 | |||
981 | class CMyBuffer | 981 | class CMyBuffer |
982 | { | 982 | { |
983 | void *_data; | 983 | void *_data; |
@@ -994,13 +994,12 @@ public: | |||
994 | ~CMyBuffer() { ::MidFree(_data); } | 994 | ~CMyBuffer() { ::MidFree(_data); } |
995 | }; | 995 | }; |
996 | 996 | ||
997 | class CExitEventLauncher | 997 | struct CExitEventLauncher |
998 | { | 998 | { |
999 | public: | ||
1000 | NWindows::NSynchronization::CManualResetEvent _exitEvent; | 999 | NWindows::NSynchronization::CManualResetEvent _exitEvent; |
1001 | bool _needExit; | 1000 | bool _needExit; |
1002 | CRecordVector< ::CThread > _threads; | ||
1003 | unsigned _numActiveThreads; | 1001 | unsigned _numActiveThreads; |
1002 | CRecordVector< ::CThread > _threads; | ||
1004 | 1003 | ||
1005 | CExitEventLauncher() | 1004 | CExitEventLauncher() |
1006 | { | 1005 | { |
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index 36a0f6d..f070be9 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp | |||
@@ -75,11 +75,21 @@ HRESULT CPanelCopyThread::ProcessVirt() | |||
75 | 75 | ||
76 | if (FolderOperations) | 76 | if (FolderOperations) |
77 | { | 77 | { |
78 | CMyComPtr<IFolderSetZoneIdMode> setZoneMode; | ||
79 | FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode); | ||
80 | if (setZoneMode) | ||
81 | { | 78 | { |
82 | RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode)) | 79 | CMyComPtr<IFolderSetZoneIdMode> setZoneMode; |
80 | FolderOperations.QueryInterface(IID_IFolderSetZoneIdMode, &setZoneMode); | ||
81 | if (setZoneMode) | ||
82 | { | ||
83 | RINOK(setZoneMode->SetZoneIdMode(options->ZoneIdMode)) | ||
84 | } | ||
85 | } | ||
86 | { | ||
87 | CMyComPtr<IFolderSetZoneIdFile> setZoneFile; | ||
88 | FolderOperations.QueryInterface(IID_IFolderSetZoneIdFile, &setZoneFile); | ||
89 | if (setZoneFile) | ||
90 | { | ||
91 | RINOK(setZoneFile->SetZoneIdFile(options->ZoneBuf, (UInt32)options->ZoneBuf.Size())) | ||
92 | } | ||
83 | } | 93 | } |
84 | } | 94 | } |
85 | 95 | ||
@@ -143,6 +153,32 @@ static void ThrowException_if_Error(HRESULT res) | |||
143 | #endif | 153 | #endif |
144 | */ | 154 | */ |
145 | 155 | ||
156 | void CPanel::Get_ZoneId_Stream_from_ParentFolders(CByteBuffer &buf) | ||
157 | { | ||
158 | // we suppose that ZoneId of top parent has priority over ZoneId from childs. | ||
159 | FOR_VECTOR (i, _parentFolders) | ||
160 | { | ||
161 | // _parentFolders[0] = is top level archive | ||
162 | // _parentFolders[1 ... ].isVirtual == true is possible | ||
163 | // if extracted size meets size conditions derived from g_RAM_Size. | ||
164 | const CFolderLink &fl = _parentFolders[i]; | ||
165 | if (fl.IsVirtual) | ||
166 | { | ||
167 | if (fl.ZoneBuf.Size() != 0) | ||
168 | { | ||
169 | buf = fl.ZoneBuf; | ||
170 | return; | ||
171 | } | ||
172 | } | ||
173 | else if (!fl.FilePath.IsEmpty()) | ||
174 | { | ||
175 | ReadZoneFile_Of_BaseFile(fl.FilePath, buf); | ||
176 | if (buf.Size() != 0) | ||
177 | return; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
146 | HRESULT CPanel::CopyTo(CCopyToOptions &options, | 182 | HRESULT CPanel::CopyTo(CCopyToOptions &options, |
147 | const CRecordVector<UInt32> &indices, | 183 | const CRecordVector<UInt32> &indices, |
148 | UStringVector *messages, | 184 | UStringVector *messages, |
@@ -157,6 +193,10 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, | |||
157 | options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone; | 193 | options.ZoneIdMode = (NExtract::NZoneIdMode::EEnum)(int)(Int32)ci.WriteZone; |
158 | } | 194 | } |
159 | 195 | ||
196 | if (options.ZoneBuf.Size() == 0 | ||
197 | && options.ZoneIdMode != NExtract::NZoneIdMode::kNone) | ||
198 | Get_ZoneId_Stream_from_ParentFolders(options.ZoneBuf); | ||
199 | |||
160 | if (IsHashFolder()) | 200 | if (IsHashFolder()) |
161 | { | 201 | { |
162 | if (!options.testMode) | 202 | if (!options.testMode) |
@@ -205,9 +245,9 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, | |||
205 | extracter.Hash.MainName = extracter.Hash.FirstFileName; | 245 | extracter.Hash.MainName = extracter.Hash.FirstFileName; |
206 | } | 246 | } |
207 | 247 | ||
208 | if (options.VirtFileSystem) | 248 | if (options.VirtFileSystemSpec) |
209 | { | 249 | { |
210 | extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystem; | 250 | extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystemSpec; |
211 | extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec; | 251 | extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec; |
212 | } | 252 | } |
213 | extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams; | 253 | extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams; |
@@ -244,7 +284,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, | |||
244 | if (options.hashMethods.Size() == 1) | 284 | if (options.hashMethods.Size() == 1) |
245 | { | 285 | { |
246 | const UString &s = options.hashMethods[0]; | 286 | const UString &s = options.hashMethods[0]; |
247 | if (s != L"*") | 287 | if (!s.IsEqualTo("*")) |
248 | title = s; | 288 | title = s; |
249 | } | 289 | } |
250 | } | 290 | } |
diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 040444c..f9b0a6c 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp | |||
@@ -2614,11 +2614,11 @@ Z7_COMWF_B CDropTarget::Drop(IDataObject *dataObject, DWORD keyState, | |||
2614 | UString s = LangString(cmdEffect == DROPEFFECT_MOVE ? | 2614 | UString s = LangString(cmdEffect == DROPEFFECT_MOVE ? |
2615 | IDS_MOVE_TO : IDS_COPY_TO); | 2615 | IDS_MOVE_TO : IDS_COPY_TO); |
2616 | s.Add_LF(); | 2616 | s.Add_LF(); |
2617 | s += "\'"; | 2617 | // s += "\'"; |
2618 | s += m_Panel->_currentFolderPrefix; | 2618 | s += m_Panel->_currentFolderPrefix; |
2619 | s += "\'"; | 2619 | // s += "\'"; |
2620 | s.Add_LF(); | 2620 | s.Add_LF(); |
2621 | s += LangString(IDS_WANT_TO_COPY_FILES); | 2621 | AddLangString(s, IDS_WANT_TO_COPY_FILES); |
2622 | s += " ?"; | 2622 | s += " ?"; |
2623 | const int res = ::MessageBoxW(*m_Panel, s, title, MB_YESNOCANCEL | MB_ICONQUESTION); | 2623 | const int res = ::MessageBoxW(*m_Panel, s, title, MB_YESNOCANCEL | MB_ICONQUESTION); |
2624 | if (res != IDYES) | 2624 | if (res != IDYES) |
@@ -2954,7 +2954,7 @@ static unsigned Drag_OnContextMenu(int xPos, int yPos, UInt32 cmdFlags) | |||
2954 | name = MyFormatNew(name, destPath); | 2954 | name = MyFormatNew(name, destPath); |
2955 | */ | 2955 | */ |
2956 | name.Add_Space(); | 2956 | name.Add_Space(); |
2957 | name += LangString(IDS_CONTEXT_ARCHIVE); | 2957 | AddLangString(name, IDS_CONTEXT_ARCHIVE); |
2958 | } | 2958 | } |
2959 | if (cmdId == NDragMenu::k_Cancel) | 2959 | if (cmdId == NDragMenu::k_Cancel) |
2960 | menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL); | 2960 | menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL); |
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index c34cb74..b0fb53e 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp | |||
@@ -428,7 +428,7 @@ void CPanel::LoadFullPathAndShow() | |||
428 | UString name_Computer = RootFolder_GetName_Computer(iconIndex); | 428 | UString name_Computer = RootFolder_GetName_Computer(iconIndex); |
429 | name_Computer.Add_PathSepar(); | 429 | name_Computer.Add_PathSepar(); |
430 | if (path == name_Computer | 430 | if (path == name_Computer |
431 | || path == L"\\\\?\\") | 431 | || path.IsEqualTo("\\\\?\\")) |
432 | item.iImage = iconIndex; | 432 | item.iImage = iconIndex; |
433 | else | 433 | else |
434 | { | 434 | { |
@@ -639,7 +639,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) | |||
639 | unsigned indent = 0; | 639 | unsigned indent = 0; |
640 | { | 640 | { |
641 | UString path = _currentFolderPrefix; | 641 | UString path = _currentFolderPrefix; |
642 | // path = L"\\\\.\\y:\\"; // for debug | 642 | // path = "\\\\.\\y:\\"; // for debug |
643 | UString prefix0; | 643 | UString prefix0; |
644 | if (path.IsPrefixedBy_Ascii_NoCase("\\\\")) | 644 | if (path.IsPrefixedBy_Ascii_NoCase("\\\\")) |
645 | { | 645 | { |
@@ -702,7 +702,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) | |||
702 | int iconIndex_Computer; | 702 | int iconIndex_Computer; |
703 | const UString name_Computer = RootFolder_GetName_Computer(iconIndex_Computer); | 703 | const UString name_Computer = RootFolder_GetName_Computer(iconIndex_Computer); |
704 | 704 | ||
705 | // const bool is_devicePrefix = (sumPath == L"\\\\.\\"); | 705 | // const bool is_devicePrefix = (sumPath.IsEqualTo("\\\\.\\")); |
706 | 706 | ||
707 | if (pathParts.Size() > 1) | 707 | if (pathParts.Size() > 1) |
708 | if (!sumPath.IsEmpty() | 708 | if (!sumPath.IsEmpty() |
@@ -901,8 +901,8 @@ UString CPanel::GetParentDirPrefix() const | |||
901 | { | 901 | { |
902 | s = _currentFolderPrefix; | 902 | s = _currentFolderPrefix; |
903 | s.DeleteBack(); | 903 | s.DeleteBack(); |
904 | if (s != L"\\\\." && | 904 | if (!s.IsEqualTo("\\\\.") && |
905 | s != L"\\\\?") | 905 | !s.IsEqualTo("\\\\?")) |
906 | { | 906 | { |
907 | int pos = s.ReverseFind_PathSepar(); | 907 | int pos = s.ReverseFind_PathSepar(); |
908 | if (pos >= 0) | 908 | if (pos >= 0) |
@@ -935,8 +935,8 @@ void CPanel::OpenParentFolder() | |||
935 | } | 935 | } |
936 | else | 936 | else |
937 | */ | 937 | */ |
938 | if (focusedName != L"\\\\." && | 938 | if (!focusedName.IsEqualTo("\\\\.") && |
939 | focusedName != L"\\\\?") | 939 | !focusedName.IsEqualTo("\\\\?")) |
940 | { | 940 | { |
941 | const int pos = focusedName.ReverseFind_PathSepar(); | 941 | const int pos = focusedName.ReverseFind_PathSepar(); |
942 | if (pos >= 0) | 942 | if (pos >= 0) |
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index 244a962..aa56ef5 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp | |||
@@ -39,7 +39,7 @@ using namespace NFile; | |||
39 | using namespace NDir; | 39 | using namespace NDir; |
40 | 40 | ||
41 | extern bool g_RAM_Size_Defined; | 41 | extern bool g_RAM_Size_Defined; |
42 | extern UInt64 g_RAM_Size; | 42 | extern size_t g_RAM_Size; |
43 | 43 | ||
44 | #ifndef _UNICODE | 44 | #ifndef _UNICODE |
45 | extern bool g_IsNT; | 45 | extern bool g_IsNT; |
@@ -606,9 +606,9 @@ HRESULT CPanel::OpenParentArchiveFolder() | |||
606 | NFind::CFileInfo newFileInfo; | 606 | NFind::CFileInfo newFileInfo; |
607 | if (newFileInfo.Find(folderLink.FilePath)) | 607 | if (newFileInfo.Find(folderLink.FilePath)) |
608 | { | 608 | { |
609 | if (folderLink.WasChanged(newFileInfo)) | 609 | if (folderLink.WasChanged_from_FolderLink(newFileInfo)) |
610 | { | 610 | { |
611 | UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, folderLink.RelPath); | 611 | const UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, folderLink.RelPath); |
612 | if (::MessageBoxW((HWND)*this, message, L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) == IDYES) | 612 | if (::MessageBoxW((HWND)*this, message, L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) == IDYES) |
613 | { | 613 | { |
614 | if (OnOpenItemChanged(folderLink.FileIndex, fs2us(folderLink.FilePath), | 614 | if (OnOpenItemChanged(folderLink.FileIndex, fs2us(folderLink.FilePath), |
@@ -1083,13 +1083,11 @@ void CExitEventLauncher::Exit(bool hardExit) | |||
1083 | FOR_VECTOR (i, _threads) | 1083 | FOR_VECTOR (i, _threads) |
1084 | { | 1084 | { |
1085 | ::CThread &th = _threads[i]; | 1085 | ::CThread &th = _threads[i]; |
1086 | DWORD wait = (hardExit ? 100 : INFINITE); | ||
1087 | if (Thread_WasCreated(&th)) | 1086 | if (Thread_WasCreated(&th)) |
1088 | { | 1087 | { |
1089 | DWORD waitResult = WaitForSingleObject(th, wait); | 1088 | const DWORD waitResult = WaitForSingleObject(th, hardExit ? 100 : INFINITE); |
1090 | // Thread_Wait(&th); | 1089 | // Thread_Wait(&th); |
1091 | if (waitResult == WAIT_TIMEOUT) | 1090 | // if (waitResult == WAIT_TIMEOUT) wait = 1; |
1092 | wait = 1; | ||
1093 | if (!hardExit && waitResult != WAIT_OBJECT_0) | 1091 | if (!hardExit && waitResult != WAIT_OBJECT_0) |
1094 | continue; | 1092 | continue; |
1095 | Thread_Close(&th); | 1093 | Thread_Close(&th); |
@@ -1107,7 +1105,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) | |||
1107 | CMyUniquePtr<CTmpProcessInfo> tpi((CTmpProcessInfo *)param); | 1105 | CMyUniquePtr<CTmpProcessInfo> tpi((CTmpProcessInfo *)param); |
1108 | CChildProcesses &processes = tpi->Processes; | 1106 | CChildProcesses &processes = tpi->Processes; |
1109 | 1107 | ||
1110 | bool mainProcessWasSet = !processes.Handles.IsEmpty(); | 1108 | const bool mainProcessWasSet = !processes.Handles.IsEmpty(); |
1111 | 1109 | ||
1112 | bool isComplexMode = true; | 1110 | bool isComplexMode = true; |
1113 | 1111 | ||
@@ -1195,7 +1193,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) | |||
1195 | { | 1193 | { |
1196 | NFind::CFileInfo newFileInfo; | 1194 | NFind::CFileInfo newFileInfo; |
1197 | if (newFileInfo.Find(tpi->FilePath)) | 1195 | if (newFileInfo.Find(tpi->FilePath)) |
1198 | if (tpi->WasChanged(newFileInfo)) | 1196 | if (tpi->WasChanged_from_TempFileInfo(newFileInfo)) |
1199 | needFindProcessByPath = false; | 1197 | needFindProcessByPath = false; |
1200 | } | 1198 | } |
1201 | 1199 | ||
@@ -1235,7 +1233,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) | |||
1235 | 1233 | ||
1236 | if (mainProcessWasSet) | 1234 | if (mainProcessWasSet) |
1237 | { | 1235 | { |
1238 | if (tpi->WasChanged(newFileInfo)) | 1236 | if (tpi->WasChanged_from_TempFileInfo(newFileInfo)) |
1239 | { | 1237 | { |
1240 | UString m = MyFormatNew(IDS_CANNOT_UPDATE_FILE, fs2us(tpi->FilePath)); | 1238 | UString m = MyFormatNew(IDS_CANNOT_UPDATE_FILE, fs2us(tpi->FilePath)); |
1241 | if (tpi->ReadOnly) | 1239 | if (tpi->ReadOnly) |
@@ -1279,10 +1277,10 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) | |||
1279 | 1277 | ||
1280 | { | 1278 | { |
1281 | NFind::CFileInfo newFileInfo; | 1279 | NFind::CFileInfo newFileInfo; |
1282 | 1280 | const bool finded = newFileInfo.Find(tpi->FilePath); | |
1283 | bool finded = newFileInfo.Find(tpi->FilePath); | 1281 | if (!needCheckTimestamp |
1284 | 1282 | || !finded | |
1285 | if (!needCheckTimestamp || !finded || !tpi->WasChanged(newFileInfo)) | 1283 | || !tpi->WasChanged_from_TempFileInfo(newFileInfo)) |
1286 | { | 1284 | { |
1287 | DEBUG_PRINT("Delete Temp file"); | 1285 | DEBUG_PRINT("Delete Temp file"); |
1288 | tpi->DeleteDirAndFile(); | 1286 | tpi->DeleteDirAndFile(); |
@@ -1534,7 +1532,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1534 | 1532 | ||
1535 | bool usePassword = false; | 1533 | bool usePassword = false; |
1536 | UString password; | 1534 | UString password; |
1537 | if (_parentFolders.Size() > 0) | 1535 | if (!_parentFolders.IsEmpty()) |
1538 | { | 1536 | { |
1539 | const CFolderLink &fl = _parentFolders.Back(); | 1537 | const CFolderLink &fl = _parentFolders.Back(); |
1540 | usePassword = fl.UsePassword; | 1538 | usePassword = fl.UsePassword; |
@@ -1547,7 +1545,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1547 | #ifndef _UNICODE | 1545 | #ifndef _UNICODE |
1548 | if (g_IsNT) | 1546 | if (g_IsNT) |
1549 | #endif | 1547 | #endif |
1550 | if (_parentFolders.Size() > 0) | 1548 | if (!_parentFolders.IsEmpty()) |
1551 | { | 1549 | { |
1552 | const CFolderLink &fl = _parentFolders.Front(); | 1550 | const CFolderLink &fl = _parentFolders.Front(); |
1553 | if (!fl.IsVirtual && !fl.FilePath.IsEmpty()) | 1551 | if (!fl.IsVirtual && !fl.FilePath.IsEmpty()) |
@@ -1576,39 +1574,42 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1576 | 1574 | ||
1577 | if (tryAsArchive) | 1575 | if (tryAsArchive) |
1578 | { | 1576 | { |
1577 | // actually we want to get sum: size of main file plus sizes of altStreams. | ||
1578 | // but now there is no interface to get altStreams sizes. | ||
1579 | NCOM::CPropVariant prop; | 1579 | NCOM::CPropVariant prop; |
1580 | _folder->GetProperty(index, kpidSize, &prop); | 1580 | _folder->GetProperty(index, kpidSize, &prop); |
1581 | UInt64 fileLimit = 1 << 22; | 1581 | const size_t fileLimit = g_RAM_Size_Defined ? |
1582 | if (g_RAM_Size_Defined) | 1582 | g_RAM_Size >> MyMax(_parentFolders.Size() + 1, 8u): |
1583 | fileLimit = g_RAM_Size / 4; | 1583 | 1u << 22; |
1584 | |||
1585 | UInt64 fileSize = 0; | 1584 | UInt64 fileSize = 0; |
1586 | if (!ConvertPropVariantToUInt64(prop, fileSize)) | 1585 | if (!ConvertPropVariantToUInt64(prop, fileSize)) |
1587 | fileSize = fileLimit; | 1586 | fileSize = fileLimit; |
1588 | if (fileSize <= fileLimit && fileSize > 0) | 1587 | #if 0 // 1 : for debug |
1588 | fileLimit = 1; | ||
1589 | #endif | ||
1590 | |||
1591 | if (fileSize <= fileLimit) | ||
1589 | { | 1592 | { |
1590 | options.streamMode = true; | 1593 | options.streamMode = true; |
1591 | virtFileSystemSpec = new CVirtFileSystem; | 1594 | virtFileSystemSpec = new CVirtFileSystem; |
1592 | virtFileSystem = virtFileSystemSpec; | 1595 | virtFileSystem = virtFileSystemSpec; |
1596 | virtFileSystemSpec->FileName = name; | ||
1597 | virtFileSystemSpec->IsAltStreamFile = isAltStream; | ||
1593 | 1598 | ||
1594 | #if defined(_WIN32) && !defined(UNDER_CE) | 1599 | #if defined(_WIN32) && !defined(UNDER_CE) |
1595 | #ifndef _UNICODE | 1600 | #ifndef _UNICODE |
1596 | if (g_IsNT) | 1601 | if (g_IsNT) |
1597 | #endif | 1602 | #endif |
1598 | if (_parentFolders.Size() > 0) | ||
1599 | { | 1603 | { |
1600 | const CFolderLink &fl = _parentFolders.Front(); | 1604 | Get_ZoneId_Stream_from_ParentFolders(virtFileSystemSpec->ZoneBuf); |
1601 | if (!fl.IsVirtual && !fl.FilePath.IsEmpty()) | 1605 | options.ZoneBuf = virtFileSystemSpec->ZoneBuf; |
1602 | ReadZoneFile_Of_BaseFile(fl.FilePath, virtFileSystemSpec->ZoneBuf); | ||
1603 | } | 1606 | } |
1604 | #endif | 1607 | #endif |
1605 | 1608 | ||
1606 | // we allow additional total size for small alt streams; | 1609 | virtFileSystemSpec->MaxTotalAllocSize = (size_t)fileSize |
1607 | virtFileSystemSpec->MaxTotalAllocSize = fileSize + (1 << 10); | 1610 | + (1 << 16); // we allow additional total size for small alt streams. |
1608 | |||
1609 | virtFileSystemSpec->DirPrefix = tempDirNorm; | 1611 | virtFileSystemSpec->DirPrefix = tempDirNorm; |
1610 | virtFileSystemSpec->Init(); | 1612 | // options.VirtFileSystem = virtFileSystem; |
1611 | options.VirtFileSystem = virtFileSystem; | ||
1612 | options.VirtFileSystemSpec = virtFileSystemSpec; | 1613 | options.VirtFileSystemSpec = virtFileSystemSpec; |
1613 | } | 1614 | } |
1614 | } | 1615 | } |
@@ -1618,7 +1619,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1618 | 1619 | ||
1619 | const HRESULT result = CopyTo(options, indices, &messages, usePassword, password); | 1620 | const HRESULT result = CopyTo(options, indices, &messages, usePassword, password); |
1620 | 1621 | ||
1621 | if (_parentFolders.Size() > 0) | 1622 | if (!_parentFolders.IsEmpty()) |
1622 | { | 1623 | { |
1623 | CFolderLink &fl = _parentFolders.Back(); | 1624 | CFolderLink &fl = _parentFolders.Back(); |
1624 | fl.UsePassword = usePassword; | 1625 | fl.UsePassword = usePassword; |
@@ -1634,34 +1635,46 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1634 | return; | 1635 | return; |
1635 | } | 1636 | } |
1636 | 1637 | ||
1637 | if (options.VirtFileSystem) | 1638 | if (virtFileSystemSpec && !virtFileSystemSpec->WasStreamFlushedToFS()) |
1638 | { | 1639 | { |
1639 | if (virtFileSystemSpec->IsStreamInMem()) | 1640 | int index_in_Files = virtFileSystemSpec->Index_of_MainExtractedFile_in_Files; |
1641 | if (index_in_Files < 0) | ||
1640 | { | 1642 | { |
1641 | const CVirtFile &file = virtFileSystemSpec->Files[0]; | 1643 | if (virtFileSystemSpec->Files.Size() != 1) |
1642 | 1644 | { | |
1643 | size_t streamSize = (size_t)file.Size; | 1645 | MessageBox_Error_HRESULT(E_FAIL); |
1644 | CBufInStream *bufInStreamSpec = new CBufInStream; | 1646 | return; |
1645 | CMyComPtr<IInStream> bufInStream = bufInStreamSpec; | 1647 | } |
1646 | bufInStreamSpec->Init(file.Data, streamSize, virtFileSystem); | 1648 | // it's not expected case that index was not set, but we support that case |
1647 | 1649 | index_in_Files = 0; | |
1648 | HRESULT res = OpenAsArc_Msg(bufInStream, tempFileInfo, fullVirtPath, type ? type : L"" | 1650 | } |
1651 | { | ||
1652 | const CVirtFile &file = virtFileSystemSpec->Files[index_in_Files]; | ||
1653 | CMyComPtr2_Create<IInStream, CBufInStream> bufInStream; | ||
1654 | bufInStream->Init(file.Data, file.WrittenSize, virtFileSystem); | ||
1655 | const HRESULT res = OpenAsArc_Msg(bufInStream, tempFileInfo, | ||
1656 | fullVirtPath, type ? type : L"" | ||
1649 | // , encrypted | 1657 | // , encrypted |
1650 | // , true // showErrorMessage | 1658 | // , true // showErrorMessage |
1651 | ); | 1659 | ); |
1652 | |||
1653 | if (res == S_OK) | 1660 | if (res == S_OK) |
1654 | { | 1661 | { |
1662 | if (virtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files >= 0 | ||
1663 | && !_parentFolders.IsEmpty()) | ||
1664 | { | ||
1665 | const CVirtFile &fileZone = virtFileSystemSpec->Files[ | ||
1666 | virtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files]; | ||
1667 | _parentFolders.Back().ZoneBuf.CopyFrom(fileZone.Data, fileZone.WrittenSize); | ||
1668 | } | ||
1669 | |||
1655 | tempDirectory.DisableDeleting(); | 1670 | tempDirectory.DisableDeleting(); |
1656 | RefreshListCtrl(); | 1671 | RefreshListCtrl(); |
1657 | return; | 1672 | return; |
1658 | } | 1673 | } |
1659 | |||
1660 | if (res == E_ABORT || res != S_FALSE) | 1674 | if (res == E_ABORT || res != S_FALSE) |
1661 | return; | 1675 | return; |
1662 | if (!tryExternal) | 1676 | if (!tryExternal) |
1663 | return; | 1677 | return; |
1664 | |||
1665 | tryAsArchive = false; | 1678 | tryAsArchive = false; |
1666 | if (virtFileSystemSpec->FlushToDisk(true) != S_OK) | 1679 | if (virtFileSystemSpec->FlushToDisk(true) != S_OK) |
1667 | return; | 1680 | return; |
@@ -1684,7 +1697,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1684 | 1697 | ||
1685 | if (tryAsArchive) | 1698 | if (tryAsArchive) |
1686 | { | 1699 | { |
1687 | HRESULT res = OpenAsArc_Msg(NULL, tempFileInfo, fullVirtPath, type ? type : L"" | 1700 | const HRESULT res = OpenAsArc_Msg(NULL, tempFileInfo, fullVirtPath, type ? type : L"" |
1688 | // , encrypted | 1701 | // , encrypted |
1689 | // , true // showErrorMessage | 1702 | // , true // showErrorMessage |
1690 | ); | 1703 | ); |
@@ -1732,7 +1745,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
1732 | return; | 1745 | return; |
1733 | } | 1746 | } |
1734 | 1747 | ||
1735 | tpi->Window = (HWND)(*this); | 1748 | tpi->Window = (HWND)*this; |
1736 | tpi->FullPathFolderPrefix = _currentFolderPrefix; | 1749 | tpi->FullPathFolderPrefix = _currentFolderPrefix; |
1737 | tpi->FileIndex = index; | 1750 | tpi->FileIndex = index; |
1738 | tpi->RelPath = relPath; | 1751 | tpi->RelPath = relPath; |
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 544e9bf..868ad22 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp | |||
@@ -1438,13 +1438,16 @@ void CPanel::OnTimer() | |||
1438 | return; | 1438 | return; |
1439 | if (!AutoRefresh_Mode) | 1439 | if (!AutoRefresh_Mode) |
1440 | return; | 1440 | return; |
1441 | CMyComPtr<IFolderWasChanged> folderWasChanged; | 1441 | if (!_folder) // it's unexpected case, but we use it as additional protection. |
1442 | if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK) | ||
1443 | return; | ||
1444 | Int32 wasChanged; | ||
1445 | if (folderWasChanged->WasChanged(&wasChanged) != S_OK) | ||
1446 | return; | ||
1447 | if (wasChanged == 0) | ||
1448 | return; | 1442 | return; |
1443 | { | ||
1444 | CMyComPtr<IFolderWasChanged> folderWasChanged; | ||
1445 | _folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged); | ||
1446 | if (!folderWasChanged) | ||
1447 | return; | ||
1448 | Int32 wasChanged; | ||
1449 | if (folderWasChanged->WasChanged(&wasChanged) != S_OK || wasChanged == 0) | ||
1450 | return; | ||
1451 | } | ||
1449 | OnReload(true); // onTimer | 1452 | OnReload(true); // onTimer |
1450 | } | 1453 | } |
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 4dbd9f6..05ab36b 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp | |||
@@ -785,7 +785,7 @@ void CPanel::Refresh_StatusBar() | |||
785 | wchar_t selectSizeString[32]; | 785 | wchar_t selectSizeString[32]; |
786 | selectSizeString[0] = 0; | 786 | selectSizeString[0] = 0; |
787 | 787 | ||
788 | if (indices.Size() > 0) | 788 | if (!indices.IsEmpty()) |
789 | { | 789 | { |
790 | // for (unsigned ttt = 0; ttt < 1000; ttt++) { | 790 | // for (unsigned ttt = 0; ttt < 1000; ttt++) { |
791 | UInt64 totalSize = 0; | 791 | UInt64 totalSize = 0; |
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index af313ff..427464b 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp | |||
@@ -80,7 +80,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr | |||
80 | 80 | ||
81 | UpdateCallbackSpec->Init(); | 81 | UpdateCallbackSpec->Init(); |
82 | 82 | ||
83 | if (panel._parentFolders.Size() > 0) | 83 | if (!panel._parentFolders.IsEmpty()) |
84 | { | 84 | { |
85 | const CFolderLink &fl = panel._parentFolders.Back(); | 85 | const CFolderLink &fl = panel._parentFolders.Back(); |
86 | UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword; | 86 | UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword; |
@@ -275,8 +275,8 @@ static bool IsCorrectFsName(const UString &name) | |||
275 | { | 275 | { |
276 | const UString lastPart = name.Ptr((unsigned)(name.ReverseFind_PathSepar() + 1)); | 276 | const UString lastPart = name.Ptr((unsigned)(name.ReverseFind_PathSepar() + 1)); |
277 | return | 277 | return |
278 | lastPart != L"." && | 278 | !lastPart.IsEqualTo(".") && |
279 | lastPart != L".."; | 279 | !lastPart.IsEqualTo(".."); |
280 | } | 280 | } |
281 | 281 | ||
282 | bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); | 282 | bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); |
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index 690ebec..a070a0a 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp | |||
@@ -78,8 +78,9 @@ static const UInt32 kLangIDs_Colon[] = | |||
78 | #define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL) | 78 | #define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL) |
79 | 79 | ||
80 | CProgressSync::CProgressSync(): | 80 | CProgressSync::CProgressSync(): |
81 | _stopped(false), _paused(false), | 81 | _stopped(false), |
82 | _bytesProgressMode(true), | 82 | _paused(false), |
83 | _filesProgressMode(false), | ||
83 | _isDir(false), | 84 | _isDir(false), |
84 | _totalBytes(UNDEFINED_VAL), _completedBytes(0), | 85 | _totalBytes(UNDEFINED_VAL), _completedBytes(0), |
85 | _totalFiles(UNDEFINED_VAL), _curFiles(0), | 86 | _totalFiles(UNDEFINED_VAL), _curFiles(0), |
@@ -108,6 +109,13 @@ HRESULT CProgressSync::CheckStop() | |||
108 | } | 109 | } |
109 | } | 110 | } |
110 | 111 | ||
112 | void CProgressSync::Clear_Stop_Status() | ||
113 | { | ||
114 | CRITICAL_LOCK | ||
115 | if (_stopped) | ||
116 | _stopped = false; | ||
117 | } | ||
118 | |||
111 | HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir) | 119 | HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir) |
112 | { | 120 | { |
113 | { | 121 | { |
@@ -242,27 +250,27 @@ void CProgressSync::AddError_Code_Name(HRESULT systemError, const wchar_t *name) | |||
242 | } | 250 | } |
243 | 251 | ||
244 | CProgressDialog::CProgressDialog(): | 252 | CProgressDialog::CProgressDialog(): |
245 | _timer(0), | 253 | _isDir(false), |
246 | CompressingMode(true), | 254 | _wasCreated(false), |
247 | MainWindow(NULL) | 255 | _needClose(false), |
256 | _errorsWereDisplayed(false), | ||
257 | _waitCloseByCancelButton(false), | ||
258 | _cancelWasPressed(false), | ||
259 | _inCancelMessageBox(false), | ||
260 | _externalCloseMessageWasReceived(false), | ||
261 | _background(false), | ||
262 | WaitMode(false), | ||
263 | MessagesDisplayed(false), | ||
264 | CompressingMode(true), | ||
265 | ShowCompressionInfo(true), | ||
266 | _numPostedMessages(0), | ||
267 | _numAutoSizeMessages(0), | ||
268 | _numMessages(0), | ||
269 | _timer(0), | ||
270 | IconID(-1), | ||
271 | MainWindow(NULL) | ||
248 | { | 272 | { |
249 | _isDir = false; | 273 | |
250 | |||
251 | _numMessages = 0; | ||
252 | IconID = -1; | ||
253 | MessagesDisplayed = false; | ||
254 | _wasCreated = false; | ||
255 | _needClose = false; | ||
256 | _inCancelMessageBox = false; | ||
257 | _externalCloseMessageWasReceived = false; | ||
258 | |||
259 | _numPostedMessages = 0; | ||
260 | _numAutoSizeMessages = 0; | ||
261 | _errorsWereDisplayed = false; | ||
262 | _waitCloseByCancelButton = false; | ||
263 | _cancelWasPressed = false; | ||
264 | ShowCompressionInfo = true; | ||
265 | WaitMode = false; | ||
266 | if (_dialogCreatedEvent.Create() != S_OK) | 274 | if (_dialogCreatedEvent.Create() != S_OK) |
267 | throw 1334987; | 275 | throw 1334987; |
268 | if (_createDialogEvent.Create() != S_OK) | 276 | if (_createDialogEvent.Create() != S_OK) |
@@ -357,8 +365,6 @@ bool CProgressDialog::OnInit() | |||
357 | _filesStr_Prev.Empty(); | 365 | _filesStr_Prev.Empty(); |
358 | _filesTotStr_Prev.Empty(); | 366 | _filesTotStr_Prev.Empty(); |
359 | 367 | ||
360 | _foreground = true; | ||
361 | |||
362 | m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); | 368 | m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); |
363 | _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES)); | 369 | _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES)); |
364 | _messageList.SetUnicodeFormat(); | 370 | _messageList.SetUnicodeFormat(); |
@@ -388,9 +394,8 @@ bool CProgressDialog::OnInit() | |||
388 | SetPauseText(); | 394 | SetPauseText(); |
389 | SetPriorityText(); | 395 | SetPriorityText(); |
390 | 396 | ||
391 | _messageList.InsertColumn(0, L"", 30); | 397 | _messageList.InsertColumn(0, L"", 40); |
392 | _messageList.InsertColumn(1, L"", 600); | 398 | _messageList.InsertColumn(1, L"", 460); |
393 | |||
394 | _messageList.SetColumnWidthAuto(0); | 399 | _messageList.SetColumnWidthAuto(0); |
395 | _messageList.SetColumnWidthAuto(1); | 400 | _messageList.SetColumnWidthAuto(1); |
396 | 401 | ||
@@ -690,7 +695,7 @@ static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) | |||
690 | void CProgressDialog::UpdateStatInfo(bool showAll) | 695 | void CProgressDialog::UpdateStatInfo(bool showAll) |
691 | { | 696 | { |
692 | UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; | 697 | UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; |
693 | bool bytesProgressMode; | 698 | bool filesProgressMode; |
694 | 699 | ||
695 | bool titleFileName_Changed; | 700 | bool titleFileName_Changed; |
696 | bool curFilePath_Changed; | 701 | bool curFilePath_Changed; |
@@ -704,7 +709,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll) | |||
704 | completedFiles = Sync._curFiles; | 709 | completedFiles = Sync._curFiles; |
705 | inSize = Sync._inSize; | 710 | inSize = Sync._inSize; |
706 | outSize = Sync._outSize; | 711 | outSize = Sync._outSize; |
707 | bytesProgressMode = Sync._bytesProgressMode; | 712 | filesProgressMode = Sync._filesProgressMode; |
708 | 713 | ||
709 | GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed); | 714 | GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed); |
710 | GetChangedString(Sync._filePath, _filePath, curFilePath_Changed); | 715 | GetChangedString(Sync._filePath, _filePath, curFilePath_Changed); |
@@ -719,8 +724,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll) | |||
719 | 724 | ||
720 | UInt32 curTime = ::GetTickCount(); | 725 | UInt32 curTime = ::GetTickCount(); |
721 | 726 | ||
722 | const UInt64 progressTotal = bytesProgressMode ? total : totalFiles; | 727 | const UInt64 progressTotal = filesProgressMode ? totalFiles : total; |
723 | const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; | 728 | const UInt64 progressCompleted = filesProgressMode ? completedFiles : completed; |
724 | { | 729 | { |
725 | if (IS_UNDEFINED_VAL(progressTotal)) | 730 | if (IS_UNDEFINED_VAL(progressTotal)) |
726 | { | 731 | { |
@@ -900,7 +905,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll) | |||
900 | { | 905 | { |
901 | UString s = _status; | 906 | UString s = _status; |
902 | ReduceString(s, _numReduceSymbols); | 907 | ReduceString(s, _numReduceSymbols); |
903 | SetItemText(IDT_PROGRESS_STATUS, _status); | 908 | SetItemText(IDT_PROGRESS_STATUS, s); |
904 | } | 909 | } |
905 | 910 | ||
906 | if (curFilePath_Changed) | 911 | if (curFilePath_Changed) |
@@ -1086,12 +1091,10 @@ void CProgressDialog::SetTitleText() | |||
1086 | } | 1091 | } |
1087 | if (IS_DEFINED_VAL(_prevPercentValue)) | 1092 | if (IS_DEFINED_VAL(_prevPercentValue)) |
1088 | { | 1093 | { |
1089 | char temp[32]; | 1094 | s.Add_UInt64(_prevPercentValue); |
1090 | ConvertUInt64ToString(_prevPercentValue, temp); | ||
1091 | s += temp; | ||
1092 | s.Add_Char('%'); | 1095 | s.Add_Char('%'); |
1093 | } | 1096 | } |
1094 | if (!_foreground) | 1097 | if (_background) |
1095 | { | 1098 | { |
1096 | s.Add_Space(); | 1099 | s.Add_Space(); |
1097 | s += _backgrounded_String; | 1100 | s += _backgrounded_String; |
@@ -1138,17 +1141,17 @@ void CProgressDialog::OnPauseButton() | |||
1138 | 1141 | ||
1139 | void CProgressDialog::SetPriorityText() | 1142 | void CProgressDialog::SetPriorityText() |
1140 | { | 1143 | { |
1141 | SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ? | 1144 | SetItemText(IDB_PROGRESS_BACKGROUND, _background ? |
1142 | _background_String : | 1145 | _foreground_String : |
1143 | _foreground_String); | 1146 | _background_String); |
1144 | SetTitleText(); | 1147 | SetTitleText(); |
1145 | } | 1148 | } |
1146 | 1149 | ||
1147 | void CProgressDialog::OnPriorityButton() | 1150 | void CProgressDialog::OnPriorityButton() |
1148 | { | 1151 | { |
1149 | _foreground = !_foreground; | 1152 | _background = !_background; |
1150 | #ifndef UNDER_CE | 1153 | #ifndef UNDER_CE |
1151 | SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS); | 1154 | SetPriorityClass(GetCurrentProcess(), _background ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); |
1152 | #endif | 1155 | #endif |
1153 | SetPriorityText(); | 1156 | SetPriorityText(); |
1154 | } | 1157 | } |
@@ -1184,12 +1187,16 @@ void CProgressDialog::AddMessage(LPCWSTR message) | |||
1184 | _numMessages++; | 1187 | _numMessages++; |
1185 | } | 1188 | } |
1186 | 1189 | ||
1187 | static unsigned GetNumDigits(UInt32 val) | 1190 | static unsigned GetNumDigits(unsigned val) |
1188 | { | 1191 | { |
1189 | unsigned i; | 1192 | unsigned i = 0; |
1190 | for (i = 0; val >= 10; i++) | 1193 | for (;;) |
1194 | { | ||
1195 | i++; | ||
1191 | val /= 10; | 1196 | val /= 10; |
1192 | return i; | 1197 | if (val == 0) |
1198 | return i; | ||
1199 | } | ||
1193 | } | 1200 | } |
1194 | 1201 | ||
1195 | void CProgressDialog::UpdateMessagesDialog() | 1202 | void CProgressDialog::UpdateMessagesDialog() |
@@ -1197,7 +1204,7 @@ void CProgressDialog::UpdateMessagesDialog() | |||
1197 | UStringVector messages; | 1204 | UStringVector messages; |
1198 | { | 1205 | { |
1199 | NSynchronization::CCriticalSectionLock lock(Sync._cs); | 1206 | NSynchronization::CCriticalSectionLock lock(Sync._cs); |
1200 | unsigned num = Sync.Messages.Size(); | 1207 | const unsigned num = Sync.Messages.Size(); |
1201 | if (num > _numPostedMessages) | 1208 | if (num > _numPostedMessages) |
1202 | { | 1209 | { |
1203 | messages.ClearAndReserve(num - _numPostedMessages); | 1210 | messages.ClearAndReserve(num - _numPostedMessages); |
@@ -1210,7 +1217,11 @@ void CProgressDialog::UpdateMessagesDialog() | |||
1210 | { | 1217 | { |
1211 | FOR_VECTOR (i, messages) | 1218 | FOR_VECTOR (i, messages) |
1212 | AddMessage(messages[i]); | 1219 | AddMessage(messages[i]); |
1213 | if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages)) | 1220 | // SetColumnWidthAuto() can be slow for big number of files. |
1221 | if (_numPostedMessages < 1000000 || _numAutoSizeMessages < 100) | ||
1222 | if (_numAutoSizeMessages < 100 || | ||
1223 | GetNumDigits(_numPostedMessages) > | ||
1224 | GetNumDigits(_numAutoSizeMessages)) | ||
1214 | { | 1225 | { |
1215 | _messageList.SetColumnWidthAuto(0); | 1226 | _messageList.SetColumnWidthAuto(0); |
1216 | _messageList.SetColumnWidthAuto(1); | 1227 | _messageList.SetColumnWidthAuto(1); |
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index 4ca9be7..60a5ca6 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h | |||
@@ -33,9 +33,8 @@ class CProgressSync | |||
33 | { | 33 | { |
34 | bool _stopped; | 34 | bool _stopped; |
35 | bool _paused; | 35 | bool _paused; |
36 | |||
37 | public: | 36 | public: |
38 | bool _bytesProgressMode; | 37 | bool _filesProgressMode; |
39 | bool _isDir; | 38 | bool _isDir; |
40 | UInt64 _totalBytes; | 39 | UInt64 _totalBytes; |
41 | UInt64 _completedBytes; | 40 | UInt64 _completedBytes; |
@@ -73,13 +72,14 @@ public: | |||
73 | _paused = val; | 72 | _paused = val; |
74 | } | 73 | } |
75 | 74 | ||
76 | void Set_BytesProgressMode(bool bytesProgressMode) | 75 | void Set_FilesProgressMode(bool filesProgressMode) |
77 | { | 76 | { |
78 | NWindows::NSynchronization::CCriticalSectionLock lock(_cs); | 77 | NWindows::NSynchronization::CCriticalSectionLock lock(_cs); |
79 | _bytesProgressMode = bytesProgressMode; | 78 | _filesProgressMode = filesProgressMode; |
80 | } | 79 | } |
81 | 80 | ||
82 | HRESULT CheckStop(); | 81 | HRESULT CheckStop(); |
82 | void Clear_Stop_Status(); | ||
83 | HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); | 83 | HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); |
84 | 84 | ||
85 | HRESULT Set_NumFilesTotal(UInt64 val); | 85 | HRESULT Set_NumFilesTotal(UInt64 val); |
@@ -102,12 +102,32 @@ public: | |||
102 | bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } | 102 | bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } |
103 | }; | 103 | }; |
104 | 104 | ||
105 | |||
105 | class CProgressDialog: public NWindows::NControl::CModalDialog | 106 | class CProgressDialog: public NWindows::NControl::CModalDialog |
106 | { | 107 | { |
108 | bool _isDir; | ||
109 | bool _wasCreated; | ||
110 | bool _needClose; | ||
111 | bool _errorsWereDisplayed; | ||
112 | bool _waitCloseByCancelButton; | ||
113 | bool _cancelWasPressed; | ||
114 | bool _inCancelMessageBox; | ||
115 | bool _externalCloseMessageWasReceived; | ||
116 | bool _background; | ||
117 | public: | ||
118 | bool WaitMode; | ||
119 | bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. | ||
120 | bool CompressingMode; | ||
121 | bool ShowCompressionInfo; | ||
122 | |||
123 | private: | ||
124 | unsigned _numPostedMessages; | ||
125 | unsigned _numAutoSizeMessages; | ||
126 | unsigned _numMessages; | ||
127 | |||
107 | UString _titleFileName; | 128 | UString _titleFileName; |
108 | UString _filePath; | 129 | UString _filePath; |
109 | UString _status; | 130 | UString _status; |
110 | bool _isDir; | ||
111 | 131 | ||
112 | UString _background_String; | 132 | UString _background_String; |
113 | UString _backgrounded_String; | 133 | UString _backgrounded_String; |
@@ -152,7 +172,6 @@ class CProgressDialog: public NWindows::NControl::CModalDialog | |||
152 | NWindows::NControl::CProgressBar m_ProgressBar; | 172 | NWindows::NControl::CProgressBar m_ProgressBar; |
153 | NWindows::NControl::CListView _messageList; | 173 | NWindows::NControl::CListView _messageList; |
154 | 174 | ||
155 | unsigned _numMessages; | ||
156 | UStringVector _messageStrings; | 175 | UStringVector _messageStrings; |
157 | 176 | ||
158 | // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ | 177 | // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ |
@@ -175,28 +194,10 @@ class CProgressDialog: public NWindows::NControl::CModalDialog | |||
175 | UString _filesStr_Prev; | 194 | UString _filesStr_Prev; |
176 | UString _filesTotStr_Prev; | 195 | UString _filesTotStr_Prev; |
177 | 196 | ||
197 | unsigned _numReduceSymbols; | ||
178 | unsigned _prevSpeed_MoveBits; | 198 | unsigned _prevSpeed_MoveBits; |
179 | UInt64 _prevSpeed; | 199 | UInt64 _prevSpeed; |
180 | 200 | ||
181 | bool _foreground; | ||
182 | |||
183 | unsigned _numReduceSymbols; | ||
184 | |||
185 | bool _wasCreated; | ||
186 | bool _needClose; | ||
187 | |||
188 | unsigned _numPostedMessages; | ||
189 | UInt32 _numAutoSizeMessages; | ||
190 | |||
191 | bool _errorsWereDisplayed; | ||
192 | |||
193 | bool _waitCloseByCancelButton; | ||
194 | bool _cancelWasPressed; | ||
195 | |||
196 | bool _inCancelMessageBox; | ||
197 | bool _externalCloseMessageWasReceived; | ||
198 | |||
199 | |||
200 | // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ | 201 | // #ifdef __ITaskbarList3_INTERFACE_DEFINED__ |
201 | void SetTaskbarProgressState(TBPFLAG tbpFlags) | 202 | void SetTaskbarProgressState(TBPFLAG tbpFlags) |
202 | { | 203 | { |
@@ -244,14 +245,10 @@ class CProgressDialog: public NWindows::NControl::CModalDialog | |||
244 | void ShowAfterMessages(HWND wndParent); | 245 | void ShowAfterMessages(HWND wndParent); |
245 | 246 | ||
246 | void CheckNeedClose(); | 247 | void CheckNeedClose(); |
248 | |||
247 | public: | 249 | public: |
248 | CProgressSync Sync; | 250 | CProgressSync Sync; |
249 | bool CompressingMode; | ||
250 | bool WaitMode; | ||
251 | bool ShowCompressionInfo; | ||
252 | bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. | ||
253 | int IconID; | 251 | int IconID; |
254 | |||
255 | HWND MainWindow; | 252 | HWND MainWindow; |
256 | #ifndef Z7_SFX | 253 | #ifndef Z7_SFX |
257 | UString MainTitle; | 254 | UString MainTitle; |
diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp index 7e61998..0284591 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp | |||
@@ -86,17 +86,15 @@ static bool Read7ZipOption(LPCTSTR value, bool defaultValue) | |||
86 | if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) | 86 | if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) |
87 | { | 87 | { |
88 | bool enabled; | 88 | bool enabled; |
89 | if (key.QueryValue(value, enabled) == ERROR_SUCCESS) | 89 | if (key.GetValue_bool_IfOk(value, enabled) == ERROR_SUCCESS) |
90 | return enabled; | 90 | return enabled; |
91 | } | 91 | } |
92 | return defaultValue; | 92 | return defaultValue; |
93 | } | 93 | } |
94 | 94 | ||
95 | static void ReadOption(CKey &key, LPCTSTR value, bool &dest) | 95 | static void ReadOption(CKey &key, LPCTSTR name, bool &dest) |
96 | { | 96 | { |
97 | bool enabled = false; | 97 | key.GetValue_bool_IfOk(name, dest); |
98 | if (key.QueryValue(value, enabled) == ERROR_SUCCESS) | ||
99 | dest = enabled; | ||
100 | } | 98 | } |
101 | 99 | ||
102 | /* | 100 | /* |
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 192f660..b512f3b 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp | |||
@@ -249,7 +249,7 @@ Z7_COM7F_IMF(CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu | |||
249 | AreEqualNames(name2, L"Documents")) | 249 | AreEqualNames(name2, L"Documents")) |
250 | return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder); | 250 | return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder); |
251 | #else | 251 | #else |
252 | if (name2 == WSTRING_PATH_SEPARATOR) | 252 | if (name2.IsEqualTo(STRING_PATH_SEPARATOR)) |
253 | return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); | 253 | return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); |
254 | #endif | 254 | #endif |
255 | 255 | ||
@@ -257,7 +257,7 @@ Z7_COM7F_IMF(CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu | |||
257 | AreEqualNames(name2, L"Computer")) | 257 | AreEqualNames(name2, L"Computer")) |
258 | return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); | 258 | return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); |
259 | 259 | ||
260 | if (name2 == WSTRING_PATH_SEPARATOR) | 260 | if (name2.IsEqualTo(STRING_PATH_SEPARATOR)) |
261 | { | 261 | { |
262 | CMyComPtr<IFolderFolder> subFolder = this; | 262 | CMyComPtr<IFolderFolder> subFolder = this; |
263 | *resultFolder = subFolder.Detach(); | 263 | *resultFolder = subFolder.Detach(); |
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index a5117be..8b5983a 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp | |||
@@ -161,7 +161,7 @@ bool CSettingsPage::OnInit() | |||
161 | needSetCur = false; | 161 | needSetCur = false; |
162 | } | 162 | } |
163 | { | 163 | { |
164 | _ramSize = (UInt64)(sizeof(size_t)) << 29; | 164 | _ramSize = (size_t)sizeof(size_t) << 29; |
165 | _ramSize_Defined = NSystem::GetRamSize(_ramSize); | 165 | _ramSize_Defined = NSystem::GetRamSize(_ramSize); |
166 | UString s; | 166 | UString s; |
167 | if (_ramSize_Defined) | 167 | if (_ramSize_Defined) |
@@ -198,10 +198,10 @@ bool CSettingsPage::OnInit() | |||
198 | 198 | ||
199 | 199 | ||
200 | { | 200 | { |
201 | UInt64 ramSize = (UInt64)sizeof(size_t) << 29; | 201 | size_t ramSize = (size_t)sizeof(size_t) << 29; |
202 | const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize); | 202 | const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize); |
203 | // ramSize *= 10; // for debug | 203 | // ramSize *= 10; // for debug |
204 | UInt64 ramSize_GB = (ramSize + (1u << 29)) >> 30; | 204 | UInt32 ramSize_GB = (UInt32)(((UInt64)ramSize + (1u << 29)) >> 30); |
205 | if (ramSize_GB == 0) | 205 | if (ramSize_GB == 0) |
206 | ramSize_GB = 1; | 206 | ramSize_GB = 1; |
207 | UString s ("GB"); | 207 | UString s ("GB"); |
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index 406c9e1..72fe5e7 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp | |||
@@ -109,7 +109,7 @@ DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( | |||
109 | iconIndex = shFileInfo.iIcon; | 109 | iconIndex = shFileInfo.iIcon; |
110 | // we use SHGFI_USEFILEATTRIBUTES, and | 110 | // we use SHGFI_USEFILEATTRIBUTES, and |
111 | // (res != 0) is expected for main cases, even if there are no such file. | 111 | // (res != 0) is expected for main cases, even if there are no such file. |
112 | // (res == 0) for path with kSuperPrefix \\?\ | 112 | // (res == 0) for path with kSuperPrefix "\\?\" |
113 | // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe. | 113 | // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe. |
114 | // So we can use SHGFI_USEFILEATTRIBUTES for any case. | 114 | // So we can use SHGFI_USEFILEATTRIBUTES for any case. |
115 | // UString temp = fs2us(path); // for debug | 115 | // UString temp = fs2us(path); // for debug |
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp index 71ad710..0796eba 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp | |||
@@ -113,6 +113,29 @@ Z7_COM7F_IMF(CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, con | |||
113 | return ProgressDialog->Sync.CheckStop(); | 113 | return ProgressDialog->Sync.CheckStop(); |
114 | } | 114 | } |
115 | 115 | ||
116 | |||
117 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode)) | ||
118 | { | ||
119 | return MoveArc_Start_Base(srcTempPath, destFinalPath, size, updateMode); | ||
120 | } | ||
121 | |||
122 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) | ||
123 | { | ||
124 | return MoveArc_Progress_Base(totalSize, currentSize); | ||
125 | } | ||
126 | |||
127 | Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Finish()) | ||
128 | { | ||
129 | return MoveArc_Finish_Base(); | ||
130 | } | ||
131 | |||
132 | Z7_COM7F_IMF(CUpdateCallback100Imp::Before_ArcReopen()) | ||
133 | { | ||
134 | ProgressDialog->Sync.Clear_Stop_Status(); | ||
135 | return S_OK; | ||
136 | } | ||
137 | |||
138 | |||
116 | Z7_COM7F_IMF(CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)) | 139 | Z7_COM7F_IMF(CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)) |
117 | { | 140 | { |
118 | *password = NULL; | 141 | *password = NULL; |
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h index 5d56dfb..adae94f 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.h +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h | |||
@@ -16,6 +16,7 @@ | |||
16 | class CUpdateCallback100Imp Z7_final: | 16 | class CUpdateCallback100Imp Z7_final: |
17 | public IFolderArchiveUpdateCallback, | 17 | public IFolderArchiveUpdateCallback, |
18 | public IFolderArchiveUpdateCallback2, | 18 | public IFolderArchiveUpdateCallback2, |
19 | public IFolderArchiveUpdateCallback_MoveArc, | ||
19 | public IFolderScanProgress, | 20 | public IFolderScanProgress, |
20 | public ICryptoGetTextPassword2, | 21 | public ICryptoGetTextPassword2, |
21 | public ICryptoGetTextPassword, | 22 | public ICryptoGetTextPassword, |
@@ -24,9 +25,10 @@ class CUpdateCallback100Imp Z7_final: | |||
24 | public CUpdateCallbackGUI2, | 25 | public CUpdateCallbackGUI2, |
25 | public CMyUnknownImp | 26 | public CMyUnknownImp |
26 | { | 27 | { |
27 | Z7_COM_UNKNOWN_IMP_7( | 28 | Z7_COM_UNKNOWN_IMP_8( |
28 | IFolderArchiveUpdateCallback, | 29 | IFolderArchiveUpdateCallback, |
29 | IFolderArchiveUpdateCallback2, | 30 | IFolderArchiveUpdateCallback2, |
31 | IFolderArchiveUpdateCallback_MoveArc, | ||
30 | IFolderScanProgress, | 32 | IFolderScanProgress, |
31 | ICryptoGetTextPassword2, | 33 | ICryptoGetTextPassword2, |
32 | ICryptoGetTextPassword, | 34 | ICryptoGetTextPassword, |
@@ -36,6 +38,7 @@ class CUpdateCallback100Imp Z7_final: | |||
36 | Z7_IFACE_COM7_IMP(IProgress) | 38 | Z7_IFACE_COM7_IMP(IProgress) |
37 | Z7_IFACE_COM7_IMP(IFolderArchiveUpdateCallback) | 39 | Z7_IFACE_COM7_IMP(IFolderArchiveUpdateCallback) |
38 | Z7_IFACE_COM7_IMP(IFolderArchiveUpdateCallback2) | 40 | Z7_IFACE_COM7_IMP(IFolderArchiveUpdateCallback2) |
41 | Z7_IFACE_COM7_IMP(IFolderArchiveUpdateCallback_MoveArc) | ||
39 | Z7_IFACE_COM7_IMP(IFolderScanProgress) | 42 | Z7_IFACE_COM7_IMP(IFolderScanProgress) |
40 | Z7_IFACE_COM7_IMP(ICryptoGetTextPassword2) | 43 | Z7_IFACE_COM7_IMP(ICryptoGetTextPassword2) |
41 | Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) | 44 | Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) |
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index 3d64602..4a8f58d 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp | |||
@@ -81,15 +81,15 @@ void CListViewInfo::Read(const UString &id) | |||
81 | { | 81 | { |
82 | Clear(); | 82 | Clear(); |
83 | CByteBuffer buf; | 83 | CByteBuffer buf; |
84 | UInt32 size; | ||
85 | { | 84 | { |
86 | NSynchronization::CCriticalSectionLock lock(g_CS); | 85 | NSynchronization::CCriticalSectionLock lock(g_CS); |
87 | CKey key; | 86 | CKey key; |
88 | if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS) | 87 | if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS) |
89 | return; | 88 | return; |
90 | if (key.QueryValue(GetSystemString(id), buf, size) != ERROR_SUCCESS) | 89 | if (key.QueryValue_Binary(GetSystemString(id), buf) != ERROR_SUCCESS) |
91 | return; | 90 | return; |
92 | } | 91 | } |
92 | unsigned size = (unsigned)buf.Size(); | ||
93 | if (size < kListViewHeaderSize) | 93 | if (size < kListViewHeaderSize) |
94 | return; | 94 | return; |
95 | UInt32 version; | 95 | UInt32 version; |
@@ -104,7 +104,9 @@ void CListViewInfo::Read(const UString &id) | |||
104 | size -= kListViewHeaderSize; | 104 | size -= kListViewHeaderSize; |
105 | if (size % kColumnInfoSize != 0) | 105 | if (size % kColumnInfoSize != 0) |
106 | return; | 106 | return; |
107 | unsigned numItems = size / kColumnInfoSize; | 107 | if (size > 1000 * kColumnInfoSize) |
108 | return; | ||
109 | const unsigned numItems = size / kColumnInfoSize; | ||
108 | Columns.ClearAndReserve(numItems); | 110 | Columns.ClearAndReserve(numItems); |
109 | for (unsigned i = 0; i < numItems; i++) | 111 | for (unsigned i = 0; i < numItems; i++) |
110 | { | 112 | { |
@@ -161,8 +163,7 @@ void CWindowInfo::Save() const | |||
161 | 163 | ||
162 | static bool QueryBuf(CKey &key, LPCTSTR name, CByteBuffer &buf, UInt32 dataSize) | 164 | static bool QueryBuf(CKey &key, LPCTSTR name, CByteBuffer &buf, UInt32 dataSize) |
163 | { | 165 | { |
164 | UInt32 size; | 166 | return key.QueryValue_Binary(name, buf) == ERROR_SUCCESS && buf.Size() == dataSize; |
165 | return key.QueryValue(name, buf, size) == ERROR_SUCCESS && size == dataSize; | ||
166 | } | 167 | } |
167 | 168 | ||
168 | void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined) | 169 | void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined) |
@@ -206,7 +207,7 @@ static bool ReadUi32Val(const TCHAR *name, UInt32 &value) | |||
206 | CKey key; | 207 | CKey key; |
207 | if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) | 208 | if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) |
208 | return false; | 209 | return false; |
209 | return key.QueryValue(name, value) == ERROR_SUCCESS; | 210 | return key.GetValue_UInt32_IfOk(name, value) == ERROR_SUCCESS; |
210 | } | 211 | } |
211 | 212 | ||
212 | void SaveToolbarsMask(UInt32 toolbarMask) | 213 | void SaveToolbarsMask(UInt32 toolbarMask) |
@@ -229,7 +230,7 @@ void CListMode::Save() const | |||
229 | { | 230 | { |
230 | UInt32 t = 0; | 231 | UInt32 t = 0; |
231 | for (int i = 0; i < 2; i++) | 232 | for (int i = 0; i < 2; i++) |
232 | t |= ((Panels[i]) & 0xFF) << (i * 8); | 233 | t |= (Panels[i] & 0xFF) << (i * 8); |
233 | SaveUi32Val(kListMode, t); | 234 | SaveUi32Val(kListMode, t); |
234 | } | 235 | } |
235 | 236 | ||
@@ -241,7 +242,7 @@ void CListMode::Read() | |||
241 | return; | 242 | return; |
242 | for (int i = 0; i < 2; i++) | 243 | for (int i = 0; i < 2; i++) |
243 | { | 244 | { |
244 | Panels[i] = (t & 0xFF); | 245 | Panels[i] = t & 0xFF; |
245 | t >>= 8; | 246 | t >>= 8; |
246 | } | 247 | } |
247 | } | 248 | } |
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile index 0ca5caa..24dc4ca 100644 --- a/CPP/7zip/UI/FileManager/makefile +++ b/CPP/7zip/UI/FileManager/makefile | |||
@@ -104,7 +104,7 @@ AR_COMMON_OBJS = \ | |||
104 | C_OBJS = $(C_OBJS) \ | 104 | C_OBJS = $(C_OBJS) \ |
105 | $O\Alloc.obj \ | 105 | $O\Alloc.obj \ |
106 | $O\CpuArch.obj \ | 106 | $O\CpuArch.obj \ |
107 | $O\Sort.obj \ | ||
108 | $O\Threads.obj \ | 107 | $O\Threads.obj \ |
109 | 108 | ||
109 | !include "../../Sort.mak" | ||
110 | !include "../../7zip.mak" | 110 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index 4e22230..36c4b53 100644 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h | |||
@@ -25,9 +25,12 @@ | |||
25 | #define IDM_CRC64 103 | 25 | #define IDM_CRC64 103 |
26 | #define IDM_SHA1 104 | 26 | #define IDM_SHA1 104 |
27 | #define IDM_SHA256 105 | 27 | #define IDM_SHA256 105 |
28 | #define IDM_XXH64 106 | 28 | #define IDM_SHA384 106 |
29 | #define IDM_BLAKE2SP 107 | 29 | #define IDM_SHA512 107 |
30 | 30 | #define IDM_SHA3_256 108 | |
31 | #define IDM_XXH64 120 | ||
32 | #define IDM_BLAKE2SP 121 | ||
33 | #define IDM_MD5 122 | ||
31 | 34 | ||
32 | #define IDM_FILE 500 | 35 | #define IDM_FILE 500 |
33 | #define IDM_EDIT 501 | 36 | #define IDM_EDIT 501 |
@@ -134,7 +137,7 @@ | |||
134 | #define IDS_COPY_TO 6002 | 137 | #define IDS_COPY_TO 6002 |
135 | #define IDS_MOVE_TO 6003 | 138 | #define IDS_MOVE_TO 6003 |
136 | #define IDS_COPYING 6004 | 139 | #define IDS_COPYING 6004 |
137 | #define IDS_MOVING 6005 | 140 | // #define IDS_MOVING 6005 |
138 | #define IDS_RENAMING 6006 | 141 | #define IDS_RENAMING 6006 |
139 | 142 | ||
140 | #define IDS_OPERATION_IS_NOT_SUPPORTED 6008 | 143 | #define IDS_OPERATION_IS_NOT_SUPPORTED 6008 |
diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index feeeaf5..d9fc6f2 100644 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc | |||
@@ -58,8 +58,12 @@ BEGIN | |||
58 | MENUITEM "CRC-32", IDM_CRC32 | 58 | MENUITEM "CRC-32", IDM_CRC32 |
59 | MENUITEM "CRC-64", IDM_CRC64 | 59 | MENUITEM "CRC-64", IDM_CRC64 |
60 | MENUITEM "XXH64", IDM_XXH64 | 60 | MENUITEM "XXH64", IDM_XXH64 |
61 | MENUITEM "MD5", IDM_MD5 | ||
61 | MENUITEM "SHA-1", IDM_SHA1 | 62 | MENUITEM "SHA-1", IDM_SHA1 |
62 | MENUITEM "SHA-256", IDM_SHA256 | 63 | MENUITEM "SHA-256", IDM_SHA256 |
64 | MENUITEM "SHA-384", IDM_SHA384 | ||
65 | MENUITEM "SHA-512", IDM_SHA512 | ||
66 | MENUITEM "SHA3-256", IDM_SHA3_256 | ||
63 | MENUITEM "BLAKE2sp", IDM_BLAKE2SP | 67 | MENUITEM "BLAKE2sp", IDM_BLAKE2SP |
64 | MENUITEM "*", IDM_HASH_ALL | 68 | MENUITEM "*", IDM_HASH_ALL |
65 | END | 69 | END |
@@ -202,7 +206,7 @@ BEGIN | |||
202 | IDS_COPY_TO "Copy to:" | 206 | IDS_COPY_TO "Copy to:" |
203 | IDS_MOVE_TO "Move to:" | 207 | IDS_MOVE_TO "Move to:" |
204 | IDS_COPYING "Copying..." | 208 | IDS_COPYING "Copying..." |
205 | IDS_MOVING "Moving..." | 209 | // IDS_MOVING "Moving..." |
206 | IDS_RENAMING "Renaming..." | 210 | IDS_RENAMING "Renaming..." |
207 | 211 | ||
208 | IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported." | 212 | IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported." |
diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h index 848b36f..2e1bab3 100644 --- a/CPP/7zip/UI/FileManager/resourceGui.h +++ b/CPP/7zip/UI/FileManager/resourceGui.h | |||
@@ -6,6 +6,8 @@ | |||
6 | #define IDS_OPENNING 3303 | 6 | #define IDS_OPENNING 3303 |
7 | #define IDS_SCANNING 3304 | 7 | #define IDS_SCANNING 3304 |
8 | 8 | ||
9 | #define IDS_MOVING 6005 | ||
10 | |||
9 | #define IDS_CHECKSUM_CALCULATING 7500 | 11 | #define IDS_CHECKSUM_CALCULATING 7500 |
10 | #define IDS_CHECKSUM_INFORMATION 7501 | 12 | #define IDS_CHECKSUM_INFORMATION 7501 |
11 | #define IDS_CHECKSUM_CRC_DATA 7502 | 13 | #define IDS_CHECKSUM_CRC_DATA 7502 |
diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc index 143e9f6..ad0d1f4 100644 --- a/CPP/7zip/UI/FileManager/resourceGui.rc +++ b/CPP/7zip/UI/FileManager/resourceGui.rc | |||
@@ -6,6 +6,8 @@ BEGIN | |||
6 | 6 | ||
7 | IDS_PROGRESS_TESTING "Testing" | 7 | IDS_PROGRESS_TESTING "Testing" |
8 | 8 | ||
9 | IDS_MOVING "Moving..." | ||
10 | |||
9 | IDS_CHECKSUM_CALCULATING "Checksum calculating..." | 11 | IDS_CHECKSUM_CALCULATING "Checksum calculating..." |
10 | IDS_CHECKSUM_INFORMATION "Checksum information" | 12 | IDS_CHECKSUM_INFORMATION "Checksum information" |
11 | IDS_CHECKSUM_CRC_DATA "CRC checksum for data:" | 13 | IDS_CHECKSUM_CRC_DATA "CRC checksum for data:" |
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 7f2edfa..1686c69 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp | |||
@@ -61,9 +61,9 @@ struct CBenchPassResult | |||
61 | { | 61 | { |
62 | CTotalBenchRes Enc; | 62 | CTotalBenchRes Enc; |
63 | CTotalBenchRes Dec; | 63 | CTotalBenchRes Dec; |
64 | #ifdef PRINT_ITER_TIME | 64 | #ifdef PRINT_ITER_TIME |
65 | DWORD Ticks; | 65 | DWORD Ticks; |
66 | #endif | 66 | #endif |
67 | // CBenchInfo EncInfo; // for debug | 67 | // CBenchInfo EncInfo; // for debug |
68 | // CBenchPassResult() {}; | 68 | // CBenchPassResult() {}; |
69 | }; | 69 | }; |
@@ -97,21 +97,9 @@ struct CTotalBenchRes2: public CTotalBenchRes | |||
97 | struct CSyncData | 97 | struct CSyncData |
98 | { | 98 | { |
99 | UInt32 NumPasses_Finished; | 99 | UInt32 NumPasses_Finished; |
100 | 100 | #ifdef PRINT_ITER_TIME | |
101 | // UInt64 NumEncProgress; // for debug | ||
102 | // UInt64 NumDecProgress; // for debug | ||
103 | // CBenchInfo EncInfo; // for debug | ||
104 | |||
105 | CTotalBenchRes2 Enc_BenchRes_1; | ||
106 | CTotalBenchRes2 Enc_BenchRes; | ||
107 | |||
108 | CTotalBenchRes2 Dec_BenchRes_1; | ||
109 | CTotalBenchRes2 Dec_BenchRes; | ||
110 | |||
111 | #ifdef PRINT_ITER_TIME | ||
112 | DWORD TotalTicks; | 101 | DWORD TotalTicks; |
113 | #endif | 102 | #endif |
114 | |||
115 | int RatingVector_DeletedIndex; | 103 | int RatingVector_DeletedIndex; |
116 | // UInt64 RatingVector_NumDeleted; | 104 | // UInt64 RatingVector_NumDeleted; |
117 | 105 | ||
@@ -124,6 +112,16 @@ struct CSyncData | |||
124 | bool NeedPrint_Dec; | 112 | bool NeedPrint_Dec; |
125 | bool NeedPrint_Tot; // intermediate Total was updated after current pass | 113 | bool NeedPrint_Tot; // intermediate Total was updated after current pass |
126 | 114 | ||
115 | // UInt64 NumEncProgress; // for debug | ||
116 | // UInt64 NumDecProgress; // for debug | ||
117 | // CBenchInfo EncInfo; // for debug | ||
118 | |||
119 | CTotalBenchRes2 Enc_BenchRes_1; | ||
120 | CTotalBenchRes2 Enc_BenchRes; | ||
121 | |||
122 | CTotalBenchRes2 Dec_BenchRes_1; | ||
123 | CTotalBenchRes2 Dec_BenchRes; | ||
124 | |||
127 | void Init(); | 125 | void Init(); |
128 | }; | 126 | }; |
129 | 127 | ||
@@ -161,24 +159,18 @@ void CSyncData::Init() | |||
161 | struct CBenchProgressSync | 159 | struct CBenchProgressSync |
162 | { | 160 | { |
163 | bool Exit; // GUI asks BenchThread to Exit, and BenchThread reads that variable | 161 | bool Exit; // GUI asks BenchThread to Exit, and BenchThread reads that variable |
162 | bool TextWasChanged; | ||
163 | |||
164 | UInt32 NumThreads; | 164 | UInt32 NumThreads; |
165 | UInt64 DictSize; | 165 | UInt64 DictSize; |
166 | UInt32 NumPasses_Limit; | 166 | UInt32 NumPasses_Limit; |
167 | int Level; | 167 | int Level; |
168 | |||
169 | // must be written by benchmark thread, read by GUI thread */ | ||
170 | CSyncData sd; | ||
171 | CRecordVector<CBenchPassResult> RatingVector; | ||
172 | |||
173 | NWindows::NSynchronization::CCriticalSection CS; | ||
174 | 168 | ||
175 | AString Text; | 169 | AString Text; |
176 | bool TextWasChanged; | ||
177 | 170 | ||
178 | /* BenchFinish_Task_HRESULT - for result from benchmark code | 171 | /* BenchFinish_Task_HRESULT - for result from benchmark code |
179 | BenchFinish_Thread_HRESULT - for Exceptions and service errors | 172 | BenchFinish_Thread_HRESULT - for Exceptions and service errors |
180 | these arreos must be shown even if user escapes benchmark */ | 173 | these arreos must be shown even if user escapes benchmark */ |
181 | |||
182 | HRESULT BenchFinish_Task_HRESULT; | 174 | HRESULT BenchFinish_Task_HRESULT; |
183 | HRESULT BenchFinish_Thread_HRESULT; | 175 | HRESULT BenchFinish_Thread_HRESULT; |
184 | 176 | ||
@@ -186,6 +178,12 @@ struct CBenchProgressSync | |||
186 | UString FreqString_Sync; | 178 | UString FreqString_Sync; |
187 | UString FreqString_GUI; | 179 | UString FreqString_GUI; |
188 | 180 | ||
181 | // must be written by benchmark thread, read by GUI thread */ | ||
182 | CRecordVector<CBenchPassResult> RatingVector; | ||
183 | CSyncData sd; | ||
184 | |||
185 | NWindows::NSynchronization::CCriticalSection CS; | ||
186 | |||
189 | CBenchProgressSync() | 187 | CBenchProgressSync() |
190 | { | 188 | { |
191 | NumPasses_Limit = 1; | 189 | NumPasses_Limit = 1; |
@@ -258,6 +256,19 @@ struct CThreadBenchmark | |||
258 | class CBenchmarkDialog: | 256 | class CBenchmarkDialog: |
259 | public NWindows::NControl::CModalDialog | 257 | public NWindows::NControl::CModalDialog |
260 | { | 258 | { |
259 | bool _finishTime_WasSet; | ||
260 | |||
261 | bool WasStopped_in_GUI; | ||
262 | bool ExitWasAsked_in_GUI; | ||
263 | bool NeedRestart; | ||
264 | |||
265 | bool RamSize_Defined; | ||
266 | |||
267 | public: | ||
268 | bool TotalMode; | ||
269 | |||
270 | private: | ||
271 | |||
261 | NWindows::NControl::CComboBox m_Dictionary; | 272 | NWindows::NControl::CComboBox m_Dictionary; |
262 | NWindows::NControl::CComboBox m_NumThreads; | 273 | NWindows::NControl::CComboBox m_NumThreads; |
263 | NWindows::NControl::CComboBox m_NumPasses; | 274 | NWindows::NControl::CComboBox m_NumPasses; |
@@ -266,17 +277,11 @@ class CBenchmarkDialog: | |||
266 | 277 | ||
267 | UInt32 _startTime; | 278 | UInt32 _startTime; |
268 | UInt32 _finishTime; | 279 | UInt32 _finishTime; |
269 | bool _finishTime_WasSet; | ||
270 | |||
271 | bool WasStopped_in_GUI; | ||
272 | bool ExitWasAsked_in_GUI; | ||
273 | bool NeedRestart; | ||
274 | 280 | ||
275 | CMyFont _font; | 281 | CMyFont _font; |
276 | 282 | ||
277 | UInt64 RamSize; | 283 | size_t RamSize; |
278 | UInt64 RamSize_Limit; | 284 | size_t RamSize_Limit; |
279 | bool RamSize_Defined; | ||
280 | 285 | ||
281 | UInt32 NumPasses_Finished_Prev; | 286 | UInt32 NumPasses_Finished_Prev; |
282 | 287 | ||
@@ -330,7 +335,6 @@ class CBenchmarkDialog: | |||
330 | public: | 335 | public: |
331 | CBenchProgressSync Sync; | 336 | CBenchProgressSync Sync; |
332 | 337 | ||
333 | bool TotalMode; | ||
334 | CObjectVector<CProperty> Props; | 338 | CObjectVector<CProperty> Props; |
335 | 339 | ||
336 | CSysString Bench2Text; | 340 | CSysString Bench2Text; |
@@ -339,11 +343,11 @@ public: | |||
339 | CThreadBenchmark _threadBenchmark; | 343 | CThreadBenchmark _threadBenchmark; |
340 | 344 | ||
341 | CBenchmarkDialog(): | 345 | CBenchmarkDialog(): |
342 | _timer(0), | ||
343 | WasStopped_in_GUI(false), | 346 | WasStopped_in_GUI(false), |
344 | ExitWasAsked_in_GUI(false), | 347 | ExitWasAsked_in_GUI(false), |
345 | NeedRestart(false), | 348 | NeedRestart(false), |
346 | TotalMode(false) | 349 | TotalMode(false), |
350 | _timer(0) | ||
347 | {} | 351 | {} |
348 | 352 | ||
349 | ~CBenchmarkDialog() Z7_DESTRUCTOR_override; | 353 | ~CBenchmarkDialog() Z7_DESTRUCTOR_override; |
@@ -504,7 +508,8 @@ bool CBenchmarkDialog::OnInit() | |||
504 | SetItemTextA(IDT_BENCH_SYS2, s2); | 508 | SetItemTextA(IDT_BENCH_SYS2, s2); |
505 | } | 509 | } |
506 | { | 510 | { |
507 | GetCpuName_MultiLine(s); | 511 | AString registers; |
512 | GetCpuName_MultiLine(s, registers); | ||
508 | SetItemTextA(IDT_BENCH_CPU, s); | 513 | SetItemTextA(IDT_BENCH_CPU, s); |
509 | } | 514 | } |
510 | { | 515 | { |
@@ -1851,7 +1856,7 @@ HRESULT Benchmark( | |||
1851 | const CProperty &prop = props[i]; | 1856 | const CProperty &prop = props[i]; |
1852 | UString name = prop.Name; | 1857 | UString name = prop.Name; |
1853 | name.MakeLower_Ascii(); | 1858 | name.MakeLower_Ascii(); |
1854 | if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value == L"*") | 1859 | if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value.IsEqualTo("*")) |
1855 | { | 1860 | { |
1856 | bd.TotalMode = true; | 1861 | bd.TotalMode = true; |
1857 | continue; | 1862 | continue; |
@@ -1860,7 +1865,7 @@ HRESULT Benchmark( | |||
1860 | NCOM::CPropVariant propVariant; | 1865 | NCOM::CPropVariant propVariant; |
1861 | if (!prop.Value.IsEmpty()) | 1866 | if (!prop.Value.IsEmpty()) |
1862 | ParseNumberString(prop.Value, propVariant); | 1867 | ParseNumberString(prop.Value, propVariant); |
1863 | if (name.IsPrefixedBy(L"mt")) | 1868 | if (name.IsPrefixedBy("mt")) |
1864 | { | 1869 | { |
1865 | #ifndef Z7_ST | 1870 | #ifndef Z7_ST |
1866 | RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads)) | 1871 | RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads)) |
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc index 3e73e46..5df7ff2 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc | |||
@@ -81,7 +81,7 @@ BEGIN | |||
81 | 81 | ||
82 | LTEXT "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 30, g0xs, 8 | 82 | LTEXT "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 30, g0xs, 8 |
83 | COMBOBOX IDC_BENCH_NUM_THREADS, g1x, 29, g1xs, 140, MY_COMBO | 83 | COMBOBOX IDC_BENCH_NUM_THREADS, g1x, 29, g1xs, 140, MY_COMBO |
84 | LTEXT "", IDT_BENCH_HARDWARE_THREADS, gc2x, 30, g7xs, MY_TEXT_NOPREFIX | 84 | LTEXT "", IDT_BENCH_HARDWARE_THREADS, gc2x, 30, g7xs, 24, SS_NOPREFIX |
85 | 85 | ||
86 | RTEXT "Size", IDT_BENCH_SIZE, xSize, 54, sSize, MY_TEXT_NOPREFIX | 86 | RTEXT "Size", IDT_BENCH_SIZE, xSize, 54, sSize, MY_TEXT_NOPREFIX |
87 | RTEXT "CPU Usage", IDT_BENCH_USAGE_LABEL, xUsage, 54, sUsage, MY_TEXT_NOPREFIX | 87 | RTEXT "CPU Usage", IDT_BENCH_USAGE_LABEL, xUsage, 54, sUsage, MY_TEXT_NOPREFIX |
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index fd53062..85d7186 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp | |||
@@ -211,11 +211,13 @@ static const EMethodID g_ZstdMethods[] = | |||
211 | }; | 211 | }; |
212 | */ | 212 | */ |
213 | 213 | ||
214 | /* | ||
214 | static const EMethodID g_SwfcMethods[] = | 215 | static const EMethodID g_SwfcMethods[] = |
215 | { | 216 | { |
216 | kDeflate | 217 | kDeflate |
217 | // kLZMA | 218 | // kLZMA |
218 | }; | 219 | }; |
220 | */ | ||
219 | 221 | ||
220 | static const EMethodID g_TarMethods[] = | 222 | static const EMethodID g_TarMethods[] = |
221 | { | 223 | { |
@@ -278,7 +280,8 @@ static const CFormatInfo g_Formats[] = | |||
278 | }, | 280 | }, |
279 | { | 281 | { |
280 | "7z", | 282 | "7z", |
281 | (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), | 283 | // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), |
284 | (1 << 10) - 1, | ||
282 | METHODS_PAIR(g_7zMethods), | 285 | METHODS_PAIR(g_7zMethods), |
283 | kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | | 286 | kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | |
284 | kFF_EncryptFileNames | kFF_MemUse | kFF_SFX | 287 | kFF_EncryptFileNames | kFF_MemUse | kFF_SFX |
@@ -306,7 +309,8 @@ static const CFormatInfo g_Formats[] = | |||
306 | }, | 309 | }, |
307 | { | 310 | { |
308 | "xz", | 311 | "xz", |
309 | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), | 312 | // (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), |
313 | (1 << 10) - 1 - (1 << 0), // store (1 << 0) is not supported | ||
310 | METHODS_PAIR(g_XzMethods), | 314 | METHODS_PAIR(g_XzMethods), |
311 | kFF_Solid | kFF_MultiThread | kFF_MemUse | 315 | kFF_Solid | kFF_MultiThread | kFF_MemUse |
312 | }, | 316 | }, |
@@ -321,12 +325,14 @@ static const CFormatInfo g_Formats[] = | |||
321 | | kFF_MemUse | 325 | | kFF_MemUse |
322 | }, | 326 | }, |
323 | */ | 327 | */ |
328 | /* | ||
324 | { | 329 | { |
325 | "Swfc", | 330 | "Swfc", |
326 | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), | 331 | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), |
327 | METHODS_PAIR(g_SwfcMethods), | 332 | METHODS_PAIR(g_SwfcMethods), |
328 | 0 | 333 | 0 |
329 | }, | 334 | }, |
335 | */ | ||
330 | { | 336 | { |
331 | "Tar", | 337 | "Tar", |
332 | (1 << 0), | 338 | (1 << 0), |
@@ -429,22 +435,23 @@ bool CCompressDialog::OnInit() | |||
429 | #endif | 435 | #endif |
430 | 436 | ||
431 | { | 437 | { |
432 | UInt64 size = (UInt64)(sizeof(size_t)) << 29; | 438 | size_t size = (size_t)sizeof(size_t) << 29; |
433 | _ramSize_Defined = NSystem::GetRamSize(size); | 439 | _ramSize_Defined = NSystem::GetRamSize(size); |
434 | // size = (UInt64)3 << 62; // for debug only; | 440 | // size = (UInt64)3 << 62; // for debug only; |
435 | _ramSize = size; | ||
436 | const UInt64 kMinUseSize = (1 << 26); | ||
437 | if (size < kMinUseSize) | ||
438 | size = kMinUseSize; | ||
439 | |||
440 | unsigned bits = sizeof(size_t) * 8; | ||
441 | if (bits == 32) | ||
442 | { | 441 | { |
443 | const UInt32 limit2 = (UInt32)7 << 28; | 442 | // we use reduced limit for 32-bit version: |
444 | if (size > limit2) | 443 | unsigned bits = sizeof(size_t) * 8; |
445 | size = limit2; | 444 | if (bits == 32) |
445 | { | ||
446 | const UInt32 limit2 = (UInt32)7 << 28; | ||
447 | if (size > limit2) | ||
448 | size = limit2; | ||
449 | } | ||
446 | } | 450 | } |
447 | 451 | _ramSize = size; | |
452 | const size_t kMinUseSize = 1 << 26; | ||
453 | if (size < kMinUseSize) | ||
454 | size = kMinUseSize; | ||
448 | _ramSize_Reduced = size; | 455 | _ramSize_Reduced = size; |
449 | 456 | ||
450 | // 80% - is auto usage limit in handlers | 457 | // 80% - is auto usage limit in handlers |
@@ -1580,24 +1587,26 @@ void CCompressDialog::SetLevel2() | |||
1580 | 1587 | ||
1581 | for (unsigned i = 0; i < sizeof(UInt32) * 8; i++) | 1588 | for (unsigned i = 0; i < sizeof(UInt32) * 8; i++) |
1582 | { | 1589 | { |
1583 | const UInt32 mask = (UInt32)1 << i; | 1590 | const UInt32 mask = fi.LevelsMask >> i; |
1584 | if ((fi.LevelsMask & mask) != 0) | 1591 | // if (mask == 0) break; |
1592 | if (mask & 1) | ||
1585 | { | 1593 | { |
1586 | const UInt32 langID = g_Levels[i]; | ||
1587 | UString s; | 1594 | UString s; |
1588 | s.Add_UInt32(i); | 1595 | s.Add_UInt32(i); |
1589 | // if (fi.LevelsMask < (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1) | 1596 | if (i < Z7_ARRAY_SIZE(g_Levels)) |
1590 | if (langID) | ||
1591 | if (i != 0 || !isZstd) | ||
1592 | { | 1597 | { |
1593 | s += " - "; | 1598 | const UInt32 langID = g_Levels[i]; |
1594 | s += LangString(langID); | 1599 | // if (fi.LevelsMask < (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1) |
1600 | if (langID) | ||
1601 | if (i != 0 || !isZstd) | ||
1602 | { | ||
1603 | s += " - "; | ||
1604 | AddLangString(s, langID); | ||
1605 | } | ||
1595 | } | 1606 | } |
1596 | const int index = (int)m_Level.AddString(s); | 1607 | const int index = (int)m_Level.AddString(s); |
1597 | m_Level.SetItemData(index, (LPARAM)i); | 1608 | m_Level.SetItemData(index, (LPARAM)i); |
1598 | } | 1609 | } |
1599 | if (fi.LevelsMask <= mask) | ||
1600 | break; | ||
1601 | } | 1610 | } |
1602 | SetNearestSelectComboBox(m_Level, level); | 1611 | SetNearestSelectComboBox(m_Level, level); |
1603 | } | 1612 | } |
@@ -1931,11 +1940,11 @@ void CCompressDialog::SetDictionary2() | |||
1931 | case kLZMA2: | 1940 | case kLZMA2: |
1932 | { | 1941 | { |
1933 | { | 1942 | { |
1934 | _auto_Dict = | 1943 | _auto_Dict = level <= 4 ? |
1935 | ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : | 1944 | (UInt32)1 << (level * 2 + 16) : |
1936 | ( level <= 6 ? ((UInt32)1 << (level + 19)) : | 1945 | level <= sizeof(size_t) / 2 + 4 ? |
1937 | ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) | 1946 | (UInt32)1 << (level + 20) : |
1938 | ))); | 1947 | (UInt32)1 << (sizeof(size_t) / 2 + 24); |
1939 | } | 1948 | } |
1940 | 1949 | ||
1941 | // we use threshold 3.75 GiB to switch to kLzmaMaxDictSize. | 1950 | // we use threshold 3.75 GiB to switch to kLzmaMaxDictSize. |
@@ -2591,11 +2600,17 @@ void CCompressDialog::SetNumThreads2() | |||
2591 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; | 2600 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; |
2592 | const int methodID = GetMethodID(); | 2601 | const int methodID = GetMethodID(); |
2593 | 2602 | ||
2594 | switch (methodID) | 2603 | const bool isZip = IsZipFormat(); |
2604 | if (isZip) | ||
2605 | numAlgoThreadsMax = | ||
2606 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit | ||
2607 | else if (IsXzFormat()) | ||
2608 | numAlgoThreadsMax = 256 * 2; | ||
2609 | else switch (methodID) | ||
2595 | { | 2610 | { |
2596 | case kLZMA: numAlgoThreadsMax = 2; break; | 2611 | case kLZMA: numAlgoThreadsMax = 2; break; |
2597 | case kLZMA2: numAlgoThreadsMax = 256; break; | 2612 | case kLZMA2: numAlgoThreadsMax = 256; break; |
2598 | case kBZip2: numAlgoThreadsMax = 32; break; | 2613 | case kBZip2: numAlgoThreadsMax = 64; break; |
2599 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; | 2614 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; |
2600 | case kCopy: | 2615 | case kCopy: |
2601 | case kPPMd: | 2616 | case kPPMd: |
@@ -2604,17 +2619,6 @@ void CCompressDialog::SetNumThreads2() | |||
2604 | case kPPMdZip: | 2619 | case kPPMdZip: |
2605 | numAlgoThreadsMax = 1; | 2620 | numAlgoThreadsMax = 1; |
2606 | } | 2621 | } |
2607 | const bool isZip = IsZipFormat(); | ||
2608 | if (isZip) | ||
2609 | { | ||
2610 | numAlgoThreadsMax = | ||
2611 | #ifdef _WIN32 | ||
2612 | 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here | ||
2613 | #else | ||
2614 | 128; | ||
2615 | #endif | ||
2616 | } | ||
2617 | |||
2618 | UInt32 autoThreads = numHardwareThreads; | 2622 | UInt32 autoThreads = numHardwareThreads; |
2619 | if (autoThreads > numAlgoThreadsMax) | 2623 | if (autoThreads > numAlgoThreadsMax) |
2620 | autoThreads = numAlgoThreadsMax; | 2624 | autoThreads = numAlgoThreadsMax; |
@@ -2999,7 +3003,7 @@ UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, | |||
2999 | else | 3003 | else |
3000 | { | 3004 | { |
3001 | size += numBlockThreads * (size1 + chunkSize); | 3005 | size += numBlockThreads * (size1 + chunkSize); |
3002 | UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; | 3006 | const UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; |
3003 | if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++; | 3007 | if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++; |
3004 | if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++; | 3008 | if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++; |
3005 | if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++; | 3009 | if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++; |
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index c2d2699..e0f3aa5 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h | |||
@@ -141,6 +141,15 @@ struct CBool1 | |||
141 | 141 | ||
142 | class CCompressDialog: public NWindows::NControl::CModalDialog | 142 | class CCompressDialog: public NWindows::NControl::CModalDialog |
143 | { | 143 | { |
144 | public: | ||
145 | CBool1 SymLinks; | ||
146 | CBool1 HardLinks; | ||
147 | CBool1 AltStreams; | ||
148 | CBool1 NtSecurity; | ||
149 | CBool1 PreserveATime; | ||
150 | private: | ||
151 | bool _ramSize_Defined; | ||
152 | |||
144 | NWindows::NControl::CComboBox m_ArchivePath; | 153 | NWindows::NControl::CComboBox m_ArchivePath; |
145 | NWindows::NControl::CComboBox m_Format; | 154 | NWindows::NControl::CComboBox m_Format; |
146 | NWindows::NControl::CComboBox m_Level; | 155 | NWindows::NControl::CComboBox m_Level; |
@@ -179,20 +188,13 @@ class CCompressDialog: public NWindows::NControl::CModalDialog | |||
179 | UString DirPrefix; | 188 | UString DirPrefix; |
180 | UString StartDirPrefix; | 189 | UString StartDirPrefix; |
181 | 190 | ||
182 | bool _ramSize_Defined; | 191 | size_t _ramSize; // full RAM size avail |
183 | UInt64 _ramSize; // full RAM size avail | 192 | size_t _ramSize_Reduced; // full for 64-bit and reduced for 32-bit |
184 | UInt64 _ramSize_Reduced; // full for 64-bit and reduced for 32-bit | ||
185 | UInt64 _ramUsage_Auto; | 193 | UInt64 _ramUsage_Auto; |
186 | 194 | ||
187 | public: | 195 | public: |
188 | NCompression::CInfo m_RegistryInfo; | 196 | NCompression::CInfo m_RegistryInfo; |
189 | 197 | ||
190 | CBool1 SymLinks; | ||
191 | CBool1 HardLinks; | ||
192 | CBool1 AltStreams; | ||
193 | CBool1 NtSecurity; | ||
194 | CBool1 PreserveATime; | ||
195 | |||
196 | void SetArchiveName(const UString &name); | 198 | void SetArchiveName(const UString &name); |
197 | int FindRegistryFormat(const UString &name); | 199 | int FindRegistryFormat(const UString &name); |
198 | unsigned FindRegistryFormat_Always(const UString &name); | 200 | unsigned FindRegistryFormat_Always(const UString &name); |
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp index 26057a7..424c6e4 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp | |||
@@ -252,6 +252,21 @@ HRESULT CUpdateCallbackGUI::DeletingAfterArchiving(const FString &path, bool isD | |||
252 | return ProgressDialog->Sync.Set_Status2(_lang_Removing, fs2us(path), isDir); | 252 | return ProgressDialog->Sync.Set_Status2(_lang_Removing, fs2us(path), isDir); |
253 | } | 253 | } |
254 | 254 | ||
255 | |||
256 | HRESULT CUpdateCallbackGUI::MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 totalSize, Int32 updateMode) | ||
257 | { | ||
258 | return MoveArc_Start_Base(srcTempPath, destFinalPath, totalSize, updateMode); | ||
259 | } | ||
260 | HRESULT CUpdateCallbackGUI::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize) | ||
261 | { | ||
262 | return MoveArc_Progress_Base(totalSize, currentSize); | ||
263 | } | ||
264 | HRESULT CUpdateCallbackGUI::MoveArc_Finish() | ||
265 | { | ||
266 | return MoveArc_Finish_Base(); | ||
267 | } | ||
268 | |||
269 | |||
255 | HRESULT CUpdateCallbackGUI::StartOpenArchive(const wchar_t * /* name */) | 270 | HRESULT CUpdateCallbackGUI::StartOpenArchive(const wchar_t * /* name */) |
256 | { | 271 | { |
257 | return S_OK; | 272 | return S_OK; |
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp index 966f57e..53fed91 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "resource2.h" | 8 | #include "resource2.h" |
9 | #include "resource3.h" | 9 | #include "resource3.h" |
10 | #include "ExtractRes.h" | 10 | #include "ExtractRes.h" |
11 | #include "../FileManager/resourceGui.h" | ||
11 | 12 | ||
12 | #include "UpdateCallbackGUI.h" | 13 | #include "UpdateCallbackGUI.h" |
13 | 14 | ||
@@ -29,7 +30,8 @@ void CUpdateCallbackGUI2::Init() | |||
29 | { | 30 | { |
30 | NumFiles = 0; | 31 | NumFiles = 0; |
31 | 32 | ||
32 | _lang_Removing = LangString(IDS_PROGRESS_REMOVE); | 33 | LangString(IDS_PROGRESS_REMOVE, _lang_Removing); |
34 | LangString(IDS_MOVING, _lang_Moving); | ||
33 | _lang_Ops.Clear(); | 35 | _lang_Ops.Clear(); |
34 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_UpdNotifyLangs); i++) | 36 | for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_UpdNotifyLangs); i++) |
35 | _lang_Ops.Add(LangString(k_UpdNotifyLangs[i])); | 37 | _lang_Ops.Add(LangString(k_UpdNotifyLangs[i])); |
@@ -57,3 +59,72 @@ HRESULT CUpdateCallbackGUI2::ShowAskPasswordDialog() | |||
57 | PasswordIsDefined = true; | 59 | PasswordIsDefined = true; |
58 | return S_OK; | 60 | return S_OK; |
59 | } | 61 | } |
62 | |||
63 | |||
64 | HRESULT CUpdateCallbackGUI2::MoveArc_UpdateStatus() | ||
65 | { | ||
66 | UString s; | ||
67 | s.Add_UInt64(_arcMoving_percents); | ||
68 | s.Add_Char('%'); | ||
69 | |||
70 | const bool totalDefined = (_arcMoving_total != 0 && _arcMoving_total != (UInt64)(Int64)-1); | ||
71 | if (totalDefined || _arcMoving_current != 0) | ||
72 | { | ||
73 | s += " : "; | ||
74 | s.Add_UInt64(_arcMoving_current >> 20); | ||
75 | s += " MiB"; | ||
76 | } | ||
77 | if (totalDefined) | ||
78 | { | ||
79 | s += " / "; | ||
80 | s.Add_UInt64((_arcMoving_total + ((1 << 20) - 1)) >> 20); | ||
81 | s += " MiB"; | ||
82 | } | ||
83 | |||
84 | s += " : "; | ||
85 | s += _lang_Moving; | ||
86 | s += " : "; | ||
87 | // s.Add_Char('\"'); | ||
88 | s += _arcMoving_name1; | ||
89 | // s.Add_Char('\"'); | ||
90 | return ProgressDialog->Sync.Set_Status2(s, _arcMoving_name2, | ||
91 | false); // isDir | ||
92 | } | ||
93 | |||
94 | |||
95 | HRESULT CUpdateCallbackGUI2::MoveArc_Start_Base(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 totalSize, Int32 updateMode) | ||
96 | { | ||
97 | _arcMoving_percents = 0; | ||
98 | _arcMoving_total = totalSize; | ||
99 | _arcMoving_current = 0; | ||
100 | _arcMoving_updateMode = updateMode; | ||
101 | _arcMoving_name1 = srcTempPath; | ||
102 | _arcMoving_name2 = destFinalPath; | ||
103 | return MoveArc_UpdateStatus(); | ||
104 | } | ||
105 | |||
106 | |||
107 | HRESULT CUpdateCallbackGUI2::MoveArc_Progress_Base(UInt64 totalSize, UInt64 currentSize) | ||
108 | { | ||
109 | _arcMoving_total = totalSize; | ||
110 | _arcMoving_current = currentSize; | ||
111 | UInt64 percents = 0; | ||
112 | if (totalSize != 0) | ||
113 | { | ||
114 | if (totalSize < ((UInt64)1 << 57)) | ||
115 | percents = currentSize * 100 / totalSize; | ||
116 | else | ||
117 | percents = currentSize / (totalSize / 100); | ||
118 | } | ||
119 | if (percents == _arcMoving_percents) | ||
120 | return ProgressDialog->Sync.CheckStop(); | ||
121 | // Sleep(300); // for debug | ||
122 | _arcMoving_percents = percents; | ||
123 | return MoveArc_UpdateStatus(); | ||
124 | } | ||
125 | |||
126 | |||
127 | HRESULT CUpdateCallbackGUI2::MoveArc_Finish_Base() | ||
128 | { | ||
129 | return ProgressDialog->Sync.Set_Status2(L"", L"", false); | ||
130 | } | ||
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h index e32b602..56747ff 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h | |||
@@ -7,17 +7,38 @@ | |||
7 | 7 | ||
8 | class CUpdateCallbackGUI2 | 8 | class CUpdateCallbackGUI2 |
9 | { | 9 | { |
10 | UStringVector _lang_Ops; | ||
11 | UString _emptyString; | ||
12 | public: | 10 | public: |
13 | UString Password; | 11 | CProgressDialog *ProgressDialog; |
12 | protected: | ||
13 | UString _arcMoving_name1; | ||
14 | UString _arcMoving_name2; | ||
15 | UInt64 _arcMoving_percents; | ||
16 | UInt64 _arcMoving_total; | ||
17 | UInt64 _arcMoving_current; | ||
18 | Int32 _arcMoving_updateMode; | ||
19 | public: | ||
14 | bool PasswordIsDefined; | 20 | bool PasswordIsDefined; |
15 | bool PasswordWasAsked; | 21 | bool PasswordWasAsked; |
16 | UInt64 NumFiles; | 22 | UInt64 NumFiles; |
17 | 23 | UString Password; | |
24 | protected: | ||
25 | UStringVector _lang_Ops; | ||
18 | UString _lang_Removing; | 26 | UString _lang_Removing; |
27 | UString _lang_Moving; | ||
28 | UString _emptyString; | ||
29 | |||
30 | HRESULT MoveArc_UpdateStatus(); | ||
31 | HRESULT MoveArc_Start_Base(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 /* totalSize */, Int32 updateMode); | ||
32 | HRESULT MoveArc_Progress_Base(UInt64 totalSize, UInt64 currentSize); | ||
33 | HRESULT MoveArc_Finish_Base(); | ||
34 | |||
35 | public: | ||
19 | 36 | ||
20 | CUpdateCallbackGUI2(): | 37 | CUpdateCallbackGUI2(): |
38 | _arcMoving_percents(0), | ||
39 | _arcMoving_total(0), | ||
40 | _arcMoving_current(0), | ||
41 | _arcMoving_updateMode(0), | ||
21 | PasswordIsDefined(false), | 42 | PasswordIsDefined(false), |
22 | PasswordWasAsked(false), | 43 | PasswordWasAsked(false), |
23 | NumFiles(0) | 44 | NumFiles(0) |
@@ -25,8 +46,6 @@ public: | |||
25 | 46 | ||
26 | void Init(); | 47 | void Init(); |
27 | 48 | ||
28 | CProgressDialog *ProgressDialog; | ||
29 | |||
30 | HRESULT SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir); | 49 | HRESULT SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir); |
31 | HRESULT ShowAskPasswordDialog(); | 50 | HRESULT ShowAskPasswordDialog(); |
32 | }; | 51 | }; |
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile index 22ae095..b879a5d 100644 --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile | |||
@@ -141,10 +141,9 @@ C_OBJS = \ | |||
141 | $O\Alloc.obj \ | 141 | $O\Alloc.obj \ |
142 | $O\CpuArch.obj \ | 142 | $O\CpuArch.obj \ |
143 | $O\DllSecur.obj \ | 143 | $O\DllSecur.obj \ |
144 | $O\Sort.obj \ | ||
145 | $O\Threads.obj \ | 144 | $O\Threads.obj \ |
146 | 145 | ||
147 | !include "../../Crc.mak" | 146 | !include "../../Crc.mak" |
148 | 147 | !include "../../Sort.mak" | |
149 | 148 | ||
150 | !include "../../7zip.mak" | 149 | !include "../../7zip.mak" |
diff --git a/CPP/7zip/warn_gcc.mak b/CPP/7zip/warn_gcc.mak index b6ed9c3..6152ab1 100644 --- a/CPP/7zip/warn_gcc.mak +++ b/CPP/7zip/warn_gcc.mak | |||
@@ -11,16 +11,16 @@ CFLAGS_WARN_GCC_4_8 = \ | |||
11 | -Wunused \ | 11 | -Wunused \ |
12 | -Wunused-macros \ | 12 | -Wunused-macros \ |
13 | 13 | ||
14 | CFLAGS_WARN_GCC_6 = $(CFLAGS_WARN_GCC_4_8)\ | 14 | CFLAGS_WARN_GCC_5 = $(CFLAGS_WARN_GCC_4_8)\ |
15 | -Wbool-compare \ | 15 | -Wbool-compare \ |
16 | |||
17 | CFLAGS_WARN_GCC_6 = $(CFLAGS_WARN_GCC_5)\ | ||
16 | -Wduplicated-cond \ | 18 | -Wduplicated-cond \ |
17 | 19 | ||
18 | # -Wno-strict-aliasing | 20 | # -Wno-strict-aliasing |
19 | 21 | ||
20 | CFLAGS_WARN_GCC_9 = $(CFLAGS_WARN_GCC_6)\ | 22 | CFLAGS_WARN_GCC_7 = $(CFLAGS_WARN_GCC_6)\ |
21 | -Waddress-of-packed-member \ | ||
22 | -Wbool-operation \ | 23 | -Wbool-operation \ |
23 | -Wcast-align=strict \ | ||
24 | -Wconversion \ | 24 | -Wconversion \ |
25 | -Wdangling-else \ | 25 | -Wdangling-else \ |
26 | -Wduplicated-branches \ | 26 | -Wduplicated-branches \ |
@@ -28,8 +28,14 @@ CFLAGS_WARN_GCC_9 = $(CFLAGS_WARN_GCC_6)\ | |||
28 | -Wint-in-bool-context \ | 28 | -Wint-in-bool-context \ |
29 | -Wmaybe-uninitialized \ | 29 | -Wmaybe-uninitialized \ |
30 | -Wmisleading-indentation \ | 30 | -Wmisleading-indentation \ |
31 | |||
32 | CFLAGS_WARN_GCC_8 = $(CFLAGS_WARN_GCC_7)\ | ||
33 | -Wcast-align=strict \ | ||
31 | -Wmissing-attributes | 34 | -Wmissing-attributes |
32 | 35 | ||
36 | CFLAGS_WARN_GCC_9 = $(CFLAGS_WARN_GCC_8)\ | ||
37 | -Waddress-of-packed-member \ | ||
38 | |||
33 | # In C: -Wsign-conversion enabled also by -Wconversion | 39 | # In C: -Wsign-conversion enabled also by -Wconversion |
34 | # -Wno-sign-conversion \ | 40 | # -Wno-sign-conversion \ |
35 | 41 | ||
@@ -39,7 +45,10 @@ CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ | |||
39 | 45 | ||
40 | 46 | ||
41 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_4_8) | 47 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_4_8) |
48 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_5) | ||
42 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_6) | 49 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_6) |
50 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_7) | ||
51 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_8) | ||
43 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) | 52 | CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) |
44 | 53 | ||
45 | # CXX_STD_FLAGS = -std=c++11 | 54 | # CXX_STD_FLAGS = -std=c++11 |
diff --git a/CPP/Build.mak b/CPP/Build.mak index afb7ae8..86cc2af 100644 --- a/CPP/Build.mak +++ b/CPP/Build.mak | |||
@@ -111,7 +111,13 @@ CFLAGS = $(CFLAGS) -Zc:forScope | |||
111 | 111 | ||
112 | !IFNDEF UNDER_CE | 112 | !IFNDEF UNDER_CE |
113 | !IF "$(CC)" != "clang-cl" | 113 | !IF "$(CC)" != "clang-cl" |
114 | CFLAGS = $(CFLAGS) -MP4 | 114 | MP_NPROC = 16 |
115 | !IFDEF NUMBER_OF_PROCESSORS | ||
116 | !IF $(NUMBER_OF_PROCESSORS) < $(MP_NPROC) | ||
117 | MP_NPROC = $(NUMBER_OF_PROCESSORS) | ||
118 | !ENDIF | ||
119 | !ENDIF | ||
120 | CFLAGS = $(CFLAGS) -MP$(MP_NPROC) | ||
115 | !ENDIF | 121 | !ENDIF |
116 | !IFNDEF PLATFORM | 122 | !IFNDEF PLATFORM |
117 | # CFLAGS = $(CFLAGS) -arch:IA32 | 123 | # CFLAGS = $(CFLAGS) -arch:IA32 |
diff --git a/CPP/Common/Md5Reg.cpp b/CPP/Common/Md5Reg.cpp new file mode 100644 index 0000000..026fd41 --- /dev/null +++ b/CPP/Common/Md5Reg.cpp | |||
@@ -0,0 +1,44 @@ | |||
1 | // Md5Reg.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../C/Md5.h" | ||
6 | |||
7 | #include "../Common/MyBuffer2.h" | ||
8 | #include "../Common/MyCom.h" | ||
9 | |||
10 | #include "../7zip/Common/RegisterCodec.h" | ||
11 | |||
12 | Z7_CLASS_IMP_COM_1( | ||
13 | CMd5Hasher | ||
14 | , IHasher | ||
15 | ) | ||
16 | CAlignedBuffer1 _buf; | ||
17 | public: | ||
18 | Byte _mtDummy[1 << 7]; | ||
19 | |||
20 | CMd5 *Md5() { return (CMd5 *)(void *)(Byte *)_buf; } | ||
21 | public: | ||
22 | CMd5Hasher(): | ||
23 | _buf(sizeof(CMd5)) | ||
24 | { | ||
25 | Md5_Init(Md5()); | ||
26 | } | ||
27 | }; | ||
28 | |||
29 | Z7_COM7F_IMF2(void, CMd5Hasher::Init()) | ||
30 | { | ||
31 | Md5_Init(Md5()); | ||
32 | } | ||
33 | |||
34 | Z7_COM7F_IMF2(void, CMd5Hasher::Update(const void *data, UInt32 size)) | ||
35 | { | ||
36 | Md5_Update(Md5(), (const Byte *)data, size); | ||
37 | } | ||
38 | |||
39 | Z7_COM7F_IMF2(void, CMd5Hasher::Final(Byte *digest)) | ||
40 | { | ||
41 | Md5_Final(Md5(), digest); | ||
42 | } | ||
43 | |||
44 | REGISTER_HASHER(CMd5Hasher, 0x208, "MD5", MD5_DIGEST_SIZE) | ||
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h index a3cc3c8..7dc21ba 100644 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h | |||
@@ -468,6 +468,19 @@ EXTERN_C_END | |||
468 | Z7_COM_QI_ENTRY(i7) \ | 468 | Z7_COM_QI_ENTRY(i7) \ |
469 | ) | 469 | ) |
470 | 470 | ||
471 | #define Z7_COM_UNKNOWN_IMP_8(i1, i2, i3, i4, i5, i6, i7, i8) \ | ||
472 | Z7_COM_UNKNOWN_IMP_SPEC( \ | ||
473 | Z7_COM_QI_ENTRY_UNKNOWN(i1) \ | ||
474 | Z7_COM_QI_ENTRY(i1) \ | ||
475 | Z7_COM_QI_ENTRY(i2) \ | ||
476 | Z7_COM_QI_ENTRY(i3) \ | ||
477 | Z7_COM_QI_ENTRY(i4) \ | ||
478 | Z7_COM_QI_ENTRY(i5) \ | ||
479 | Z7_COM_QI_ENTRY(i6) \ | ||
480 | Z7_COM_QI_ENTRY(i7) \ | ||
481 | Z7_COM_QI_ENTRY(i8) \ | ||
482 | ) | ||
483 | |||
471 | 484 | ||
472 | #define Z7_IFACES_IMP_UNK_1(i1) \ | 485 | #define Z7_IFACES_IMP_UNK_1(i1) \ |
473 | Z7_COM_UNKNOWN_IMP_1(i1) \ | 486 | Z7_COM_UNKNOWN_IMP_1(i1) \ |
@@ -508,6 +521,16 @@ EXTERN_C_END | |||
508 | Z7_IFACE_COM7_IMP(i5) \ | 521 | Z7_IFACE_COM7_IMP(i5) \ |
509 | Z7_IFACE_COM7_IMP(i6) \ | 522 | Z7_IFACE_COM7_IMP(i6) \ |
510 | 523 | ||
524 | #define Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \ | ||
525 | Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \ | ||
526 | Z7_IFACE_COM7_IMP(i1) \ | ||
527 | Z7_IFACE_COM7_IMP(i2) \ | ||
528 | Z7_IFACE_COM7_IMP(i3) \ | ||
529 | Z7_IFACE_COM7_IMP(i4) \ | ||
530 | Z7_IFACE_COM7_IMP(i5) \ | ||
531 | Z7_IFACE_COM7_IMP(i6) \ | ||
532 | Z7_IFACE_COM7_IMP(i7) \ | ||
533 | |||
511 | 534 | ||
512 | #define Z7_CLASS_IMP_COM_0(c) \ | 535 | #define Z7_CLASS_IMP_COM_0(c) \ |
513 | Z7_class_final(c) : \ | 536 | Z7_class_final(c) : \ |
@@ -574,6 +597,20 @@ EXTERN_C_END | |||
574 | private: | 597 | private: |
575 | 598 | ||
576 | 599 | ||
600 | #define Z7_CLASS_IMP_COM_7(c, i1, i2, i3, i4, i5, i6, i7) \ | ||
601 | Z7_class_final(c) : \ | ||
602 | public i1, \ | ||
603 | public i2, \ | ||
604 | public i3, \ | ||
605 | public i4, \ | ||
606 | public i5, \ | ||
607 | public i6, \ | ||
608 | public i7, \ | ||
609 | public CMyUnknownImp { \ | ||
610 | Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \ | ||
611 | private: | ||
612 | |||
613 | |||
577 | /* | 614 | /* |
578 | #define Z7_CLASS_IMP_NOQIB_0(c) \ | 615 | #define Z7_CLASS_IMP_NOQIB_0(c) \ |
579 | Z7_class_final(c) : \ | 616 | Z7_class_final(c) : \ |
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index b5f7e52..10e2331 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp | |||
@@ -208,35 +208,6 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() | |||
208 | 208 | ||
209 | // ---------- ASCII ---------- | 209 | // ---------- ASCII ---------- |
210 | 210 | ||
211 | bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() | ||
212 | { | ||
213 | const char *s1 = _chars; | ||
214 | for (;;) | ||
215 | { | ||
216 | const char c2 = *s++; | ||
217 | if (c2 == 0) | ||
218 | return true; | ||
219 | const char c1 = *s1++; | ||
220 | if (MyCharLower_Ascii(c1) != | ||
221 | MyCharLower_Ascii(c2)) | ||
222 | return false; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() | ||
227 | { | ||
228 | const wchar_t *s1 = _chars; | ||
229 | for (;;) | ||
230 | { | ||
231 | const char c2 = *s++; | ||
232 | if (c2 == 0) | ||
233 | return true; | ||
234 | const wchar_t c1 = *s1++; | ||
235 | if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) | ||
236 | return false; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | bool StringsAreEqual_Ascii(const char *u, const char *a) throw() | 211 | bool StringsAreEqual_Ascii(const char *u, const char *a) throw() |
241 | { | 212 | { |
242 | for (;;) | 213 | for (;;) |
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index ba9914e..639b874 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h | |||
@@ -429,11 +429,11 @@ public: | |||
429 | // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } | 429 | // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } |
430 | // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } | 430 | // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } |
431 | bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } | 431 | bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } |
432 | bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); | 432 | bool IsPrefixedBy_Ascii_NoCase(const char *s) const { return IsString1PrefixedByString2_NoCase_Ascii(_chars, s); } |
433 | 433 | ||
434 | bool IsAscii() const | 434 | bool IsAscii() const |
435 | { | 435 | { |
436 | unsigned len = Len(); | 436 | const unsigned len = Len(); |
437 | const char *s = _chars; | 437 | const char *s = _chars; |
438 | for (unsigned i = 0; i < len; i++) | 438 | for (unsigned i = 0; i < len; i++) |
439 | if ((unsigned char)s[i] >= 0x80) | 439 | if ((unsigned char)s[i] >= 0x80) |
@@ -727,22 +727,23 @@ public: | |||
727 | // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } | 727 | // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } |
728 | // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } | 728 | // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } |
729 | bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); } | 729 | bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); } |
730 | bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } | ||
730 | bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); } | 731 | bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); } |
731 | bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); | 732 | bool IsPrefixedBy_Ascii_NoCase(const char *s) const { return IsString1PrefixedByString2_NoCase_Ascii(_chars, s); } |
732 | 733 | ||
733 | bool IsAscii() const | 734 | bool IsAscii() const |
734 | { | 735 | { |
735 | unsigned len = Len(); | 736 | const unsigned len = Len(); |
736 | const wchar_t *s = _chars; | 737 | const wchar_t *s = _chars; |
737 | for (unsigned i = 0; i < len; i++) | 738 | for (unsigned i = 0; i < len; i++) |
738 | if (s[i] >= 0x80) | 739 | if ((unsigned)(int)s[i] >= 0x80) |
739 | return false; | 740 | return false; |
740 | return true; | 741 | return true; |
741 | } | 742 | } |
742 | int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } | 743 | int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } |
743 | int Find(wchar_t c, unsigned startIndex) const | 744 | int Find(wchar_t c, unsigned startIndex) const |
744 | { | 745 | { |
745 | int pos = FindCharPosInString(_chars + startIndex, c); | 746 | const int pos = FindCharPosInString(_chars + startIndex, c); |
746 | return pos < 0 ? -1 : (int)startIndex + pos; | 747 | return pos < 0 ? -1 : (int)startIndex + pos; |
747 | } | 748 | } |
748 | 749 | ||
diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp index cc891fc..8364aae 100644 --- a/CPP/Common/MyXml.cpp +++ b/CPP/Common/MyXml.cpp | |||
@@ -24,7 +24,7 @@ static bool IsSpaceChar(char c) | |||
24 | int CXmlItem::FindProp(const char *propName) const throw() | 24 | int CXmlItem::FindProp(const char *propName) const throw() |
25 | { | 25 | { |
26 | FOR_VECTOR (i, Props) | 26 | FOR_VECTOR (i, Props) |
27 | if (Props[i].Name == propName) | 27 | if (Props[i].Name.IsEqualTo(propName)) |
28 | return (int)i; | 28 | return (int)i; |
29 | return -1; | 29 | return -1; |
30 | } | 30 | } |
@@ -39,7 +39,7 @@ AString CXmlItem::GetPropVal(const char *propName) const | |||
39 | 39 | ||
40 | bool CXmlItem::IsTagged(const char *tag) const throw() | 40 | bool CXmlItem::IsTagged(const char *tag) const throw() |
41 | { | 41 | { |
42 | return (IsTag && Name == tag); | 42 | return (IsTag && Name.IsEqualTo(tag)); |
43 | } | 43 | } |
44 | 44 | ||
45 | int CXmlItem::FindSubTag(const char *tag) const throw() | 45 | int CXmlItem::FindSubTag(const char *tag) const throw() |
diff --git a/CPP/Common/Sha3Reg.cpp b/CPP/Common/Sha3Reg.cpp new file mode 100644 index 0000000..cd2e288 --- /dev/null +++ b/CPP/Common/Sha3Reg.cpp | |||
@@ -0,0 +1,76 @@ | |||
1 | // Sha3Reg.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../C/Sha3.h" | ||
6 | |||
7 | #include "../Common/MyBuffer2.h" | ||
8 | #include "../Common/MyCom.h" | ||
9 | |||
10 | #include "../7zip/Common/RegisterCodec.h" | ||
11 | |||
12 | Z7_CLASS_IMP_COM_1( | ||
13 | CSha3Hasher | ||
14 | , IHasher | ||
15 | ) | ||
16 | unsigned _digestSize; | ||
17 | bool _isShake; | ||
18 | CAlignedBuffer1 _buf; | ||
19 | public: | ||
20 | Byte _mtDummy[1 << 7]; | ||
21 | |||
22 | CSha3 *Sha() { return (CSha3 *)(void *)(Byte *)_buf; } | ||
23 | public: | ||
24 | CSha3Hasher(unsigned digestSize, bool isShake, unsigned blockSize): | ||
25 | _digestSize(digestSize), | ||
26 | _isShake(isShake), | ||
27 | _buf(sizeof(CSha3)) | ||
28 | { | ||
29 | CSha3 *p = Sha(); | ||
30 | Sha3_SET_blockSize(p, blockSize) | ||
31 | Sha3_Init(Sha()); | ||
32 | } | ||
33 | }; | ||
34 | |||
35 | Z7_COM7F_IMF2(void, CSha3Hasher::Init()) | ||
36 | { | ||
37 | Sha3_Init(Sha()); | ||
38 | } | ||
39 | |||
40 | Z7_COM7F_IMF2(void, CSha3Hasher::Update(const void *data, UInt32 size)) | ||
41 | { | ||
42 | Sha3_Update(Sha(), (const Byte *)data, size); | ||
43 | } | ||
44 | |||
45 | Z7_COM7F_IMF2(void, CSha3Hasher::Final(Byte *digest)) | ||
46 | { | ||
47 | Sha3_Final(Sha(), digest, _digestSize, _isShake); | ||
48 | } | ||
49 | |||
50 | Z7_COM7F_IMF2(UInt32, CSha3Hasher::GetDigestSize()) | ||
51 | { | ||
52 | return (UInt32)_digestSize; | ||
53 | } | ||
54 | |||
55 | |||
56 | #define REGISTER_SHA3_HASHER_2(cls, id, name, digestSize, isShake, digestSize_for_blockSize) \ | ||
57 | namespace N ## cls { \ | ||
58 | static IHasher *CreateHasherSpec() \ | ||
59 | { return new CSha3Hasher(digestSize / 8, isShake, \ | ||
60 | SHA3_BLOCK_SIZE_FROM_DIGEST_SIZE(digestSize_for_blockSize / 8)); } \ | ||
61 | static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, digestSize / 8 }; \ | ||
62 | struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \ | ||
63 | static REGISTER_HASHER_NAME(cls) g_RegisterHasher; } | ||
64 | |||
65 | #define REGISTER_SHA3_HASHER( cls, id, name, size, isShake) \ | ||
66 | REGISTER_SHA3_HASHER_2(cls, id, name, size, isShake, size) | ||
67 | |||
68 | // REGISTER_SHA3_HASHER (Sha3_224_Hasher, 0x230, "SHA3-224", 224, false) | ||
69 | REGISTER_SHA3_HASHER (Sha3_256_Hasher, 0x231, "SHA3-256", 256, false) | ||
70 | // REGISTER_SHA3_HASHER (Sha3_386_Hasher, 0x232, "SHA3-384", 384, false) | ||
71 | // REGISTER_SHA3_HASHER (Sha3_512_Hasher, 0x233, "SHA3-512", 512, false) | ||
72 | // REGISTER_SHA3_HASHER (Shake128_Hasher, 0x240, "SHAKE128", 128, true) | ||
73 | // REGISTER_SHA3_HASHER (Shake256_Hasher, 0x241, "SHAKE256", 256, true) | ||
74 | // REGISTER_SHA3_HASHER_2 (Shake128_512_Hasher, 0x248, "SHAKE128-256", 256, true, 128) // -1344 (max) | ||
75 | // REGISTER_SHA3_HASHER_2 (Shake256_512_Hasher, 0x249, "SHAKE256-512", 512, true, 256) // -1088 (max) | ||
76 | // Shake supports different digestSize values for same blockSize | ||
diff --git a/CPP/Common/Sha512Prepare.cpp b/CPP/Common/Sha512Prepare.cpp new file mode 100644 index 0000000..e7beff5 --- /dev/null +++ b/CPP/Common/Sha512Prepare.cpp | |||
@@ -0,0 +1,7 @@ | |||
1 | // Sha512Prepare.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../C/Sha512.h" | ||
6 | |||
7 | static struct CSha512Prepare { CSha512Prepare() { Sha512Prepare(); } } g_Sha512Prepare; | ||
diff --git a/CPP/Common/Sha512Reg.cpp b/CPP/Common/Sha512Reg.cpp new file mode 100644 index 0000000..21df6ba --- /dev/null +++ b/CPP/Common/Sha512Reg.cpp | |||
@@ -0,0 +1,83 @@ | |||
1 | // Sha512Reg.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../C/Sha512.h" | ||
6 | |||
7 | #include "../Common/MyBuffer2.h" | ||
8 | #include "../Common/MyCom.h" | ||
9 | |||
10 | #include "../7zip/Common/RegisterCodec.h" | ||
11 | |||
12 | Z7_CLASS_IMP_COM_2( | ||
13 | CSha512Hasher | ||
14 | , IHasher | ||
15 | , ICompressSetCoderProperties | ||
16 | ) | ||
17 | unsigned _digestSize; | ||
18 | CAlignedBuffer1 _buf; | ||
19 | public: | ||
20 | Byte _mtDummy[1 << 7]; | ||
21 | |||
22 | CSha512 *Sha() { return (CSha512 *)(void *)(Byte *)_buf; } | ||
23 | public: | ||
24 | CSha512Hasher(unsigned digestSize): | ||
25 | _digestSize(digestSize), | ||
26 | _buf(sizeof(CSha512)) | ||
27 | { | ||
28 | Sha512_SetFunction(Sha(), 0); | ||
29 | Sha512_InitState(Sha(), _digestSize); | ||
30 | } | ||
31 | }; | ||
32 | |||
33 | Z7_COM7F_IMF2(void, CSha512Hasher::Init()) | ||
34 | { | ||
35 | Sha512_InitState(Sha(), _digestSize); | ||
36 | } | ||
37 | |||
38 | Z7_COM7F_IMF2(void, CSha512Hasher::Update(const void *data, UInt32 size)) | ||
39 | { | ||
40 | Sha512_Update(Sha(), (const Byte *)data, size); | ||
41 | } | ||
42 | |||
43 | Z7_COM7F_IMF2(void, CSha512Hasher::Final(Byte *digest)) | ||
44 | { | ||
45 | Sha512_Final(Sha(), digest, _digestSize); | ||
46 | } | ||
47 | |||
48 | Z7_COM7F_IMF2(UInt32, CSha512Hasher::GetDigestSize()) | ||
49 | { | ||
50 | return (UInt32)_digestSize; | ||
51 | } | ||
52 | |||
53 | Z7_COM7F_IMF(CSha512Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)) | ||
54 | { | ||
55 | unsigned algo = 0; | ||
56 | for (UInt32 i = 0; i < numProps; i++) | ||
57 | { | ||
58 | if (propIDs[i] == NCoderPropID::kDefaultProp) | ||
59 | { | ||
60 | const PROPVARIANT &prop = coderProps[i]; | ||
61 | if (prop.vt != VT_UI4) | ||
62 | return E_INVALIDARG; | ||
63 | if (prop.ulVal > 2) | ||
64 | return E_NOTIMPL; | ||
65 | algo = (unsigned)prop.ulVal; | ||
66 | } | ||
67 | } | ||
68 | if (!Sha512_SetFunction(Sha(), algo)) | ||
69 | return E_NOTIMPL; | ||
70 | return S_OK; | ||
71 | } | ||
72 | |||
73 | #define REGISTER_SHA512_HASHER(cls, id, name, size) \ | ||
74 | namespace N ## cls { \ | ||
75 | static IHasher *CreateHasherSpec() { return new CSha512Hasher(size); } \ | ||
76 | static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \ | ||
77 | struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \ | ||
78 | static REGISTER_HASHER_NAME(cls) g_RegisterHasher; } | ||
79 | |||
80 | // REGISTER_SHA512_HASHER (Sha512_224_Hasher, 0x220, "SHA512-224", SHA512_224_DIGEST_SIZE) | ||
81 | // REGISTER_SHA512_HASHER (Sha512_256_Hasher, 0x221, "SHA512-256", SHA512_256_DIGEST_SIZE) | ||
82 | REGISTER_SHA512_HASHER (Sha384Hasher, 0x222, "SHA384", SHA512_384_DIGEST_SIZE) | ||
83 | REGISTER_SHA512_HASHER (Sha512Hasher, 0x223, "SHA512", SHA512_DIGEST_SIZE) | ||
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index 798cbd9..b561a89 100644 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp | |||
@@ -255,7 +255,8 @@ ForDir nonrec [0, M) same as ForBoth-File | |||
255 | 255 | ||
256 | bool CItem::AreAllAllowed() const | 256 | bool CItem::AreAllAllowed() const |
257 | { | 257 | { |
258 | return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*"; | 258 | return ForFile && ForDir && WildcardMatching |
259 | && PathParts.Size() == 1 && PathParts.Front().IsEqualTo("*"); | ||
259 | } | 260 | } |
260 | 261 | ||
261 | bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const | 262 | bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const |
@@ -542,7 +543,7 @@ unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) | |||
542 | { | 543 | { |
543 | if (pathParts.Size() < 4 | 544 | if (pathParts.Size() < 4 |
544 | || !pathParts[1].IsEmpty() | 545 | || !pathParts[1].IsEmpty() |
545 | || pathParts[2] != L"?") | 546 | || !pathParts[2].IsEqualTo("?")) |
546 | return 0; | 547 | return 0; |
547 | testIndex = 3; | 548 | testIndex = 3; |
548 | } | 549 | } |
@@ -574,11 +575,11 @@ static unsigned GetNumPrefixParts(const UStringVector &pathParts) | |||
574 | return 1; | 575 | return 1; |
575 | if (pathParts.Size() == 2) | 576 | if (pathParts.Size() == 2) |
576 | return 2; | 577 | return 2; |
577 | if (pathParts[2] == L".") | 578 | if (pathParts[2].IsEqualTo(".")) |
578 | return 3; | 579 | return 3; |
579 | 580 | ||
580 | unsigned networkParts = 2; | 581 | unsigned networkParts = 2; |
581 | if (pathParts[2] == L"?") | 582 | if (pathParts[2].IsEqualTo("?")) |
582 | { | 583 | { |
583 | if (pathParts.Size() == 3) | 584 | if (pathParts.Size() == 3) |
584 | return 3; | 585 | return 3; |
@@ -642,7 +643,7 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat | |||
642 | if (pathParts.Size() >= 3 | 643 | if (pathParts.Size() >= 3 |
643 | && pathParts[0].IsEmpty() | 644 | && pathParts[0].IsEmpty() |
644 | && pathParts[1].IsEmpty() | 645 | && pathParts[1].IsEmpty() |
645 | && pathParts[2] == L"?") | 646 | && pathParts[2].IsEqualTo("?")) |
646 | ignoreWildcardIndex = 2; | 647 | ignoreWildcardIndex = 2; |
647 | // #endif | 648 | // #endif |
648 | 649 | ||
@@ -665,7 +666,7 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat | |||
665 | for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) | 666 | for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) |
666 | { | 667 | { |
667 | const UString &part = pathParts[i]; | 668 | const UString &part = pathParts[i]; |
668 | if (part == L".." || part == L".") | 669 | if (part.IsEqualTo("..") || part.IsEqualTo(".")) |
669 | dotsIndex = (int)i; | 670 | dotsIndex = (int)i; |
670 | } | 671 | } |
671 | 672 | ||
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index dfeed82..ad0d8c9 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp | |||
@@ -15,8 +15,9 @@ | |||
15 | #include <sys/stat.h> | 15 | #include <sys/stat.h> |
16 | #include <sys/types.h> | 16 | #include <sys/types.h> |
17 | 17 | ||
18 | #include "../Common/StringConvert.h" | ||
19 | #include "../Common/C_FileIO.h" | 18 | #include "../Common/C_FileIO.h" |
19 | #include "../Common/MyBuffer2.h" | ||
20 | #include "../Common/StringConvert.h" | ||
20 | #endif | 21 | #endif |
21 | 22 | ||
22 | #include "FileDir.h" | 23 | #include "FileDir.h" |
@@ -123,7 +124,7 @@ bool GetSystemDir(FString &path) | |||
123 | #endif // UNDER_CE | 124 | #endif // UNDER_CE |
124 | 125 | ||
125 | 126 | ||
126 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | 127 | static bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD dwFlagsAndAttributes) |
127 | { | 128 | { |
128 | #ifndef _UNICODE | 129 | #ifndef _UNICODE |
129 | if (!g_IsNT) | 130 | if (!g_IsNT) |
@@ -136,14 +137,14 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF | |||
136 | HANDLE hDir = INVALID_HANDLE_VALUE; | 137 | HANDLE hDir = INVALID_HANDLE_VALUE; |
137 | IF_USE_MAIN_PATH | 138 | IF_USE_MAIN_PATH |
138 | hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | 139 | hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, |
139 | NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 140 | NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); |
140 | #ifdef Z7_LONG_PATH | 141 | #ifdef Z7_LONG_PATH |
141 | if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) | 142 | if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) |
142 | { | 143 | { |
143 | UString superPath; | 144 | UString superPath; |
144 | if (GetSuperPath(path, superPath, USE_MAIN_PATH)) | 145 | if (GetSuperPath(path, superPath, USE_MAIN_PATH)) |
145 | hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | 146 | hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, |
146 | NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 147 | NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); |
147 | } | 148 | } |
148 | #endif | 149 | #endif |
149 | 150 | ||
@@ -156,6 +157,15 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF | |||
156 | return res; | 157 | return res; |
157 | } | 158 | } |
158 | 159 | ||
160 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | ||
161 | { | ||
162 | return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS); | ||
163 | } | ||
164 | |||
165 | bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | ||
166 | { | ||
167 | return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT); | ||
168 | } | ||
159 | 169 | ||
160 | 170 | ||
161 | bool SetFileAttrib(CFSTR path, DWORD attrib) | 171 | bool SetFileAttrib(CFSTR path, DWORD attrib) |
@@ -222,6 +232,8 @@ bool RemoveDir(CFSTR path) | |||
222 | } | 232 | } |
223 | 233 | ||
224 | 234 | ||
235 | // When moving a directory, oldFile and newFile must be on the same drive. | ||
236 | |||
225 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 237 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) |
226 | { | 238 | { |
227 | #ifndef _UNICODE | 239 | #ifndef _UNICODE |
@@ -250,6 +262,59 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
250 | return false; | 262 | return false; |
251 | } | 263 | } |
252 | 264 | ||
265 | #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 | ||
266 | static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress( | ||
267 | LARGE_INTEGER TotalFileSize, // file size | ||
268 | LARGE_INTEGER TotalBytesTransferred, // bytes transferred | ||
269 | LARGE_INTEGER /* StreamSize */, // bytes in stream | ||
270 | LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream | ||
271 | DWORD /* dwStreamNumber */, // current stream | ||
272 | DWORD /* dwCallbackReason */, // callback reason | ||
273 | HANDLE /* hSourceFile */, // handle to source file | ||
274 | HANDLE /* hDestinationFile */, // handle to destination file | ||
275 | LPVOID lpData // from CopyFileEx | ||
276 | ) | ||
277 | { | ||
278 | return ((ICopyFileProgress *)lpData)->CopyFileProgress( | ||
279 | (UInt64)TotalFileSize.QuadPart, | ||
280 | (UInt64)TotalBytesTransferred.QuadPart); | ||
281 | } | ||
282 | #endif | ||
283 | |||
284 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, | ||
285 | ICopyFileProgress *progress) | ||
286 | { | ||
287 | #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 | ||
288 | #ifndef _UNICODE | ||
289 | if (g_IsNT) | ||
290 | #endif | ||
291 | if (progress) | ||
292 | { | ||
293 | IF_USE_MAIN_PATH_2(oldFile, newFile) | ||
294 | { | ||
295 | if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), | ||
296 | CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)) | ||
297 | return true; | ||
298 | if (::GetLastError() == ERROR_REQUEST_ABORTED) | ||
299 | return false; | ||
300 | } | ||
301 | #ifdef Z7_LONG_PATH | ||
302 | if (USE_SUPER_PATH_2) | ||
303 | { | ||
304 | UString d1, d2; | ||
305 | if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) | ||
306 | return BOOLToBool(::MoveFileWithProgressW(d1, d2, | ||
307 | CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)); | ||
308 | } | ||
309 | #endif | ||
310 | return false; | ||
311 | } | ||
312 | #else | ||
313 | UNUSED_VAR(progress) | ||
314 | #endif | ||
315 | return MyMoveFile(oldFile, newFile); | ||
316 | } | ||
317 | |||
253 | #ifndef UNDER_CE | 318 | #ifndef UNDER_CE |
254 | #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 | 319 | #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 |
255 | #define Z7_USE_DYN_CreateHardLink | 320 | #define Z7_USE_DYN_CreateHardLink |
@@ -595,6 +660,35 @@ bool RemoveDirWithSubItems(const FString &path) | |||
595 | return RemoveDir(path); | 660 | return RemoveDir(path); |
596 | } | 661 | } |
597 | 662 | ||
663 | bool RemoveDirAlways_if_Empty(const FString &path) | ||
664 | { | ||
665 | const DWORD attrib = NFind::GetFileAttrib(path); | ||
666 | if (attrib != INVALID_FILE_ATTRIBUTES | ||
667 | && (attrib & FILE_ATTRIBUTE_READONLY)) | ||
668 | { | ||
669 | bool need_ClearAttrib = true; | ||
670 | if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0) | ||
671 | { | ||
672 | FString s (path); | ||
673 | s.Add_PathSepar(); | ||
674 | NFind::CEnumerator enumerator; | ||
675 | enumerator.SetDirPrefix(s); | ||
676 | NFind::CDirEntry fi; | ||
677 | if (enumerator.Next(fi)) | ||
678 | { | ||
679 | // we don't want to change attributes, if there are files | ||
680 | // in directory, because RemoveDir(path) will fail. | ||
681 | need_ClearAttrib = false; | ||
682 | // SetLastError(ERROR_DIR_NOT_EMPTY); | ||
683 | // return false; | ||
684 | } | ||
685 | } | ||
686 | if (need_ClearAttrib) | ||
687 | SetFileAttrib(path, 0); // we clear read-only attrib to remove read-only dir | ||
688 | } | ||
689 | return RemoveDir(path); | ||
690 | } | ||
691 | |||
598 | #endif // _WIN32 | 692 | #endif // _WIN32 |
599 | 693 | ||
600 | #ifdef UNDER_CE | 694 | #ifdef UNDER_CE |
@@ -878,9 +972,9 @@ bool CTempFile::Remove() | |||
878 | return !_mustBeDeleted; | 972 | return !_mustBeDeleted; |
879 | } | 973 | } |
880 | 974 | ||
881 | bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) | 975 | bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore, |
976 | ICopyFileProgress *progress) | ||
882 | { | 977 | { |
883 | // DWORD attrib = 0; | ||
884 | if (deleteDestBefore) | 978 | if (deleteDestBefore) |
885 | { | 979 | { |
886 | if (NFind::DoesFileExist_Raw(name)) | 980 | if (NFind::DoesFileExist_Raw(name)) |
@@ -891,8 +985,8 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) | |||
891 | } | 985 | } |
892 | } | 986 | } |
893 | DisableDeleting(); | 987 | DisableDeleting(); |
894 | return MyMoveFile(_path, name); | 988 | // if (!progress) return MyMoveFile(_path, name); |
895 | 989 | return MyMoveFile_with_Progress(_path, name, progress); | |
896 | /* | 990 | /* |
897 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) | 991 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) |
898 | { | 992 | { |
@@ -941,34 +1035,59 @@ bool RemoveDir(CFSTR path) | |||
941 | } | 1035 | } |
942 | 1036 | ||
943 | 1037 | ||
944 | static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) | 1038 | static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress) |
945 | { | 1039 | { |
946 | NWindows::NFile::NIO::COutFile outFile; | ||
947 | if (!outFile.Create_NEW(newFile)) | ||
948 | return FALSE; | ||
949 | |||
950 | NWindows::NFile::NIO::CInFile inFile; | ||
951 | if (!inFile.Open(oldFile)) | ||
952 | return FALSE; | ||
953 | |||
954 | char buf[1 << 14]; | ||
955 | |||
956 | for (;;) | ||
957 | { | 1040 | { |
958 | const ssize_t num = inFile.read_part(buf, sizeof(buf)); | 1041 | NIO::COutFile outFile; |
959 | if (num == 0) | 1042 | if (!outFile.Create_NEW(newFile)) |
960 | return TRUE; | ||
961 | if (num < 0) | ||
962 | return FALSE; | 1043 | return FALSE; |
963 | size_t processed; | 1044 | NIO::CInFile inFile; |
964 | const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); | 1045 | if (!inFile.Open(oldFile)) |
965 | if (num2 != num || processed != (size_t)num) | ||
966 | return FALSE; | 1046 | return FALSE; |
1047 | |||
1048 | const size_t k_BufSize = 1 << 16; | ||
1049 | CAlignedBuffer1 buf(k_BufSize); | ||
1050 | |||
1051 | UInt64 length = 0; | ||
1052 | if (progress && !inFile.GetLength(length)) | ||
1053 | length = 0; | ||
1054 | UInt64 prev = 0; | ||
1055 | UInt64 cur = 0; | ||
1056 | for (;;) | ||
1057 | { | ||
1058 | const ssize_t num = inFile.read_part(buf, k_BufSize); | ||
1059 | if (num == 0) | ||
1060 | return TRUE; | ||
1061 | if (num < 0) | ||
1062 | break; | ||
1063 | size_t processed; | ||
1064 | const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); | ||
1065 | if (num2 != num || processed != (size_t)num) | ||
1066 | break; | ||
1067 | cur += (size_t)num2; | ||
1068 | if (progress && cur - prev >= (1u << 20)) | ||
1069 | { | ||
1070 | prev = cur; | ||
1071 | if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE) | ||
1072 | { | ||
1073 | errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED | ||
1074 | break; | ||
1075 | } | ||
1076 | } | ||
1077 | } | ||
967 | } | 1078 | } |
1079 | // There is file IO error or process was interrupted by user. | ||
1080 | // We close output file and delete it. | ||
1081 | // DeleteFileAlways doesn't change errno (if successed), but we restore errno. | ||
1082 | const int errno_save = errno; | ||
1083 | DeleteFileAlways(newFile); | ||
1084 | errno = errno_save; | ||
1085 | return FALSE; | ||
968 | } | 1086 | } |
969 | 1087 | ||
970 | 1088 | ||
971 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 1089 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, |
1090 | ICopyFileProgress *progress) | ||
972 | { | 1091 | { |
973 | int res = rename(oldFile, newFile); | 1092 | int res = rename(oldFile, newFile); |
974 | if (res == 0) | 1093 | if (res == 0) |
@@ -976,7 +1095,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
976 | if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) | 1095 | if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) |
977 | return false; | 1096 | return false; |
978 | 1097 | ||
979 | if (My_CopyFile(oldFile, newFile) == FALSE) | 1098 | if (My_CopyFile(oldFile, newFile, progress) == FALSE) |
980 | return false; | 1099 | return false; |
981 | 1100 | ||
982 | struct stat info_file; | 1101 | struct stat info_file; |
@@ -990,6 +1109,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
990 | return (unlink(oldFile) == 0); | 1109 | return (unlink(oldFile) == 0); |
991 | } | 1110 | } |
992 | 1111 | ||
1112 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | ||
1113 | { | ||
1114 | return MyMoveFile_with_Progress(oldFile, newFile, NULL); | ||
1115 | } | ||
1116 | |||
993 | 1117 | ||
994 | bool CreateDir(CFSTR path) | 1118 | bool CreateDir(CFSTR path) |
995 | { | 1119 | { |
@@ -1058,17 +1182,15 @@ bool GetCurrentDir(FString &path) | |||
1058 | 1182 | ||
1059 | 1183 | ||
1060 | 1184 | ||
1061 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | 1185 | static bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, const int flags) |
1062 | { | 1186 | { |
1063 | // need testing | 1187 | // need testing |
1064 | /* | 1188 | /* |
1065 | struct utimbuf buf; | 1189 | struct utimbuf buf; |
1066 | struct stat st; | 1190 | struct stat st; |
1067 | UNUSED_VAR(cTime) | 1191 | UNUSED_VAR(cTime) |
1068 | |||
1069 | printf("\nstat = %s\n", path); | 1192 | printf("\nstat = %s\n", path); |
1070 | int ret = stat(path, &st); | 1193 | int ret = stat(path, &st); |
1071 | |||
1072 | if (ret == 0) | 1194 | if (ret == 0) |
1073 | { | 1195 | { |
1074 | buf.actime = st.st_atime; | 1196 | buf.actime = st.st_atime; |
@@ -1080,47 +1202,42 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF | |||
1080 | buf.actime = cur_time; | 1202 | buf.actime = cur_time; |
1081 | buf.modtime = cur_time; | 1203 | buf.modtime = cur_time; |
1082 | } | 1204 | } |
1083 | |||
1084 | if (aTime) | 1205 | if (aTime) |
1085 | { | 1206 | { |
1086 | UInt32 ut; | 1207 | UInt32 ut; |
1087 | if (NTime::FileTimeToUnixTime(*aTime, ut)) | 1208 | if (NTime::FileTimeToUnixTime(*aTime, ut)) |
1088 | buf.actime = ut; | 1209 | buf.actime = ut; |
1089 | } | 1210 | } |
1090 | |||
1091 | if (mTime) | 1211 | if (mTime) |
1092 | { | 1212 | { |
1093 | UInt32 ut; | 1213 | UInt32 ut; |
1094 | if (NTime::FileTimeToUnixTime(*mTime, ut)) | 1214 | if (NTime::FileTimeToUnixTime(*mTime, ut)) |
1095 | buf.modtime = ut; | 1215 | buf.modtime = ut; |
1096 | } | 1216 | } |
1097 | |||
1098 | return utime(path, &buf) == 0; | 1217 | return utime(path, &buf) == 0; |
1099 | */ | 1218 | */ |
1100 | 1219 | ||
1101 | // if (!aTime && !mTime) return true; | 1220 | // if (!aTime && !mTime) return true; |
1102 | |||
1103 | struct timespec times[2]; | 1221 | struct timespec times[2]; |
1104 | UNUSED_VAR(cTime) | 1222 | UNUSED_VAR(cTime) |
1105 | |||
1106 | bool needChange; | 1223 | bool needChange; |
1107 | needChange = FiTime_To_timespec(aTime, times[0]); | 1224 | needChange = FiTime_To_timespec(aTime, times[0]); |
1108 | needChange |= FiTime_To_timespec(mTime, times[1]); | 1225 | needChange |= FiTime_To_timespec(mTime, times[1]); |
1109 | 1226 | // if (mTime) { printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); } | |
1110 | /* | ||
1111 | if (mTime) | ||
1112 | { | ||
1113 | printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); | ||
1114 | } | ||
1115 | */ | ||
1116 | |||
1117 | if (!needChange) | 1227 | if (!needChange) |
1118 | return true; | 1228 | return true; |
1119 | const int flags = 0; // follow link | ||
1120 | // = AT_SYMLINK_NOFOLLOW; // don't follow link | ||
1121 | return utimensat(AT_FDCWD, path, times, flags) == 0; | 1229 | return utimensat(AT_FDCWD, path, times, flags) == 0; |
1122 | } | 1230 | } |
1123 | 1231 | ||
1232 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | ||
1233 | { | ||
1234 | return SetFileTime_Base(path, cTime, aTime, mTime, 0); // (flags = 0) means follow_link | ||
1235 | } | ||
1236 | |||
1237 | bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) | ||
1238 | { | ||
1239 | return SetFileTime_Base(path, cTime, aTime, mTime, AT_SYMLINK_NOFOLLOW); | ||
1240 | } | ||
1124 | 1241 | ||
1125 | 1242 | ||
1126 | struct C_umask | 1243 | struct C_umask |
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 573ffa2..9ba98fc 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h | |||
@@ -18,9 +18,20 @@ bool GetSystemDir(FString &path); | |||
18 | WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file | 18 | WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file |
19 | but linux : allows unix time = 0 in filesystem | 19 | but linux : allows unix time = 0 in filesystem |
20 | */ | 20 | */ |
21 | 21 | /* | |
22 | SetDirTime() can be used to set time for file or for dir. | ||
23 | If path is symbolic link, SetDirTime() will follow symbolic link, | ||
24 | and it will set timestamps of symbolic link's target file or dir. | ||
25 | */ | ||
22 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); | 26 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); |
23 | 27 | ||
28 | /* | ||
29 | SetLinkFileTime() doesn't follow symbolic link, | ||
30 | and it sets timestamps for symbolic link file itself. | ||
31 | If (path) is not symbolic link, it still can work (at least in some new OS versions). | ||
32 | */ | ||
33 | bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); | ||
34 | |||
24 | 35 | ||
25 | #ifdef _WIN32 | 36 | #ifdef _WIN32 |
26 | 37 | ||
@@ -41,7 +52,26 @@ int my_chown(CFSTR path, uid_t owner, gid_t group); | |||
41 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); | 52 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); |
42 | 53 | ||
43 | 54 | ||
55 | #ifndef _WIN32 | ||
56 | #define PROGRESS_CONTINUE 0 | ||
57 | #define PROGRESS_CANCEL 1 | ||
58 | // #define PROGRESS_STOP 2 | ||
59 | // #define PROGRESS_QUIET 3 | ||
60 | #endif | ||
61 | Z7_PURE_INTERFACES_BEGIN | ||
62 | DECLARE_INTERFACE(ICopyFileProgress) | ||
63 | { | ||
64 | // in: total, current: include all/processed alt streams. | ||
65 | // it returns PROGRESS_CONTINUE or PROGRESS_CANCEL. | ||
66 | virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) = 0; | ||
67 | }; | ||
68 | Z7_PURE_INTERFACES_END | ||
69 | |||
44 | bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); | 70 | bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); |
71 | // (progress == NULL) is allowed | ||
72 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, | ||
73 | ICopyFileProgress *progress); | ||
74 | |||
45 | 75 | ||
46 | #ifndef UNDER_CE | 76 | #ifndef UNDER_CE |
47 | bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); | 77 | bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); |
@@ -59,6 +89,11 @@ bool CreateComplexDir(CFSTR path); | |||
59 | 89 | ||
60 | bool DeleteFileAlways(CFSTR name); | 90 | bool DeleteFileAlways(CFSTR name); |
61 | bool RemoveDirWithSubItems(const FString &path); | 91 | bool RemoveDirWithSubItems(const FString &path); |
92 | #ifdef _WIN32 | ||
93 | bool RemoveDirAlways_if_Empty(const FString &path); | ||
94 | #else | ||
95 | #define RemoveDirAlways_if_Empty RemoveDir | ||
96 | #endif | ||
62 | 97 | ||
63 | bool MyGetFullPathName(CFSTR path, FString &resFullPath); | 98 | bool MyGetFullPathName(CFSTR path, FString &resFullPath); |
64 | bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); | 99 | bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); |
@@ -87,7 +122,9 @@ public: | |||
87 | bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix | 122 | bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix |
88 | bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); | 123 | bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); |
89 | bool Remove(); | 124 | bool Remove(); |
90 | bool MoveTo(CFSTR name, bool deleteDestBefore); | 125 | // bool MoveTo(CFSTR name, bool deleteDestBefore); |
126 | bool MoveTo(CFSTR name, bool deleteDestBefore, | ||
127 | ICopyFileProgress *progress); | ||
91 | }; | 128 | }; |
92 | 129 | ||
93 | 130 | ||
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index ca387f6..64075ab 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp | |||
@@ -731,7 +731,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink) | |||
731 | bool isOK = false; | 731 | bool isOK = false; |
732 | if (finder.FindFirst(s, *this)) | 732 | if (finder.FindFirst(s, *this)) |
733 | { | 733 | { |
734 | if (Name == FTEXT(".")) | 734 | if (Name.IsEqualTo(".")) |
735 | { | 735 | { |
736 | Name = path + prefixSize; | 736 | Name = path + prefixSize; |
737 | return true; | 737 | return true; |
@@ -769,6 +769,13 @@ bool CFileInfo::Find(CFSTR path, bool followLink) | |||
769 | 769 | ||
770 | // return FollowReparse(path, IsDir()); | 770 | // return FollowReparse(path, IsDir()); |
771 | return Fill_From_ByHandleFileInfo(path); | 771 | return Fill_From_ByHandleFileInfo(path); |
772 | /* | ||
773 | // Fill_From_ByHandleFileInfo returns false (with Access Denied error), | ||
774 | // if there is reparse link file (not directory reparse item). | ||
775 | if (Fill_From_ByHandleFileInfo(path)) | ||
776 | return true; | ||
777 | return HasReparsePoint(); | ||
778 | */ | ||
772 | } | 779 | } |
773 | 780 | ||
774 | bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path) | 781 | bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path) |
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index 6ba40eb..26edef4 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h | |||
@@ -11,8 +11,7 @@ | |||
11 | 11 | ||
12 | #define Z7_WIN_SYMLINK_FLAG_RELATIVE 1 | 12 | #define Z7_WIN_SYMLINK_FLAG_RELATIVE 1 |
13 | 13 | ||
14 | // what the meaning of that FLAG or field (2)? | 14 | #define Z7_WIN_LX_SYMLINK_VERSION_2 2 |
15 | #define Z7_WIN_LX_SYMLINK_FLAG 2 | ||
16 | 15 | ||
17 | #ifdef _WIN32 | 16 | #ifdef _WIN32 |
18 | 17 | ||
@@ -44,7 +43,33 @@ namespace NWindows { | |||
44 | namespace NFile { | 43 | namespace NFile { |
45 | 44 | ||
46 | #if defined(_WIN32) && !defined(UNDER_CE) | 45 | #if defined(_WIN32) && !defined(UNDER_CE) |
47 | bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL); | 46 | /* |
47 | in: (CByteBuffer &dest) is empty | ||
48 | in: (path) uses Windows path separator (\). | ||
49 | out: (path) uses Linux path separator (/). | ||
50 | if (isAbsPath == true), then "c:\\" prefix is replaced to "/mnt/c/" prefix | ||
51 | */ | ||
52 | void Convert_WinPath_to_WslLinuxPath(FString &path, bool convertDrivePath); | ||
53 | // (path) must use Linux path separator (/). | ||
54 | void FillLinkData_WslLink(CByteBuffer &dest, const wchar_t *path); | ||
55 | |||
56 | /* | ||
57 | in: (CByteBuffer &dest) is empty | ||
58 | if (isSymLink == false) : MOUNT_POINT : (path) must be absolute. | ||
59 | if (isSymLink == true) : SYMLINK : Windows | ||
60 | (path) must use Windows path separator (\). | ||
61 | (path) must be without link "\\??\\" prefix. | ||
62 | link "\\??\\" prefix will be added inside FillLinkData(), if path is absolute. | ||
63 | */ | ||
64 | void FillLinkData_WinLink(CByteBuffer &dest, const wchar_t *path, bool isSymLink); | ||
65 | // in: (CByteBuffer &dest) is empty | ||
66 | inline void FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) | ||
67 | { | ||
68 | if (isWSL) | ||
69 | FillLinkData_WslLink(dest, path); | ||
70 | else | ||
71 | FillLinkData_WinLink(dest, path, isSymLink); | ||
72 | } | ||
48 | #endif | 73 | #endif |
49 | 74 | ||
50 | struct CReparseShortInfo | 75 | struct CReparseShortInfo |
@@ -61,7 +86,6 @@ struct CReparseAttr | |||
61 | UInt32 Flags; | 86 | UInt32 Flags; |
62 | UString SubsName; | 87 | UString SubsName; |
63 | UString PrintName; | 88 | UString PrintName; |
64 | |||
65 | AString WslName; | 89 | AString WslName; |
66 | 90 | ||
67 | bool HeaderError; | 91 | bool HeaderError; |
@@ -71,8 +95,7 @@ struct CReparseAttr | |||
71 | 95 | ||
72 | CReparseAttr(): Tag(0), Flags(0) {} | 96 | CReparseAttr(): Tag(0), Flags(0) {} |
73 | 97 | ||
74 | // Parse() | 98 | // returns (true) and (ErrorCode = 0), if (it's correct known link) |
75 | // returns (true) and (ErrorCode = 0), if (it'a correct known link) | ||
76 | // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag | 99 | // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag |
77 | bool Parse(const Byte *p, size_t size); | 100 | bool Parse(const Byte *p, size_t size); |
78 | 101 | ||
@@ -80,18 +103,14 @@ struct CReparseAttr | |||
80 | bool IsSymLink_Win() const { return Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK; } | 103 | bool IsSymLink_Win() const { return Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK; } |
81 | bool IsSymLink_WSL() const { return Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK; } | 104 | bool IsSymLink_WSL() const { return Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK; } |
82 | 105 | ||
106 | // note: "/dir1/path" is marked as relative. | ||
83 | bool IsRelative_Win() const { return Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE; } | 107 | bool IsRelative_Win() const { return Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE; } |
84 | 108 | ||
85 | bool IsRelative_WSL() const | 109 | bool IsRelative_WSL() const |
86 | { | 110 | { |
87 | if (WslName.IsEmpty()) | 111 | return WslName[0] != '/'; // WSL uses unix path separator |
88 | return true; | ||
89 | char c = WslName[0]; | ||
90 | return !IS_PATH_SEPAR(c); | ||
91 | } | 112 | } |
92 | 113 | ||
93 | // bool IsVolume() const; | ||
94 | |||
95 | bool IsOkNamePair() const; | 114 | bool IsOkNamePair() const; |
96 | UString GetPath() const; | 115 | UString GetPath() const; |
97 | }; | 116 | }; |
diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp index bb380ec..2883c82 100644 --- a/CPP/Windows/FileLink.cpp +++ b/CPP/Windows/FileLink.cpp | |||
@@ -39,12 +39,24 @@ namespace NFile { | |||
39 | using namespace NName; | 39 | using namespace NName; |
40 | 40 | ||
41 | /* | 41 | /* |
42 | Win10 Junctions/SymLinks: | ||
43 | - (/) slash doesn't work as path separator | ||
44 | - Win10 preinstalled junctions don't use tail backslash, but tail backslashes also work. | ||
45 | - double backslash works only after drive prefix "c:\\dir1\dir2\", | ||
46 | and doesn't work in another places. | ||
47 | - absolute path without \??\ prefix doesn't work | ||
48 | - absolute path "c:" doesn't work | ||
49 | */ | ||
50 | |||
51 | /* | ||
42 | Reparse Points (Junctions and Symbolic Links): | 52 | Reparse Points (Junctions and Symbolic Links): |
43 | struct | 53 | struct |
44 | { | 54 | { |
45 | UInt32 Tag; | 55 | UInt32 Tag; |
46 | UInt16 Size; // not including starting 8 bytes | 56 | UInt16 Size; // not including starting 8 bytes |
47 | UInt16 Reserved; // = 0 | 57 | UInt16 Reserved; // = 0, DOCs: // Length, in bytes, of the unparsed portion of |
58 | // the file name pointed to by the FileName member of the associated file object. | ||
59 | // This member is only valid for create operations when the I/O fails with STATUS_REPARSE. | ||
48 | 60 | ||
49 | UInt16 SubstituteOffset; // offset in bytes from start of namesChars | 61 | UInt16 SubstituteOffset; // offset in bytes from start of namesChars |
50 | UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL | 62 | UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL |
@@ -68,6 +80,16 @@ using namespace NName; | |||
68 | 2) Default Order in table: | 80 | 2) Default Order in table: |
69 | Print Path | 81 | Print Path |
70 | Substitute Path | 82 | Substitute Path |
83 | |||
84 | DOCS: | ||
85 | The print name SHOULD be an informative pathname, suitable for display | ||
86 | to a user, that also identifies the target of the mount point. | ||
87 | Neither of these pathnames can contain dot directory names. | ||
88 | |||
89 | reparse tags, with the exception of IO_REPARSE_TAG_SYMLINK, | ||
90 | are processed on the server and are not processed by a client | ||
91 | after transmission over the wire. | ||
92 | Clients SHOULD treat associated reparse data as opaque data. | ||
71 | */ | 93 | */ |
72 | 94 | ||
73 | /* | 95 | /* |
@@ -93,7 +115,8 @@ static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); | |||
93 | #define Get16(p) GetUi16(p) | 115 | #define Get16(p) GetUi16(p) |
94 | #define Get32(p) GetUi32(p) | 116 | #define Get32(p) GetUi32(p) |
95 | 117 | ||
96 | static const wchar_t * const k_LinkPrefix = L"\\??\\"; | 118 | static const char * const k_LinkPrefix = "\\??\\"; |
119 | static const char * const k_LinkPrefix_UNC = "\\??\\UNC\\"; | ||
97 | static const unsigned k_LinkPrefix_Size = 4; | 120 | static const unsigned k_LinkPrefix_Size = 4; |
98 | 121 | ||
99 | static bool IsLinkPrefix(const wchar_t *s) | 122 | static bool IsLinkPrefix(const wchar_t *s) |
@@ -102,7 +125,7 @@ static bool IsLinkPrefix(const wchar_t *s) | |||
102 | } | 125 | } |
103 | 126 | ||
104 | /* | 127 | /* |
105 | static const wchar_t * const k_VolumePrefix = L"Volume{"; | 128 | static const char * const k_VolumePrefix = "Volume{"; |
106 | static const bool IsVolumeName(const wchar_t *s) | 129 | static const bool IsVolumeName(const wchar_t *s) |
107 | { | 130 | { |
108 | return IsString1PrefixedByString2(s, k_VolumePrefix); | 131 | return IsString1PrefixedByString2(s, k_VolumePrefix); |
@@ -118,7 +141,7 @@ static void WriteString(Byte *dest, const wchar_t *path) | |||
118 | { | 141 | { |
119 | for (;;) | 142 | for (;;) |
120 | { | 143 | { |
121 | wchar_t c = *path++; | 144 | const wchar_t c = *path++; |
122 | if (c == 0) | 145 | if (c == 0) |
123 | return; | 146 | return; |
124 | Set16(dest, (UInt16)c) | 147 | Set16(dest, (UInt16)c) |
@@ -126,62 +149,103 @@ static void WriteString(Byte *dest, const wchar_t *path) | |||
126 | } | 149 | } |
127 | } | 150 | } |
128 | 151 | ||
129 | bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) | 152 | #ifdef _WIN32 |
153 | void Convert_WinPath_to_WslLinuxPath(FString &s, bool convertDrivePath) | ||
130 | { | 154 | { |
131 | bool isAbs = IsAbsolutePath(path); | 155 | if (convertDrivePath && IsDrivePath(s)) |
132 | if (!isAbs && !isSymLink) | ||
133 | return false; | ||
134 | |||
135 | if (isWSL) | ||
136 | { | 156 | { |
137 | // unsupported characters probably use Replacement Character UTF-16 0xFFFD | 157 | FChar c = s[0]; |
138 | AString utf; | 158 | c = MyCharLower_Ascii(c); |
139 | ConvertUnicodeToUTF8(path, utf); | 159 | s.DeleteFrontal(2); |
140 | const size_t size = 4 + utf.Len(); | 160 | s.InsertAtFront(c); |
141 | if (size != (UInt16)size) | 161 | s.Insert(0, FTEXT("/mnt/")); |
142 | return false; | ||
143 | dest.Alloc(8 + size); | ||
144 | Byte *p = dest; | ||
145 | Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) | ||
146 | Set16(p + 4, (UInt16)(size)) | ||
147 | Set16(p + 6, 0) | ||
148 | Set32(p + 8, Z7_WIN_LX_SYMLINK_FLAG) | ||
149 | memcpy(p + 12, utf.Ptr(), utf.Len()); | ||
150 | return true; | ||
151 | } | 162 | } |
163 | s.Replace(FCHAR_PATH_SEPARATOR, FTEXT('/')); | ||
164 | } | ||
165 | #endif | ||
152 | 166 | ||
153 | // usual symbolic LINK (NOT WSL) | ||
154 | 167 | ||
155 | bool needPrintName = true; | 168 | static const unsigned k_Link_Size_Limit = 1u << 16; // 16-bit field is used for size. |
169 | |||
170 | void FillLinkData_WslLink(CByteBuffer &dest, const wchar_t *path) | ||
171 | { | ||
172 | // dest.Free(); // it's empty already | ||
173 | // WSL probably uses Replacement Character UTF-16 0xFFFD for unsupported characters? | ||
174 | AString utf; | ||
175 | ConvertUnicodeToUTF8(path, utf); | ||
176 | const unsigned size = 4 + utf.Len(); | ||
177 | if (size >= k_Link_Size_Limit) | ||
178 | return; | ||
179 | dest.Alloc(8 + size); | ||
180 | Byte *p = dest; | ||
181 | Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) | ||
182 | // Set32(p + 4, (UInt32)size) | ||
183 | Set16(p + 4, (UInt16)size) | ||
184 | Set16(p + 6, 0) | ||
185 | Set32(p + 8, Z7_WIN_LX_SYMLINK_VERSION_2) | ||
186 | memcpy(p + 12, utf.Ptr(), utf.Len()); | ||
187 | } | ||
188 | |||
156 | 189 | ||
157 | if (IsSuperPath(path)) | 190 | void FillLinkData_WinLink(CByteBuffer &dest, const wchar_t *path, bool isSymLink) |
191 | { | ||
192 | // dest.Free(); // it's empty already | ||
193 | bool isAbs = false; | ||
194 | if (IS_PATH_SEPAR(path[0])) | ||
158 | { | 195 | { |
159 | path += kSuperPathPrefixSize; | 196 | // root paths "\dir1\path" are marked as relative |
160 | if (!IsDrivePath(path)) | 197 | if (IS_PATH_SEPAR(path[1])) |
161 | needPrintName = false; | 198 | isAbs = true; |
199 | } | ||
200 | else | ||
201 | isAbs = IsAbsolutePath(path); | ||
202 | if (!isAbs && !isSymLink) | ||
203 | { | ||
204 | // Win10 allows us to create relative MOUNT_POINT. | ||
205 | // But relative MOUNT_POINT will not work when accessing it. | ||
206 | // So we prevent useless creation of a relative MOUNT_POINT. | ||
207 | return; | ||
162 | } | 208 | } |
163 | 209 | ||
164 | const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; | 210 | bool needPrintName = true; |
165 | 211 | UString subs (path); | |
212 | if (isAbs) | ||
213 | { | ||
214 | const bool isSuperPath = IsSuperPath(path); | ||
215 | if (!isSuperPath && NName::IsNetworkPath(us2fs(path))) | ||
216 | { | ||
217 | subs = k_LinkPrefix_UNC; | ||
218 | subs += (path + 2); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | if (isSuperPath) | ||
223 | { | ||
224 | // we remove super prefix: | ||
225 | path += kSuperPathPrefixSize; | ||
226 | // we want to get correct abolute path in PrintName still. | ||
227 | if (!IsDrivePath(path)) | ||
228 | needPrintName = false; // we need "\\server\path" for print name. | ||
229 | } | ||
230 | subs = k_LinkPrefix; | ||
231 | subs += path; | ||
232 | } | ||
233 | } | ||
234 | const size_t len1 = subs.Len() * 2; | ||
166 | size_t len2 = (size_t)MyStringLen(path) * 2; | 235 | size_t len2 = (size_t)MyStringLen(path) * 2; |
167 | const size_t len1 = len2 + add_Prefix_Len * 2; | ||
168 | if (!needPrintName) | 236 | if (!needPrintName) |
169 | len2 = 0; | 237 | len2 = 0; |
170 | 238 | size_t totalNamesSize = len1 + len2; | |
171 | size_t totalNamesSize = (len1 + len2); | ||
172 | |||
173 | /* some WIM imagex software uses old scheme for symbolic links. | 239 | /* some WIM imagex software uses old scheme for symbolic links. |
174 | so we can old scheme for byte to byte compatibility */ | 240 | so we can use old scheme for byte to byte compatibility */ |
175 | 241 | const bool newOrderScheme = isSymLink; | |
176 | bool newOrderScheme = isSymLink; | ||
177 | // newOrderScheme = false; | 242 | // newOrderScheme = false; |
178 | |||
179 | if (!newOrderScheme) | 243 | if (!newOrderScheme) |
180 | totalNamesSize += 2 * 2; | 244 | totalNamesSize += 2 * 2; // we use NULL terminators in old scheme. |
181 | 245 | ||
182 | const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; | 246 | const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; |
183 | if (size != (UInt16)size) | 247 | if (size >= k_Link_Size_Limit) |
184 | return false; | 248 | return; |
185 | dest.Alloc(size); | 249 | dest.Alloc(size); |
186 | memset(dest, 0, size); | 250 | memset(dest, 0, size); |
187 | const UInt32 tag = isSymLink ? | 251 | const UInt32 tag = isSymLink ? |
@@ -189,6 +253,7 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool i | |||
189 | Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; | 253 | Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; |
190 | Byte *p = dest; | 254 | Byte *p = dest; |
191 | Set32(p, tag) | 255 | Set32(p, tag) |
256 | // Set32(p + 4, (UInt32)(size - 8)) | ||
192 | Set16(p + 4, (UInt16)(size - 8)) | 257 | Set16(p + 4, (UInt16)(size - 8)) |
193 | Set16(p + 6, 0) | 258 | Set16(p + 6, 0) |
194 | p += 8; | 259 | p += 8; |
@@ -204,21 +269,16 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool i | |||
204 | Set16(p + 2, (UInt16)len1) | 269 | Set16(p + 2, (UInt16)len1) |
205 | Set16(p + 4, (UInt16)printOffs) | 270 | Set16(p + 4, (UInt16)printOffs) |
206 | Set16(p + 6, (UInt16)len2) | 271 | Set16(p + 6, (UInt16)len2) |
207 | |||
208 | p += 8; | 272 | p += 8; |
209 | if (isSymLink) | 273 | if (isSymLink) |
210 | { | 274 | { |
211 | UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE; | 275 | const UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE; |
212 | Set32(p, flags) | 276 | Set32(p, flags) |
213 | p += 4; | 277 | p += 4; |
214 | } | 278 | } |
215 | 279 | WriteString(p + subOffs, subs); | |
216 | if (add_Prefix_Len != 0) | ||
217 | WriteString(p + subOffs, k_LinkPrefix); | ||
218 | WriteString(p + subOffs + add_Prefix_Len * 2, path); | ||
219 | if (needPrintName) | 280 | if (needPrintName) |
220 | WriteString(p + printOffs, path); | 281 | WriteString(p + printOffs, path); |
221 | return true; | ||
222 | } | 282 | } |
223 | 283 | ||
224 | #endif // defined(_WIN32) && !defined(UNDER_CE) | 284 | #endif // defined(_WIN32) && !defined(UNDER_CE) |
@@ -230,7 +290,7 @@ static void GetString(const Byte *p, unsigned len, UString &res) | |||
230 | unsigned i; | 290 | unsigned i; |
231 | for (i = 0; i < len; i++) | 291 | for (i = 0; i < len; i++) |
232 | { | 292 | { |
233 | wchar_t c = Get16(p + i * 2); | 293 | const wchar_t c = Get16(p + (size_t)i * 2); |
234 | if (c == 0) | 294 | if (c == 0) |
235 | break; | 295 | break; |
236 | s[i] = c; | 296 | s[i] = c; |
@@ -239,6 +299,7 @@ static void GetString(const Byte *p, unsigned len, UString &res) | |||
239 | res.ReleaseBuf_SetLen(i); | 299 | res.ReleaseBuf_SetLen(i); |
240 | } | 300 | } |
241 | 301 | ||
302 | |||
242 | bool CReparseAttr::Parse(const Byte *p, size_t size) | 303 | bool CReparseAttr::Parse(const Byte *p, size_t size) |
243 | { | 304 | { |
244 | ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; | 305 | ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; |
@@ -250,7 +311,12 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
250 | return false; | 311 | return false; |
251 | Tag = Get32(p); | 312 | Tag = Get32(p); |
252 | if (Get16(p + 6) != 0) // padding | 313 | if (Get16(p + 6) != 0) // padding |
253 | return false; | 314 | { |
315 | // DOCs: Reserved : the field SHOULD be set to 0 | ||
316 | // and MUST be ignored (by parser). | ||
317 | // Win10 ignores it. | ||
318 | MinorError = true; // optional | ||
319 | } | ||
254 | unsigned len = Get16(p + 4); | 320 | unsigned len = Get16(p + 4); |
255 | p += 8; | 321 | p += 8; |
256 | size -= 8; | 322 | size -= 8; |
@@ -262,8 +328,6 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
262 | (type & kReparseFlags_Microsoft) == 0 || | 328 | (type & kReparseFlags_Microsoft) == 0 || |
263 | (type & 0xFFFF) != 3) | 329 | (type & 0xFFFF) != 3) |
264 | */ | 330 | */ |
265 | |||
266 | |||
267 | HeaderError = false; | 331 | HeaderError = false; |
268 | 332 | ||
269 | if ( Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT | 333 | if ( Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT |
@@ -282,8 +346,7 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
282 | { | 346 | { |
283 | if (len < 4) | 347 | if (len < 4) |
284 | return false; | 348 | return false; |
285 | Flags = Get32(p); // maybe it's not Flags | 349 | if (Get32(p) != Z7_WIN_LX_SYMLINK_VERSION_2) |
286 | if (Flags != Z7_WIN_LX_SYMLINK_FLAG) | ||
287 | return false; | 350 | return false; |
288 | len -= 4; | 351 | len -= 4; |
289 | p += 4; | 352 | p += 4; |
@@ -291,12 +354,13 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
291 | unsigned i; | 354 | unsigned i; |
292 | for (i = 0; i < len; i++) | 355 | for (i = 0; i < len; i++) |
293 | { | 356 | { |
294 | char c = (char)p[i]; | 357 | const char c = (char)p[i]; |
295 | s[i] = c; | 358 | s[i] = c; |
296 | if (c == 0) | 359 | if (c == 0) |
297 | break; | 360 | break; |
298 | } | 361 | } |
299 | WslName.ReleaseBuf_SetEnd(i); | 362 | s[i] = 0; |
363 | WslName.ReleaseBuf_SetLen(i); | ||
300 | MinorError = (i != len); | 364 | MinorError = (i != len); |
301 | ErrorCode = 0; | 365 | ErrorCode = 0; |
302 | return true; | 366 | return true; |
@@ -304,10 +368,10 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
304 | 368 | ||
305 | if (len < 8) | 369 | if (len < 8) |
306 | return false; | 370 | return false; |
307 | unsigned subOffs = Get16(p); | 371 | const unsigned subOffs = Get16(p); |
308 | unsigned subLen = Get16(p + 2); | 372 | const unsigned subLen = Get16(p + 2); |
309 | unsigned printOffs = Get16(p + 4); | 373 | const unsigned printOffs = Get16(p + 4); |
310 | unsigned printLen = Get16(p + 6); | 374 | const unsigned printLen = Get16(p + 6); |
311 | len -= 8; | 375 | len -= 8; |
312 | p += 8; | 376 | p += 8; |
313 | 377 | ||
@@ -335,15 +399,17 @@ bool CReparseAttr::Parse(const Byte *p, size_t size) | |||
335 | 399 | ||
336 | bool CReparseShortInfo::Parse(const Byte *p, size_t size) | 400 | bool CReparseShortInfo::Parse(const Byte *p, size_t size) |
337 | { | 401 | { |
338 | const Byte *start = p; | 402 | const Byte * const start = p; |
339 | Offset= 0; | 403 | Offset = 0; |
340 | Size = 0; | 404 | Size = 0; |
341 | if (size < 8) | 405 | if (size < 8) |
342 | return false; | 406 | return false; |
343 | UInt32 Tag = Get32(p); | 407 | const UInt32 Tag = Get32(p); |
344 | UInt32 len = Get16(p + 4); | 408 | UInt32 len = Get16(p + 4); |
409 | /* | ||
345 | if (len + 8 > size) | 410 | if (len + 8 > size) |
346 | return false; | 411 | return false; |
412 | */ | ||
347 | /* | 413 | /* |
348 | if ((type & kReparseFlags_Alias) == 0 || | 414 | if ((type & kReparseFlags_Alias) == 0 || |
349 | (type & kReparseFlags_Microsoft) == 0 || | 415 | (type & kReparseFlags_Microsoft) == 0 || |
@@ -353,16 +419,14 @@ bool CReparseShortInfo::Parse(const Byte *p, size_t size) | |||
353 | Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK) | 419 | Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK) |
354 | // return true; | 420 | // return true; |
355 | return false; | 421 | return false; |
356 | 422 | /* | |
357 | if (Get16(p + 6) != 0) // padding | 423 | if (Get16(p + 6) != 0) // padding |
358 | return false; | 424 | return false; |
359 | 425 | */ | |
360 | p += 8; | 426 | p += 8; |
361 | size -= 8; | 427 | size -= 8; |
362 | |||
363 | if (len != size) // do we need that check? | 428 | if (len != size) // do we need that check? |
364 | return false; | 429 | return false; |
365 | |||
366 | if (len < 8) | 430 | if (len < 8) |
367 | return false; | 431 | return false; |
368 | unsigned subOffs = Get16(p); | 432 | unsigned subOffs = Get16(p); |
@@ -396,10 +460,14 @@ bool CReparseAttr::IsOkNamePair() const | |||
396 | { | 460 | { |
397 | if (IsLinkPrefix(SubsName)) | 461 | if (IsLinkPrefix(SubsName)) |
398 | { | 462 | { |
463 | if (PrintName == GetPath()) | ||
464 | return true; | ||
465 | /* | ||
399 | if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) | 466 | if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) |
400 | return PrintName.IsEmpty(); | 467 | return PrintName.IsEmpty(); |
401 | if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) | 468 | if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) |
402 | return true; | 469 | return true; |
470 | */ | ||
403 | } | 471 | } |
404 | return wcscmp(SubsName, PrintName) == 0; | 472 | return wcscmp(SubsName, PrintName) == 0; |
405 | } | 473 | } |
@@ -415,21 +483,26 @@ bool CReparseAttr::IsVolume() const | |||
415 | 483 | ||
416 | UString CReparseAttr::GetPath() const | 484 | UString CReparseAttr::GetPath() const |
417 | { | 485 | { |
486 | UString s (SubsName); | ||
418 | if (IsSymLink_WSL()) | 487 | if (IsSymLink_WSL()) |
419 | { | 488 | { |
420 | UString u; | ||
421 | // if (CheckUTF8(attr.WslName) | 489 | // if (CheckUTF8(attr.WslName) |
422 | if (!ConvertUTF8ToUnicode(WslName, u)) | 490 | if (!ConvertUTF8ToUnicode(WslName, s)) |
423 | MultiByteToUnicodeString2(u, WslName); | 491 | MultiByteToUnicodeString2(s, WslName); |
424 | return u; | ||
425 | } | 492 | } |
426 | 493 | else if (IsLinkPrefix(s)) | |
427 | UString s (SubsName); | ||
428 | if (IsLinkPrefix(s)) | ||
429 | { | 494 | { |
430 | s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" | 495 | if (IsString1PrefixedByString2_NoCase_Ascii(s.Ptr(), k_LinkPrefix_UNC)) |
431 | if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) | 496 | { |
432 | s.DeleteFrontal(k_LinkPrefix_Size); | 497 | s.DeleteFrontal(6); |
498 | s.ReplaceOneCharAtPos(0, '\\'); | ||
499 | } | ||
500 | else | ||
501 | { | ||
502 | s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" | ||
503 | if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) | ||
504 | s.DeleteFrontal(k_LinkPrefix_Size); | ||
505 | } | ||
433 | } | 506 | } |
434 | return s; | 507 | return s; |
435 | } | 508 | } |
@@ -468,7 +541,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMA | |||
468 | static bool CreatePrefixDirOfFile(CFSTR path) | 541 | static bool CreatePrefixDirOfFile(CFSTR path) |
469 | { | 542 | { |
470 | FString path2 (path); | 543 | FString path2 (path); |
471 | int pos = path2.ReverseFind_PathSepar(); | 544 | const int pos = path2.ReverseFind_PathSepar(); |
472 | if (pos < 0) | 545 | if (pos < 0) |
473 | return true; | 546 | return true; |
474 | #ifdef _WIN32 | 547 | #ifdef _WIN32 |
@@ -494,6 +567,8 @@ static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD si | |||
494 | } | 567 | } |
495 | 568 | ||
496 | 569 | ||
570 | // MOUNT_POINT (Junction Point) and LX_SYMLINK (WSL) can be written without administrator rights. | ||
571 | // SYMLINK requires administrator rights. | ||
497 | // If there is Reparse data already, it still writes new Reparse data | 572 | // If there is Reparse data already, it still writes new Reparse data |
498 | bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) | 573 | bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) |
499 | { | 574 | { |
@@ -540,10 +615,11 @@ bool DeleteReparseData(CFSTR path) | |||
540 | SetLastError(ERROR_INVALID_REPARSE_DATA); | 615 | SetLastError(ERROR_INVALID_REPARSE_DATA); |
541 | return false; | 616 | return false; |
542 | } | 617 | } |
543 | BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; | 618 | // BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; |
544 | memset(buf, 0, sizeof(buf)); | 619 | // memset(buf, 0, sizeof(buf)); |
545 | memcpy(buf, reparseData, 4); // tag | 620 | // memcpy(buf, reparseData, 4); // tag |
546 | return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf)); | 621 | memset(reparseData + 4, 0, my_REPARSE_DATA_BUFFER_HEADER_SIZE - 4); |
622 | return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, reparseData, my_REPARSE_DATA_BUFFER_HEADER_SIZE); | ||
547 | } | 623 | } |
548 | 624 | ||
549 | } | 625 | } |
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index c16b3d4..eb62567 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp | |||
@@ -65,8 +65,15 @@ void NormalizeDirPathPrefix(UString &dirPath) | |||
65 | dirPath.Add_PathSepar(); | 65 | dirPath.Add_PathSepar(); |
66 | } | 66 | } |
67 | 67 | ||
68 | |||
69 | #define IS_LETTER_CHAR(c) ((((unsigned)(int)(c) | 0x20) - (unsigned)'a' <= (unsigned)('z' - 'a'))) | ||
70 | bool IsDrivePath (const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } | ||
71 | // bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } | ||
72 | |||
68 | #ifdef _WIN32 | 73 | #ifdef _WIN32 |
69 | 74 | ||
75 | bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } | ||
76 | |||
70 | #ifndef USE_UNICODE_FSTRING | 77 | #ifndef USE_UNICODE_FSTRING |
71 | #ifdef Z7_LONG_PATH | 78 | #ifdef Z7_LONG_PATH |
72 | static void NormalizeDirSeparators(UString &s) | 79 | static void NormalizeDirSeparators(UString &s) |
@@ -87,13 +94,6 @@ void NormalizeDirSeparators(FString &s) | |||
87 | s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR); | 94 | s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR); |
88 | } | 95 | } |
89 | 96 | ||
90 | #endif | ||
91 | |||
92 | |||
93 | #define IS_LETTER_CHAR(c) ((((unsigned)(int)(c) | 0x20) - (unsigned)'a' <= (unsigned)('z' - 'a'))) | ||
94 | |||
95 | bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } | ||
96 | |||
97 | bool IsAltPathPrefix(CFSTR s) throw() | 97 | bool IsAltPathPrefix(CFSTR s) throw() |
98 | { | 98 | { |
99 | unsigned len = MyStringLen(s); | 99 | unsigned len = MyStringLen(s); |
@@ -117,16 +117,23 @@ bool IsAltPathPrefix(CFSTR s) throw() | |||
117 | return true; | 117 | return true; |
118 | } | 118 | } |
119 | 119 | ||
120 | #if defined(_WIN32) && !defined(UNDER_CE) | 120 | #endif // _WIN32 |
121 | |||
121 | 122 | ||
122 | const char * const kSuperPathPrefix = "\\\\?\\"; | 123 | const char * const kSuperPathPrefix = |
124 | STRING_PATH_SEPARATOR | ||
125 | STRING_PATH_SEPARATOR "?" | ||
126 | STRING_PATH_SEPARATOR; | ||
123 | #ifdef Z7_LONG_PATH | 127 | #ifdef Z7_LONG_PATH |
124 | static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; | 128 | static const char * const kSuperUncPrefix = |
129 | STRING_PATH_SEPARATOR | ||
130 | STRING_PATH_SEPARATOR "?" | ||
131 | STRING_PATH_SEPARATOR "UNC" | ||
132 | STRING_PATH_SEPARATOR; | ||
125 | #endif | 133 | #endif |
126 | 134 | ||
127 | #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) | 135 | #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) |
128 | #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) | 136 | #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) |
129 | #define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3])) | ||
130 | 137 | ||
131 | #define IS_UNC_WITH_SLASH(s) ( \ | 138 | #define IS_UNC_WITH_SLASH(s) ( \ |
132 | ((s)[0] == 'U' || (s)[0] == 'u') \ | 139 | ((s)[0] == 'U' || (s)[0] == 'u') \ |
@@ -134,6 +141,16 @@ static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; | |||
134 | && ((s)[2] == 'C' || (s)[2] == 'c') \ | 141 | && ((s)[2] == 'C' || (s)[2] == 'c') \ |
135 | && IS_SEPAR((s)[3])) | 142 | && IS_SEPAR((s)[3])) |
136 | 143 | ||
144 | static const unsigned kDrivePrefixSize = 3; /* c:\ */ | ||
145 | |||
146 | bool IsSuperPath(const wchar_t *s) throw(); | ||
147 | bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } | ||
148 | // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } | ||
149 | |||
150 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
151 | |||
152 | #define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3])) | ||
153 | bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } | ||
137 | bool IsDevicePath(CFSTR s) throw() | 154 | bool IsDevicePath(CFSTR s) throw() |
138 | { | 155 | { |
139 | #ifdef UNDER_CE | 156 | #ifdef UNDER_CE |
@@ -154,7 +171,7 @@ bool IsDevicePath(CFSTR s) throw() | |||
154 | 171 | ||
155 | if (!IS_DEVICE_PATH(s)) | 172 | if (!IS_DEVICE_PATH(s)) |
156 | return false; | 173 | return false; |
157 | unsigned len = MyStringLen(s); | 174 | const unsigned len = MyStringLen(s); |
158 | if (len == 6 && s[5] == ':') | 175 | if (len == 6 && s[5] == ':') |
159 | return true; | 176 | return true; |
160 | if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) | 177 | if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) |
@@ -174,7 +191,7 @@ bool IsNetworkPath(CFSTR s) throw() | |||
174 | return false; | 191 | return false; |
175 | if (IsSuperUncPath(s)) | 192 | if (IsSuperUncPath(s)) |
176 | return true; | 193 | return true; |
177 | FChar c = s[2]; | 194 | const FChar c = s[2]; |
178 | return (c != '.' && c != '?'); | 195 | return (c != '.' && c != '?'); |
179 | } | 196 | } |
180 | 197 | ||
@@ -187,7 +204,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw() | |||
187 | prefixSize = kSuperUncPathPrefixSize; | 204 | prefixSize = kSuperUncPathPrefixSize; |
188 | else | 205 | else |
189 | { | 206 | { |
190 | FChar c = s[2]; | 207 | const FChar c = s[2]; |
191 | if (c == '.' || c == '?') | 208 | if (c == '.' || c == '?') |
192 | return 0; | 209 | return 0; |
193 | } | 210 | } |
@@ -209,14 +226,6 @@ bool IsNetworkShareRootPath(CFSTR s) throw() | |||
209 | return s[(unsigned)pos + 1] == 0; | 226 | return s[(unsigned)pos + 1] == 0; |
210 | } | 227 | } |
211 | 228 | ||
212 | static const unsigned kDrivePrefixSize = 3; /* c:\ */ | ||
213 | |||
214 | bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } | ||
215 | // bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } | ||
216 | bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } | ||
217 | bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } | ||
218 | // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } | ||
219 | |||
220 | bool IsAltStreamPrefixWithColon(const UString &s) throw() | 229 | bool IsAltStreamPrefixWithColon(const UString &s) throw() |
221 | { | 230 | { |
222 | if (s.IsEmpty()) | 231 | if (s.IsEmpty()) |
@@ -278,12 +287,14 @@ bool IsAbsolutePath(const wchar_t *s) throw() | |||
278 | int FindAltStreamColon(CFSTR path) throw() | 287 | int FindAltStreamColon(CFSTR path) throw() |
279 | { | 288 | { |
280 | unsigned i = 0; | 289 | unsigned i = 0; |
281 | if (IsDrivePath2(path)) | 290 | if (IsSuperPath(path)) |
282 | i = 2; | 291 | i = kSuperPathPrefixSize; |
292 | if (IsDrivePath2(path + i)) | ||
293 | i += 2; | ||
283 | int colonPos = -1; | 294 | int colonPos = -1; |
284 | for (;; i++) | 295 | for (;; i++) |
285 | { | 296 | { |
286 | FChar c = path[i]; | 297 | const FChar c = path[i]; |
287 | if (c == 0) | 298 | if (c == 0) |
288 | return colonPos; | 299 | return colonPos; |
289 | if (c == ':') | 300 | if (c == ':') |
@@ -347,14 +358,16 @@ unsigned GetRootPrefixSize(CFSTR s) throw() | |||
347 | } | 358 | } |
348 | 359 | ||
349 | #endif // USE_UNICODE_FSTRING | 360 | #endif // USE_UNICODE_FSTRING |
361 | #endif // _WIN32 | ||
362 | |||
350 | 363 | ||
351 | static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() | 364 | static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() |
352 | { | 365 | { |
353 | // Network path: we look "server\path\" as root prefix | 366 | // Network path: we look "server\path\" as root prefix |
354 | int pos = FindSepar(s); | 367 | const int pos = FindSepar(s); |
355 | if (pos < 0) | 368 | if (pos < 0) |
356 | return 0; | 369 | return 0; |
357 | int pos2 = FindSepar(s + (unsigned)pos + 1); | 370 | const int pos2 = FindSepar(s + (unsigned)pos + 1); |
358 | if (pos2 < 0) | 371 | if (pos2 < 0) |
359 | return 0; | 372 | return 0; |
360 | return (unsigned)(pos + pos2 + 2); | 373 | return (unsigned)(pos + pos2 + 2); |
@@ -368,7 +381,7 @@ static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() | |||
368 | return 0; | 381 | return 0; |
369 | if (s[1] == 0 || !IS_SEPAR(s[1])) | 382 | if (s[1] == 0 || !IS_SEPAR(s[1])) |
370 | return 1; | 383 | return 1; |
371 | unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); | 384 | const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); |
372 | return (size == 0) ? 0 : 2 + size; | 385 | return (size == 0) ? 0 : 2 + size; |
373 | } | 386 | } |
374 | 387 | ||
@@ -376,17 +389,21 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() | |||
376 | { | 389 | { |
377 | if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) | 390 | if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) |
378 | { | 391 | { |
379 | unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); | 392 | const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); |
380 | return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; | 393 | return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; |
381 | } | 394 | } |
382 | // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" | 395 | // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" |
383 | int pos = FindSepar(s + kSuperPathPrefixSize); | 396 | const int pos = FindSepar(s + kSuperPathPrefixSize); |
384 | if (pos < 0) | 397 | if (pos < 0) |
385 | return 0; | 398 | return 0; |
386 | return kSuperPathPrefixSize + (unsigned)(pos + 1); | 399 | return kSuperPathPrefixSize + (unsigned)(pos + 1); |
387 | } | 400 | } |
388 | 401 | ||
402 | #ifdef _WIN32 | ||
389 | unsigned GetRootPrefixSize(const wchar_t *s) throw() | 403 | unsigned GetRootPrefixSize(const wchar_t *s) throw() |
404 | #else | ||
405 | unsigned GetRootPrefixSize_WINDOWS(const wchar_t *s) throw() | ||
406 | #endif | ||
390 | { | 407 | { |
391 | if (IS_DEVICE_PATH(s)) | 408 | if (IS_DEVICE_PATH(s)) |
392 | return kDevicePathPrefixSize; | 409 | return kDevicePathPrefixSize; |
@@ -395,7 +412,7 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw() | |||
395 | return GetRootPrefixSize_Of_SimplePath(s); | 412 | return GetRootPrefixSize_Of_SimplePath(s); |
396 | } | 413 | } |
397 | 414 | ||
398 | #else // _WIN32 | 415 | #ifndef _WIN32 |
399 | 416 | ||
400 | bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); } | 417 | bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); } |
401 | 418 | ||
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h index 219b656..ce26e78 100644 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h | |||
@@ -25,13 +25,13 @@ bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars li | |||
25 | 25 | ||
26 | bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ | 26 | bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ |
27 | 27 | ||
28 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
29 | |||
30 | extern const char * const kSuperPathPrefix; /* \\?\ */ | 28 | extern const char * const kSuperPathPrefix; /* \\?\ */ |
31 | const unsigned kDevicePathPrefixSize = 4; | 29 | const unsigned kDevicePathPrefixSize = 4; |
32 | const unsigned kSuperPathPrefixSize = 4; | 30 | const unsigned kSuperPathPrefixSize = 4; |
33 | const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; | 31 | const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; |
34 | 32 | ||
33 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
34 | |||
35 | bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ | 35 | bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ |
36 | bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */ | 36 | bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */ |
37 | bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */ | 37 | bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */ |
@@ -86,6 +86,15 @@ int FindAltStreamColon(CFSTR path) throw(); | |||
86 | bool IsAbsolutePath(const wchar_t *s) throw(); | 86 | bool IsAbsolutePath(const wchar_t *s) throw(); |
87 | unsigned GetRootPrefixSize(const wchar_t *s) throw(); | 87 | unsigned GetRootPrefixSize(const wchar_t *s) throw(); |
88 | 88 | ||
89 | #ifndef _WIN32 | ||
90 | /* GetRootPrefixSize_WINDOWS() is called in linux, but it parses path by windows rules. | ||
91 | It supports only paths system (linux) slash separators (STRING_PATH_SEPARATOR), | ||
92 | It doesn't parses paths with backslash (windows) separators. | ||
93 | "c:/dir/file" is supported. | ||
94 | */ | ||
95 | unsigned GetRootPrefixSize_WINDOWS(const wchar_t *s) throw(); | ||
96 | #endif | ||
97 | |||
89 | #ifdef Z7_LONG_PATH | 98 | #ifdef Z7_LONG_PATH |
90 | 99 | ||
91 | const int kSuperPathType_UseOnlyMain = 0; | 100 | const int kSuperPathType_UseOnlyMain = 0; |
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp index c8b1709..a94a50f 100644 --- a/CPP/Windows/Registry.cpp +++ b/CPP/Windows/Registry.cpp | |||
@@ -78,7 +78,7 @@ LONG CKey::Close() throw() | |||
78 | return res; | 78 | return res; |
79 | } | 79 | } |
80 | 80 | ||
81 | // win95, win98: deletes sunkey and all its subkeys | 81 | // win95, win98: deletes subkey and all its subkeys |
82 | // winNT to be deleted must not have subkeys | 82 | // winNT to be deleted must not have subkeys |
83 | LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() | 83 | LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() |
84 | { | 84 | { |
@@ -88,22 +88,36 @@ LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() | |||
88 | 88 | ||
89 | LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() | 89 | LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() |
90 | { | 90 | { |
91 | CKey key; | ||
92 | LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); | ||
93 | if (res != ERROR_SUCCESS) | ||
94 | return res; | ||
95 | FILETIME fileTime; | ||
96 | const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL | ||
97 | DWORD size = kBufSize; | ||
98 | TCHAR buffer[kBufSize]; | ||
99 | while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) | ||
100 | { | 91 | { |
101 | res = key.RecurseDeleteKey(buffer); | 92 | CKey key; |
93 | LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); | ||
102 | if (res != ERROR_SUCCESS) | 94 | if (res != ERROR_SUCCESS) |
103 | return res; | 95 | return res; |
104 | size = kBufSize; | 96 | FILETIME fileTime; |
97 | const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL | ||
98 | TCHAR buffer[kBufSize]; | ||
99 | // we use loop limit here for some unexpected code failure | ||
100 | for (unsigned loop_cnt = 0; loop_cnt < (1u << 26); loop_cnt++) | ||
101 | { | ||
102 | DWORD size = kBufSize; | ||
103 | // we always request starting item (index==0) in each iteration, | ||
104 | // because we remove starting item (index==0) in each loop iteration. | ||
105 | res = RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime); | ||
106 | if (res != ERROR_SUCCESS) | ||
107 | { | ||
108 | // possible return codes: | ||
109 | // ERROR_NO_MORE_ITEMS : are no more subkeys available | ||
110 | // ERROR_MORE_DATA : name buffer is too small | ||
111 | // we can try to remove (subKeyName), even if there is non ERROR_NO_MORE_ITEMS error. | ||
112 | // if (res != ERROR_NO_MORE_ITEMS) return res; | ||
113 | break; | ||
114 | } | ||
115 | res = key.RecurseDeleteKey(buffer); | ||
116 | if (res != ERROR_SUCCESS) | ||
117 | return res; | ||
118 | } | ||
119 | // key.Close(); | ||
105 | } | 120 | } |
106 | key.Close(); | ||
107 | return DeleteSubKey(subKeyName); | 121 | return DeleteSubKey(subKeyName); |
108 | } | 122 | } |
109 | 123 | ||
@@ -127,7 +141,7 @@ LONG CKey::DeleteValue(LPCWSTR name) | |||
127 | MY_ASSUME(_object != NULL); | 141 | MY_ASSUME(_object != NULL); |
128 | if (g_IsNT) | 142 | if (g_IsNT) |
129 | return ::RegDeleteValueW(_object, name); | 143 | return ::RegDeleteValueW(_object, name); |
130 | return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); | 144 | return DeleteValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name)); |
131 | } | 145 | } |
132 | #endif | 146 | #endif |
133 | 147 | ||
@@ -143,12 +157,15 @@ LONG CKey::SetValue(LPCTSTR name, bool value) throw() | |||
143 | return SetValue(name, BoolToUINT32(value)); | 157 | return SetValue(name, BoolToUINT32(value)); |
144 | } | 158 | } |
145 | 159 | ||
160 | |||
161 | // value must be string that is NULL terminated | ||
146 | LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() | 162 | LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() |
147 | { | 163 | { |
148 | MYASSERT(value != NULL); | 164 | MYASSERT(value != NULL); |
149 | MY_ASSUME(_object != NULL); | 165 | MY_ASSUME(_object != NULL); |
166 | // note: RegSetValueEx supports (value == NULL), if (cbData == 0) | ||
150 | return RegSetValueEx(_object, name, 0, REG_SZ, | 167 | return RegSetValueEx(_object, name, 0, REG_SZ, |
151 | (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)); | 168 | (const BYTE *)value, (DWORD)(((DWORD)lstrlen(value) + 1) * sizeof(TCHAR))); |
152 | } | 169 | } |
153 | 170 | ||
154 | /* | 171 | /* |
@@ -156,7 +173,7 @@ LONG CKey::SetValue(LPCTSTR name, const CSysString &value) | |||
156 | { | 173 | { |
157 | MYASSERT(value != NULL); | 174 | MYASSERT(value != NULL); |
158 | MY_ASSUME(_object != NULL); | 175 | MY_ASSUME(_object != NULL); |
159 | return RegSetValueEx(_object, name, NULL, REG_SZ, | 176 | return RegSetValueEx(_object, name, 0, REG_SZ, |
160 | (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); | 177 | (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); |
161 | } | 178 | } |
162 | */ | 179 | */ |
@@ -169,9 +186,10 @@ LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) | |||
169 | MY_ASSUME(_object != NULL); | 186 | MY_ASSUME(_object != NULL); |
170 | if (g_IsNT) | 187 | if (g_IsNT) |
171 | return RegSetValueExW(_object, name, 0, REG_SZ, | 188 | return RegSetValueExW(_object, name, 0, REG_SZ, |
172 | (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); | 189 | (const BYTE *)value, (DWORD)(((DWORD)wcslen(value) + 1) * sizeof(wchar_t))); |
173 | return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), | 190 | return SetValue(name == NULL ? NULL : |
174 | value == 0 ? 0 : (LPCSTR)GetSystemString(value)); | 191 | (LPCSTR)GetSystemString(name), |
192 | (LPCSTR)GetSystemString(value)); | ||
175 | } | 193 | } |
176 | 194 | ||
177 | #endif | 195 | #endif |
@@ -205,99 +223,137 @@ LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw( | |||
205 | return res; | 223 | return res; |
206 | } | 224 | } |
207 | 225 | ||
208 | LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() | ||
209 | { | ||
210 | DWORD type = 0; | ||
211 | DWORD count = sizeof(DWORD); | ||
212 | LONG res = RegQueryValueEx(_object, name, NULL, &type, | ||
213 | (LPBYTE)&value, &count); | ||
214 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); | ||
215 | MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); | ||
216 | return res; | ||
217 | } | ||
218 | 226 | ||
219 | LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() | 227 | LONG CKey::GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw() |
220 | { | 228 | { |
221 | UInt32 uintValue = BoolToUINT32(value); | 229 | DWORD type = 0; |
222 | LONG res = QueryValue(name, uintValue); | 230 | DWORD count = sizeof(value); |
223 | value = UINT32ToBool(uintValue); | 231 | UInt32 value2; // = value; |
232 | const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count); | ||
233 | if (res == ERROR_SUCCESS) | ||
234 | { | ||
235 | // ERROR_UNSUPPORTED_TYPE | ||
236 | if (count != sizeof(value) || type != REG_DWORD) | ||
237 | return ERROR_UNSUPPORTED_TYPE; // ERROR_INVALID_DATA; | ||
238 | value = value2; | ||
239 | } | ||
224 | return res; | 240 | return res; |
225 | } | 241 | } |
226 | 242 | ||
227 | LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() | 243 | LONG CKey::GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw() |
228 | { | 244 | { |
229 | UInt32 newVal; | 245 | DWORD type = 0; |
230 | LONG res = QueryValue(name, newVal); | 246 | DWORD count = sizeof(value); |
247 | UInt64 value2; // = value; | ||
248 | const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count); | ||
231 | if (res == ERROR_SUCCESS) | 249 | if (res == ERROR_SUCCESS) |
232 | value = newVal; | 250 | { |
251 | if (count != sizeof(value) || type != REG_QWORD) | ||
252 | return ERROR_UNSUPPORTED_TYPE; | ||
253 | value = value2; | ||
254 | } | ||
233 | return res; | 255 | return res; |
234 | } | 256 | } |
235 | 257 | ||
236 | LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() | 258 | LONG CKey::GetValue_bool_IfOk(LPCTSTR name, bool &value) throw() |
237 | { | 259 | { |
238 | bool newVal = false; | 260 | UInt32 uintValue; |
239 | LONG res = QueryValue(name, newVal); | 261 | const LONG res = GetValue_UInt32_IfOk(name, uintValue); |
240 | if (res == ERROR_SUCCESS) | 262 | if (res == ERROR_SUCCESS) |
241 | value = newVal; | 263 | value = UINT32ToBool(uintValue); |
242 | return res; | 264 | return res; |
243 | } | 265 | } |
244 | 266 | ||
245 | LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() | 267 | |
246 | { | ||
247 | DWORD type = 0; | ||
248 | LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | ||
249 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | ||
250 | return res; | ||
251 | } | ||
252 | 268 | ||
253 | LONG CKey::QueryValue(LPCTSTR name, CSysString &value) | 269 | LONG CKey::QueryValue(LPCTSTR name, CSysString &value) |
254 | { | 270 | { |
255 | value.Empty(); | 271 | value.Empty(); |
256 | DWORD type = 0; | 272 | LONG res = ERROR_SUCCESS; |
257 | DWORD curSize = 0; | 273 | { |
258 | LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, &curSize); | 274 | // if we don't want multiple calls here, |
259 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | 275 | // we can use big value (264) here. |
260 | return res; | 276 | // 3 is default available length in new string. |
261 | UInt32 curSize2 = curSize; | 277 | DWORD size_prev = 3 * sizeof(TCHAR); |
262 | res = QueryValue(name, value.GetBuf(curSize), curSize2); | 278 | // at least 2 attempts are required. But we use more attempts for cases, |
263 | if (curSize > curSize2) | 279 | // where string can be changed by anothner process |
264 | curSize = curSize2; | 280 | for (unsigned i = 0; i < 2 + 2; i++) |
265 | value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); | 281 | { |
282 | DWORD type = 0; | ||
283 | DWORD size = size_prev; | ||
284 | { | ||
285 | LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(TCHAR)); | ||
286 | res = QueryValueEx(name, &type, size == 0 ? NULL : buf, &size); | ||
287 | // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size. | ||
288 | } | ||
289 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
290 | { | ||
291 | if (type != REG_SZ && type != REG_EXPAND_SZ) | ||
292 | { | ||
293 | res = ERROR_UNSUPPORTED_TYPE; | ||
294 | size = 0; | ||
295 | } | ||
296 | } | ||
297 | else | ||
298 | size = 0; | ||
299 | if (size > size_prev) | ||
300 | { | ||
301 | size_prev = size; | ||
302 | size = 0; | ||
303 | res = ERROR_MORE_DATA; | ||
304 | } | ||
305 | value.ReleaseBuf_CalcLen(size / sizeof(TCHAR)); | ||
306 | if (res != ERROR_MORE_DATA) | ||
307 | return res; | ||
308 | } | ||
309 | } | ||
266 | return res; | 310 | return res; |
267 | } | 311 | } |
268 | 312 | ||
269 | 313 | ||
270 | #ifndef _UNICODE | 314 | #ifndef _UNICODE |
271 | 315 | ||
272 | LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) | ||
273 | { | ||
274 | DWORD type = 0; | ||
275 | LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | ||
276 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | ||
277 | return res; | ||
278 | } | ||
279 | |||
280 | LONG CKey::QueryValue(LPCWSTR name, UString &value) | 316 | LONG CKey::QueryValue(LPCWSTR name, UString &value) |
281 | { | 317 | { |
282 | value.Empty(); | 318 | value.Empty(); |
283 | DWORD type = 0; | 319 | LONG res = ERROR_SUCCESS; |
284 | DWORD curSize = 0; | ||
285 | LONG res; | ||
286 | if (g_IsNT) | 320 | if (g_IsNT) |
287 | { | 321 | { |
288 | res = RegQueryValueExW(_object, name, NULL, &type, NULL, &curSize); | 322 | DWORD size_prev = 3 * sizeof(wchar_t); |
289 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | 323 | for (unsigned i = 0; i < 2 + 2; i++) |
290 | return res; | 324 | { |
291 | UInt32 curSize2 = curSize; | 325 | DWORD type = 0; |
292 | res = QueryValue(name, value.GetBuf(curSize), curSize2); | 326 | DWORD size = size_prev; |
293 | if (curSize > curSize2) | 327 | { |
294 | curSize = curSize2; | 328 | LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(wchar_t)); |
295 | value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); | 329 | res = RegQueryValueExW(_object, name, NULL, &type, |
330 | size == 0 ? NULL : buf, &size); | ||
331 | } | ||
332 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
333 | { | ||
334 | if (type != REG_SZ && type != REG_EXPAND_SZ) | ||
335 | { | ||
336 | res = ERROR_UNSUPPORTED_TYPE; | ||
337 | size = 0; | ||
338 | } | ||
339 | } | ||
340 | else | ||
341 | size = 0; | ||
342 | if (size > size_prev) | ||
343 | { | ||
344 | size_prev = size; | ||
345 | size = 0; | ||
346 | res = ERROR_MORE_DATA; | ||
347 | } | ||
348 | value.ReleaseBuf_CalcLen(size / sizeof(wchar_t)); | ||
349 | if (res != ERROR_MORE_DATA) | ||
350 | return res; | ||
351 | } | ||
296 | } | 352 | } |
297 | else | 353 | else |
298 | { | 354 | { |
299 | AString vTemp; | 355 | AString vTemp; |
300 | res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); | 356 | res = QueryValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name), vTemp); |
301 | value = GetUnicodeString(vTemp); | 357 | value = GetUnicodeString(vTemp); |
302 | } | 358 | } |
303 | return res; | 359 | return res; |
@@ -306,26 +362,43 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value) | |||
306 | #endif | 362 | #endif |
307 | 363 | ||
308 | 364 | ||
309 | LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() | 365 | LONG CKey::QueryValue_Binary(LPCTSTR name, CByteBuffer &value) |
310 | { | 366 | { |
311 | DWORD type = 0; | 367 | // value.Free(); |
312 | LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | 368 | DWORD size_prev = 0; |
313 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); | 369 | LONG res = ERROR_SUCCESS; |
370 | for (unsigned i = 0; i < 2 + 2; i++) | ||
371 | { | ||
372 | DWORD type = 0; | ||
373 | DWORD size = size_prev; | ||
374 | value.Alloc(size_prev); | ||
375 | res = QueryValueEx(name, &type, value.NonConstData(), &size); | ||
376 | // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size. | ||
377 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
378 | { | ||
379 | if (type != REG_BINARY) | ||
380 | { | ||
381 | res = ERROR_UNSUPPORTED_TYPE; | ||
382 | size = 0; | ||
383 | } | ||
384 | } | ||
385 | else | ||
386 | size = 0; | ||
387 | if (size > size_prev) | ||
388 | { | ||
389 | size_prev = size; | ||
390 | size = 0; | ||
391 | res = ERROR_MORE_DATA; | ||
392 | } | ||
393 | if (size < value.Size()) | ||
394 | value.ChangeSize_KeepData(size, size); | ||
395 | if (res != ERROR_MORE_DATA) | ||
396 | return res; | ||
397 | } | ||
314 | return res; | 398 | return res; |
315 | } | 399 | } |
316 | 400 | ||
317 | 401 | ||
318 | LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) | ||
319 | { | ||
320 | DWORD type = 0; | ||
321 | dataSize = 0; | ||
322 | LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize); | ||
323 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | ||
324 | return res; | ||
325 | value.Alloc(dataSize); | ||
326 | return QueryValue(name, (BYTE *)value, dataSize); | ||
327 | } | ||
328 | |||
329 | LONG CKey::EnumKeys(CSysStringVector &keyNames) | 402 | LONG CKey::EnumKeys(CSysStringVector &keyNames) |
330 | { | 403 | { |
331 | keyNames.Clear(); | 404 | keyNames.Clear(); |
@@ -334,23 +407,23 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames) | |||
334 | { | 407 | { |
335 | const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL | 408 | const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL |
336 | FILETIME lastWriteTime; | 409 | FILETIME lastWriteTime; |
337 | UInt32 nameSize = kBufSize; | 410 | DWORD nameSize = kBufSize; |
338 | LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), | 411 | const LONG res = ::RegEnumKeyEx(_object, index, |
339 | (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); | 412 | keyName.GetBuf(kBufSize), &nameSize, |
413 | NULL, NULL, NULL, &lastWriteTime); | ||
340 | keyName.ReleaseBuf_CalcLen(kBufSize); | 414 | keyName.ReleaseBuf_CalcLen(kBufSize); |
341 | if (result == ERROR_NO_MORE_ITEMS) | 415 | if (res == ERROR_NO_MORE_ITEMS) |
342 | break; | 416 | return ERROR_SUCCESS; |
343 | if (result != ERROR_SUCCESS) | 417 | if (res != ERROR_SUCCESS) |
344 | return result; | 418 | return res; |
345 | keyNames.Add(keyName); | 419 | keyNames.Add(keyName); |
346 | } | 420 | } |
347 | return ERROR_SUCCESS; | ||
348 | } | 421 | } |
349 | 422 | ||
423 | |||
350 | LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) | 424 | LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) |
351 | { | 425 | { |
352 | size_t numChars = 0; | 426 | size_t numChars = 0; |
353 | |||
354 | unsigned i; | 427 | unsigned i; |
355 | 428 | ||
356 | for (i = 0; i < strings.Size(); i++) | 429 | for (i = 0; i < strings.Size(); i++) |
@@ -362,10 +435,11 @@ LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) | |||
362 | for (i = 0; i < strings.Size(); i++) | 435 | for (i = 0; i < strings.Size(); i++) |
363 | { | 436 | { |
364 | const UString &s = strings[i]; | 437 | const UString &s = strings[i]; |
365 | size_t size = s.Len() + 1; | 438 | const size_t size = s.Len() + 1; |
366 | wmemcpy(buffer + pos, s, size); | 439 | wmemcpy(buffer + pos, s, size); |
367 | pos += size; | 440 | pos += size; |
368 | } | 441 | } |
442 | // if (pos != numChars) return E_FAIL; | ||
369 | return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); | 443 | return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); |
370 | } | 444 | } |
371 | 445 | ||
@@ -373,20 +447,18 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) | |||
373 | { | 447 | { |
374 | strings.Clear(); | 448 | strings.Clear(); |
375 | CByteBuffer buffer; | 449 | CByteBuffer buffer; |
376 | UInt32 dataSize = 0; | 450 | const LONG res = QueryValue_Binary(valueName, buffer); |
377 | const LONG res = QueryValue(valueName, buffer, dataSize); | ||
378 | if (res != ERROR_SUCCESS) | 451 | if (res != ERROR_SUCCESS) |
379 | return res; | 452 | return res; |
380 | if (dataSize > buffer.Size()) | 453 | const size_t dataSize = buffer.Size(); |
381 | return E_FAIL; | 454 | if (dataSize % sizeof(wchar_t)) |
382 | if (dataSize % sizeof(wchar_t) != 0) | 455 | return ERROR_INVALID_DATA; |
383 | return E_FAIL; | ||
384 | |||
385 | const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; | 456 | const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; |
386 | const size_t numChars = dataSize / sizeof(wchar_t); | 457 | const size_t numChars = dataSize / sizeof(wchar_t); |
458 | // we can check that all names are finished | ||
459 | // if (numChars != 0 && data[numChars - 1] != 0) return ERROR_INVALID_DATA; | ||
387 | size_t prev = 0; | 460 | size_t prev = 0; |
388 | UString s; | 461 | UString s; |
389 | |||
390 | for (size_t i = 0; i < numChars; i++) | 462 | for (size_t i = 0; i < numChars; i++) |
391 | { | 463 | { |
392 | if (data[i] == 0) | 464 | if (data[i] == 0) |
@@ -396,7 +468,6 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) | |||
396 | prev = i + 1; | 468 | prev = i + 1; |
397 | } | 469 | } |
398 | } | 470 | } |
399 | |||
400 | return res; | 471 | return res; |
401 | } | 472 | } |
402 | 473 | ||
diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h index 0d3b4fc..74ee919 100644 --- a/CPP/Windows/Registry.h +++ b/CPP/Windows/Registry.h | |||
@@ -14,6 +14,13 @@ LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) | |||
14 | class CKey | 14 | class CKey |
15 | { | 15 | { |
16 | HKEY _object; | 16 | HKEY _object; |
17 | |||
18 | LONG QueryValueEx(LPCTSTR lpValueName, LPDWORD lpType, | ||
19 | LPBYTE lpData, LPDWORD lpcbData) | ||
20 | { | ||
21 | return RegQueryValueEx(_object, lpValueName, NULL, lpType, lpData, lpcbData); | ||
22 | } | ||
23 | |||
17 | public: | 24 | public: |
18 | CKey(): _object(NULL) {} | 25 | CKey(): _object(NULL) {} |
19 | ~CKey() { Close(); } | 26 | ~CKey() { Close(); } |
@@ -22,13 +29,14 @@ public: | |||
22 | void Attach(HKEY key) { _object = key; } | 29 | void Attach(HKEY key) { _object = key; } |
23 | HKEY Detach() | 30 | HKEY Detach() |
24 | { | 31 | { |
25 | HKEY key = _object; | 32 | const HKEY key = _object; |
26 | _object = NULL; | 33 | _object = NULL; |
27 | return key; | 34 | return key; |
28 | } | 35 | } |
29 | 36 | ||
30 | LONG Create(HKEY parentKey, LPCTSTR keyName, | 37 | LONG Create(HKEY parentKey, LPCTSTR keyName, |
31 | LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, | 38 | LPTSTR keyClass = REG_NONE, |
39 | DWORD options = REG_OPTION_NON_VOLATILE, | ||
32 | REGSAM accessMask = KEY_ALL_ACCESS, | 40 | REGSAM accessMask = KEY_ALL_ACCESS, |
33 | LPSECURITY_ATTRIBUTES securityAttributes = NULL, | 41 | LPSECURITY_ATTRIBUTES securityAttributes = NULL, |
34 | LPDWORD disposition = NULL) throw(); | 42 | LPDWORD disposition = NULL) throw(); |
@@ -40,18 +48,18 @@ public: | |||
40 | LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); | 48 | LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); |
41 | 49 | ||
42 | LONG DeleteValue(LPCTSTR name) throw(); | 50 | LONG DeleteValue(LPCTSTR name) throw(); |
43 | #ifndef _UNICODE | 51 | #ifndef _UNICODE |
44 | LONG DeleteValue(LPCWSTR name); | 52 | LONG DeleteValue(LPCWSTR name); |
45 | #endif | 53 | #endif |
46 | 54 | ||
47 | LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); | 55 | LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); |
48 | LONG SetValue(LPCTSTR valueName, bool value) throw(); | 56 | LONG SetValue(LPCTSTR valueName, bool value) throw(); |
49 | LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); | 57 | LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); |
50 | // LONG SetValue(LPCTSTR valueName, const CSysString &value); | 58 | // LONG SetValue(LPCTSTR valueName, const CSysString &value); |
51 | #ifndef _UNICODE | 59 | #ifndef _UNICODE |
52 | LONG SetValue(LPCWSTR name, LPCWSTR value); | 60 | LONG SetValue(LPCWSTR name, LPCWSTR value); |
53 | // LONG SetValue(LPCWSTR name, const UString &value); | 61 | // LONG SetValue(LPCWSTR name, const UString &value); |
54 | #endif | 62 | #endif |
55 | 63 | ||
56 | LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); | 64 | LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); |
57 | 65 | ||
@@ -60,21 +68,25 @@ public: | |||
60 | 68 | ||
61 | LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); | 69 | LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); |
62 | 70 | ||
63 | LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); | 71 | // GetValue_[type]_IfOk(): |
64 | LONG QueryValue(LPCTSTR name, bool &value) throw(); | 72 | // if (return_result == ERROR_SUCCESS), (value) variable was read from registry |
65 | LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); | 73 | // if (return_result != ERROR_SUCCESS), (value) variable was not changed |
66 | LONG QueryValue(LPCTSTR name, CSysString &value); | 74 | LONG GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw(); |
67 | 75 | LONG GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw(); | |
68 | LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); | 76 | LONG GetValue_bool_IfOk(LPCTSTR name, bool &value) throw(); |
69 | LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); | ||
70 | 77 | ||
71 | #ifndef _UNICODE | 78 | // QueryValue(): |
72 | LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); | 79 | // if (return_result == ERROR_SUCCESS), (value) string was read from registry |
80 | // if (return_result != ERROR_SUCCESS), (value) string was cleared | ||
81 | LONG QueryValue(LPCTSTR name, CSysString &value); | ||
82 | #ifndef _UNICODE | ||
73 | LONG QueryValue(LPCWSTR name, UString &value); | 83 | LONG QueryValue(LPCWSTR name, UString &value); |
74 | #endif | 84 | #endif |
75 | 85 | ||
76 | LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); | 86 | // QueryValue_Binary(): |
77 | LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); | 87 | // if (return_result == ERROR_SUCCESS), (value) buffer was read from registry (BINARY data) |
88 | // if (return_result != ERROR_SUCCESS), (value) buffer was cleared | ||
89 | LONG QueryValue_Binary(LPCTSTR name, CByteBuffer &value); | ||
78 | 90 | ||
79 | LONG EnumKeys(CSysStringVector &keyNames); | 91 | LONG EnumKeys(CSysStringVector &keyNames); |
80 | }; | 92 | }; |
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 03c8988..4745785 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp | |||
@@ -25,6 +25,69 @@ namespace NSystem { | |||
25 | 25 | ||
26 | #ifdef _WIN32 | 26 | #ifdef _WIN32 |
27 | 27 | ||
28 | /* | ||
29 | note: returned value in 32-bit version can be limited by value 32. | ||
30 | while 64-bit version returns full value. | ||
31 | GetMaximumProcessorCount(groupNumber) can return higher value than | ||
32 | GetActiveProcessorCount(groupNumber) in some cases, because CPUs can be added. | ||
33 | */ | ||
34 | // typedef DWORD (WINAPI *Func_GetMaximumProcessorCount)(WORD GroupNumber); | ||
35 | typedef DWORD (WINAPI *Func_GetActiveProcessorCount)(WORD GroupNumber); | ||
36 | typedef WORD (WINAPI *Func_GetActiveProcessorGroupCount)(VOID); | ||
37 | /* | ||
38 | #if 0 && defined(ALL_PROCESSOR_GROUPS) | ||
39 | #define MY_ALL_PROCESSOR_GROUPS ALL_PROCESSOR_GROUPS | ||
40 | #else | ||
41 | #define MY_ALL_PROCESSOR_GROUPS 0xffff | ||
42 | #endif | ||
43 | */ | ||
44 | |||
45 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
46 | |||
47 | bool CCpuGroups::Load() | ||
48 | { | ||
49 | NumThreadsTotal = 0; | ||
50 | GroupSizes.Clear(); | ||
51 | const HMODULE hmodule = ::GetModuleHandleA("kernel32.dll"); | ||
52 | // Is_Win11_Groups = GetProcAddress(hmodule, "SetThreadSelectedCpuSetMasks") != NULL; | ||
53 | const | ||
54 | Func_GetActiveProcessorGroupCount | ||
55 | fn_GetActiveProcessorGroupCount = Z7_GET_PROC_ADDRESS( | ||
56 | Func_GetActiveProcessorGroupCount, hmodule, | ||
57 | "GetActiveProcessorGroupCount"); | ||
58 | const | ||
59 | Func_GetActiveProcessorCount | ||
60 | fn_GetActiveProcessorCount = Z7_GET_PROC_ADDRESS( | ||
61 | Func_GetActiveProcessorCount, hmodule, | ||
62 | "GetActiveProcessorCount"); | ||
63 | if (!fn_GetActiveProcessorGroupCount || | ||
64 | !fn_GetActiveProcessorCount) | ||
65 | return false; | ||
66 | |||
67 | const unsigned numGroups = fn_GetActiveProcessorGroupCount(); | ||
68 | if (numGroups == 0) | ||
69 | return false; | ||
70 | UInt32 sum = 0; | ||
71 | for (unsigned i = 0; i < numGroups; i++) | ||
72 | { | ||
73 | const UInt32 num = fn_GetActiveProcessorCount((WORD)i); | ||
74 | /* | ||
75 | if (num == 0) | ||
76 | { | ||
77 | // it means error | ||
78 | // but is it possible that some group is empty by some reason? | ||
79 | // GroupSizes.Clear(); | ||
80 | // return false; | ||
81 | } | ||
82 | */ | ||
83 | sum += num; | ||
84 | GroupSizes.Add(num); | ||
85 | } | ||
86 | NumThreadsTotal = sum; | ||
87 | // NumThreadsTotal = fn_GetActiveProcessorCount(MY_ALL_PROCESSOR_GROUPS); | ||
88 | return true; | ||
89 | } | ||
90 | |||
28 | UInt32 CountAffinity(DWORD_PTR mask) | 91 | UInt32 CountAffinity(DWORD_PTR mask) |
29 | { | 92 | { |
30 | UInt32 num = 0; | 93 | UInt32 num = 0; |
@@ -38,31 +101,62 @@ UInt32 CountAffinity(DWORD_PTR mask) | |||
38 | 101 | ||
39 | BOOL CProcessAffinity::Get() | 102 | BOOL CProcessAffinity::Get() |
40 | { | 103 | { |
41 | #ifndef UNDER_CE | 104 | IsGroupMode = false; |
42 | return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); | 105 | Groups.Load(); |
43 | #else | 106 | // SetThreadAffinityMask(GetCurrentThread(), 1); |
44 | return FALSE; | 107 | // SetProcessAffinityMask(GetCurrentProcess(), 1); |
45 | #endif | 108 | BOOL res = GetProcessAffinityMask(GetCurrentProcess(), |
109 | &processAffinityMask, &systemAffinityMask); | ||
110 | /* DOCs: On a system with more than 64 processors, if the threads | ||
111 | of the calling process are in a single processor group, the | ||
112 | function sets the variables pointed to by lpProcessAffinityMask | ||
113 | and lpSystemAffinityMask to the process affinity mask and the | ||
114 | processor mask of active logical processors for that group. | ||
115 | If the calling process contains threads in multiple groups, | ||
116 | the function returns zero for both affinity masks | ||
117 | |||
118 | note: tested in Win10: GetProcessAffinityMask() doesn't return 0 | ||
119 | in (processAffinityMask) and (systemAffinityMask) masks. | ||
120 | We need to test it in Win11: how to get mask==0 from GetProcessAffinityMask()? | ||
121 | */ | ||
122 | if (!res) | ||
123 | { | ||
124 | processAffinityMask = 0; | ||
125 | systemAffinityMask = 0; | ||
126 | } | ||
127 | if (Groups.GroupSizes.Size() > 1 && Groups.NumThreadsTotal) | ||
128 | if (// !res || | ||
129 | processAffinityMask == 0 || // to support case described in DOCs and for (!res) case | ||
130 | processAffinityMask == systemAffinityMask) // for default nonchanged affinity | ||
131 | { | ||
132 | // we set IsGroupMode only if processAffinity is default (not changed). | ||
133 | res = TRUE; | ||
134 | IsGroupMode = true; | ||
135 | } | ||
136 | return res; | ||
46 | } | 137 | } |
47 | 138 | ||
48 | 139 | ||
140 | UInt32 CProcessAffinity::Load_and_GetNumberOfThreads() | ||
141 | { | ||
142 | if (Get()) | ||
143 | { | ||
144 | const UInt32 numProcessors = GetNumProcessThreads(); | ||
145 | if (numProcessors) | ||
146 | return numProcessors; | ||
147 | } | ||
148 | SYSTEM_INFO systemInfo; | ||
149 | GetSystemInfo(&systemInfo); | ||
150 | // the number of logical processors in the current group | ||
151 | return systemInfo.dwNumberOfProcessors; | ||
152 | } | ||
153 | |||
49 | UInt32 GetNumberOfProcessors() | 154 | UInt32 GetNumberOfProcessors() |
50 | { | 155 | { |
51 | // We need to know how many threads we can use. | 156 | // We need to know how many threads we can use. |
52 | // By default the process is assigned to one group. | 157 | // By default the process is assigned to one group. |
53 | // So we get the number of logical processors (threads) | ||
54 | // assigned to current process in the current group. | ||
55 | // Group size can be smaller than total number logical processors, for exammple, 2x36 | ||
56 | |||
57 | CProcessAffinity pa; | 158 | CProcessAffinity pa; |
58 | 159 | return pa.Load_and_GetNumberOfThreads(); | |
59 | if (pa.Get() && pa.processAffinityMask != 0) | ||
60 | return pa.GetNumProcessThreads(); | ||
61 | |||
62 | SYSTEM_INFO systemInfo; | ||
63 | GetSystemInfo(&systemInfo); | ||
64 | // the number of logical processors in the current group | ||
65 | return (UInt32)systemInfo.dwNumberOfProcessors; | ||
66 | } | 160 | } |
67 | 161 | ||
68 | #else | 162 | #else |
@@ -142,9 +236,9 @@ typedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer); | |||
142 | #endif // !UNDER_CE | 236 | #endif // !UNDER_CE |
143 | 237 | ||
144 | 238 | ||
145 | bool GetRamSize(UInt64 &size) | 239 | bool GetRamSize(size_t &size) |
146 | { | 240 | { |
147 | size = (UInt64)(sizeof(size_t)) << 29; | 241 | size = (size_t)sizeof(size_t) << 29; |
148 | 242 | ||
149 | #ifndef UNDER_CE | 243 | #ifndef UNDER_CE |
150 | MY_MEMORYSTATUSEX stat; | 244 | MY_MEMORYSTATUSEX stat; |
@@ -167,11 +261,23 @@ bool GetRamSize(UInt64 &size) | |||
167 | "GlobalMemoryStatusEx"); | 261 | "GlobalMemoryStatusEx"); |
168 | if (fn && fn(&stat)) | 262 | if (fn && fn(&stat)) |
169 | { | 263 | { |
170 | size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); | 264 | // (MY_MEMORYSTATUSEX::ullTotalVirtual) < 4 GiB in 32-bit mode |
265 | size_t size2 = (size_t)0 - 1; | ||
266 | if (size2 > stat.ullTotalPhys) | ||
267 | size2 = (size_t)stat.ullTotalPhys; | ||
268 | if (size2 > stat.ullTotalVirtual) | ||
269 | size2 = (size_t)stat.ullTotalVirtual; | ||
270 | size = size2; | ||
171 | return true; | 271 | return true; |
172 | } | 272 | } |
173 | #endif | 273 | #endif |
174 | 274 | ||
275 | // On computers with more than 4 GB of memory: | ||
276 | // new docs : GlobalMemoryStatus can report (-1) value to indicate an overflow. | ||
277 | // some old docs : GlobalMemoryStatus can report (modulo 4 GiB) value. | ||
278 | // (for example, if 5 GB total memory, it could report 1 GB). | ||
279 | // We don't want to get (modulo 4 GiB) value. | ||
280 | // So we use GlobalMemoryStatusEx() instead. | ||
175 | { | 281 | { |
176 | MEMORYSTATUS stat2; | 282 | MEMORYSTATUS stat2; |
177 | stat2.dwLength = sizeof(stat2); | 283 | stat2.dwLength = sizeof(stat2); |
@@ -187,9 +293,11 @@ bool GetRamSize(UInt64 &size) | |||
187 | // POSIX | 293 | // POSIX |
188 | // #include <stdio.h> | 294 | // #include <stdio.h> |
189 | 295 | ||
190 | bool GetRamSize(UInt64 &size) | 296 | bool GetRamSize(size_t &size) |
191 | { | 297 | { |
192 | size = (UInt64)(sizeof(size_t)) << 29; | 298 | UInt64 size64; |
299 | size = (size_t)sizeof(size_t) << 29; | ||
300 | size64 = size; | ||
193 | 301 | ||
194 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 302 | #if defined(__APPLE__) || defined(__DragonFly__) || \ |
195 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 303 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) |
@@ -215,7 +323,7 @@ bool GetRamSize(UInt64 &size) | |||
215 | // we use strict check (size_sys == sizeof(val)) for returned value | 323 | // we use strict check (size_sys == sizeof(val)) for returned value |
216 | // because big-endian encoding is possible: | 324 | // because big-endian encoding is possible: |
217 | if (res == 0 && size_sys == sizeof(val) && val) | 325 | if (res == 0 && size_sys == sizeof(val) && val) |
218 | size = val; | 326 | size64 = val; |
219 | else | 327 | else |
220 | { | 328 | { |
221 | uint32_t val32 = 0; | 329 | uint32_t val32 = 0; |
@@ -223,12 +331,12 @@ bool GetRamSize(UInt64 &size) | |||
223 | res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); | 331 | res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); |
224 | // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); | 332 | // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); |
225 | if (res == 0 && size_sys == sizeof(val32) && val32) | 333 | if (res == 0 && size_sys == sizeof(val32) && val32) |
226 | size = val32; | 334 | size64 = val32; |
227 | } | 335 | } |
228 | 336 | ||
229 | #elif defined(_AIX) | 337 | #elif defined(_AIX) |
230 | #if defined(_SC_AIX_REALMEM) // AIX | 338 | #if defined(_SC_AIX_REALMEM) // AIX |
231 | size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; | 339 | size64 = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; |
232 | #endif | 340 | #endif |
233 | #elif 0 || defined(__sun) | 341 | #elif 0 || defined(__sun) |
234 | #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) | 342 | #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) |
@@ -240,7 +348,7 @@ bool GetRamSize(UInt64 &size) | |||
240 | // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); | 348 | // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); |
241 | // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); | 349 | // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); |
242 | if (phys_pages != -1 && page_size != -1) | 350 | if (phys_pages != -1 && page_size != -1) |
243 | size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; | 351 | size64 = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; |
244 | } | 352 | } |
245 | #endif | 353 | #endif |
246 | #elif defined(__gnu_hurd__) | 354 | #elif defined(__gnu_hurd__) |
@@ -253,7 +361,7 @@ bool GetRamSize(UInt64 &size) | |||
253 | struct sysinfo info; | 361 | struct sysinfo info; |
254 | if (::sysinfo(&info) != 0) | 362 | if (::sysinfo(&info) != 0) |
255 | return false; | 363 | return false; |
256 | size = (UInt64)info.mem_unit * info.totalram; | 364 | size64 = (UInt64)info.mem_unit * info.totalram; |
257 | /* | 365 | /* |
258 | printf("\n mem_unit = %lld", (UInt64)info.mem_unit); | 366 | printf("\n mem_unit = %lld", (UInt64)info.mem_unit); |
259 | printf("\n totalram = %lld", (UInt64)info.totalram); | 367 | printf("\n totalram = %lld", (UInt64)info.totalram); |
@@ -262,10 +370,9 @@ bool GetRamSize(UInt64 &size) | |||
262 | 370 | ||
263 | #endif | 371 | #endif |
264 | 372 | ||
265 | const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); | 373 | size = (size_t)1 << (sizeof(size_t) * 8 - 1); |
266 | if (size > kLimit) | 374 | if (size > size64) |
267 | size = kLimit; | 375 | size = (size_t)size64; |
268 | |||
269 | return true; | 376 | return true; |
270 | } | 377 | } |
271 | 378 | ||
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index b17111c..0c80373 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | #include "../Common/MyTypes.h" | 11 | #include "../Common/MyTypes.h" |
12 | #include "../Common/MyVector.h" | ||
12 | #include "../Common/MyWindows.h" | 13 | #include "../Common/MyWindows.h" |
13 | 14 | ||
14 | namespace NWindows { | 15 | namespace NWindows { |
@@ -16,6 +17,34 @@ namespace NSystem { | |||
16 | 17 | ||
17 | #ifdef _WIN32 | 18 | #ifdef _WIN32 |
18 | 19 | ||
20 | struct CCpuGroups | ||
21 | { | ||
22 | CRecordVector<UInt32> GroupSizes; | ||
23 | UInt32 NumThreadsTotal; // sum of threads in all groups | ||
24 | // bool Is_Win11_Groups; // useless | ||
25 | |||
26 | void Get_GroupSize_Min_Max(UInt32 &minSize, UInt32 &maxSize) const | ||
27 | { | ||
28 | unsigned num = GroupSizes.Size(); | ||
29 | UInt32 minSize2 = 0, maxSize2 = 0; | ||
30 | if (num) | ||
31 | { | ||
32 | minSize2 = (UInt32)0 - 1; | ||
33 | do | ||
34 | { | ||
35 | const UInt32 v = GroupSizes[--num]; | ||
36 | if (minSize2 > v) minSize2 = v; | ||
37 | if (maxSize2 < v) maxSize2 = v; | ||
38 | } | ||
39 | while (num); | ||
40 | } | ||
41 | minSize = minSize2; | ||
42 | maxSize = maxSize2; | ||
43 | } | ||
44 | bool Load(); | ||
45 | CCpuGroups(): NumThreadsTotal(0) {} | ||
46 | }; | ||
47 | |||
19 | UInt32 CountAffinity(DWORD_PTR mask); | 48 | UInt32 CountAffinity(DWORD_PTR mask); |
20 | 49 | ||
21 | struct CProcessAffinity | 50 | struct CProcessAffinity |
@@ -25,14 +54,28 @@ struct CProcessAffinity | |||
25 | DWORD_PTR processAffinityMask; | 54 | DWORD_PTR processAffinityMask; |
26 | DWORD_PTR systemAffinityMask; | 55 | DWORD_PTR systemAffinityMask; |
27 | 56 | ||
57 | CCpuGroups Groups; | ||
58 | bool IsGroupMode; | ||
59 | /* | ||
60 | IsGroupMode == true, if | ||
61 | Groups.GroupSizes.Size() > 1) && { dafalt affinity was not changed } | ||
62 | IsGroupMode == false, if single group or affinity was changed | ||
63 | */ | ||
64 | |||
65 | UInt32 Load_and_GetNumberOfThreads(); | ||
66 | |||
28 | void InitST() | 67 | void InitST() |
29 | { | 68 | { |
30 | // numProcessThreads = 1; | 69 | // numProcessThreads = 1; |
31 | // numSysThreads = 1; | 70 | // numSysThreads = 1; |
32 | processAffinityMask = 1; | 71 | processAffinityMask = 1; |
33 | systemAffinityMask = 1; | 72 | systemAffinityMask = 1; |
73 | IsGroupMode = false; | ||
74 | // Groups.NumThreadsTotal = 0; | ||
75 | // Groups.Is_Win11_Groups = false; | ||
34 | } | 76 | } |
35 | 77 | ||
78 | /* | ||
36 | void CpuZero() | 79 | void CpuZero() |
37 | { | 80 | { |
38 | processAffinityMask = 0; | 81 | processAffinityMask = 0; |
@@ -42,9 +85,23 @@ struct CProcessAffinity | |||
42 | { | 85 | { |
43 | processAffinityMask |= ((DWORD_PTR)1 << cpuIndex); | 86 | processAffinityMask |= ((DWORD_PTR)1 << cpuIndex); |
44 | } | 87 | } |
88 | */ | ||
45 | 89 | ||
46 | UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } | 90 | UInt32 GetNumProcessThreads() const |
47 | UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } | 91 | { |
92 | if (IsGroupMode) | ||
93 | return Groups.NumThreadsTotal; | ||
94 | // IsGroupMode == false | ||
95 | // so we don't want to use groups | ||
96 | // we return number of threads in default primary group: | ||
97 | return CountAffinity(processAffinityMask); | ||
98 | } | ||
99 | UInt32 GetNumSystemThreads() const | ||
100 | { | ||
101 | if (Groups.GroupSizes.Size() > 1 && Groups.NumThreadsTotal) | ||
102 | return Groups.NumThreadsTotal; | ||
103 | return CountAffinity(systemAffinityMask); | ||
104 | } | ||
48 | 105 | ||
49 | BOOL Get(); | 106 | BOOL Get(); |
50 | 107 | ||
@@ -122,7 +179,7 @@ struct CProcessAffinity | |||
122 | 179 | ||
123 | UInt32 GetNumberOfProcessors(); | 180 | UInt32 GetNumberOfProcessors(); |
124 | 181 | ||
125 | bool GetRamSize(UInt64 &size); // returns false, if unknown ram size | 182 | bool GetRamSize(size_t &size); // returns false, if unknown ram size |
126 | 183 | ||
127 | unsigned long Get_File_OPEN_MAX(); | 184 | unsigned long Get_File_OPEN_MAX(); |
128 | unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks(); | 185 | unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks(); |
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp index cfc6a90..35846e0 100644 --- a/CPP/Windows/SystemInfo.cpp +++ b/CPP/Windows/SystemInfo.cpp | |||
@@ -530,6 +530,28 @@ struct CCpuName | |||
530 | AString Microcode; | 530 | AString Microcode; |
531 | AString LargePages; | 531 | AString LargePages; |
532 | 532 | ||
533 | #ifdef _WIN32 | ||
534 | UInt32 MHz; | ||
535 | |||
536 | #ifdef MY_CPU_ARM64 | ||
537 | #define Z7_SYS_INFO_SHOW_ARM64_REGS | ||
538 | #endif | ||
539 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
540 | bool Arm64_ISAR0_EL1_Defined; | ||
541 | UInt64 Arm64_ISAR0_EL1; | ||
542 | #endif | ||
543 | #endif | ||
544 | |||
545 | #ifdef _WIN32 | ||
546 | CCpuName(): | ||
547 | MHz(0) | ||
548 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
549 | , Arm64_ISAR0_EL1_Defined(false) | ||
550 | , Arm64_ISAR0_EL1(0) | ||
551 | #endif | ||
552 | {} | ||
553 | #endif | ||
554 | |||
533 | void Fill(); | 555 | void Fill(); |
534 | 556 | ||
535 | void Get_Revision_Microcode_LargePages(AString &s) | 557 | void Get_Revision_Microcode_LargePages(AString &s) |
@@ -537,16 +559,46 @@ struct CCpuName | |||
537 | s.Empty(); | 559 | s.Empty(); |
538 | AddBracedString(s, Revision); | 560 | AddBracedString(s, Revision); |
539 | AddBracedString(s, Microcode); | 561 | AddBracedString(s, Microcode); |
540 | s.Add_OptSpaced(LargePages); | 562 | #ifdef _WIN32 |
563 | if (MHz != 0) | ||
564 | { | ||
565 | s.Add_Space_if_NotEmpty(); | ||
566 | s.Add_UInt32(MHz); | ||
567 | s += " MHz"; | ||
568 | } | ||
569 | #endif | ||
570 | if (!LargePages.IsEmpty()) | ||
571 | s.Add_OptSpaced(LargePages); | ||
572 | } | ||
573 | |||
574 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
575 | void Get_Registers(AString &s) | ||
576 | { | ||
577 | if (Arm64_ISAR0_EL1_Defined) | ||
578 | { | ||
579 | // ID_AA64ISAR0_EL1 | ||
580 | s.Add_OptSpaced("cp4030:"); | ||
581 | PrintHex(s, Arm64_ISAR0_EL1); | ||
582 | { | ||
583 | const unsigned sha2 = ((unsigned)(Arm64_ISAR0_EL1 >> 12) & 0xf) - 1; | ||
584 | if (sha2 < 2) | ||
585 | { | ||
586 | s += ":SHA256"; | ||
587 | if (sha2) | ||
588 | s += ":SHA512"; | ||
589 | } | ||
590 | } | ||
591 | } | ||
541 | } | 592 | } |
593 | #endif | ||
542 | }; | 594 | }; |
543 | 595 | ||
544 | void CCpuName::Fill() | 596 | void CCpuName::Fill() |
545 | { | 597 | { |
546 | CpuName.Empty(); | 598 | // CpuName.Empty(); |
547 | Revision.Empty(); | 599 | // Revision.Empty(); |
548 | Microcode.Empty(); | 600 | // Microcode.Empty(); |
549 | LargePages.Empty(); | 601 | // LargePages.Empty(); |
550 | 602 | ||
551 | AString &s = CpuName; | 603 | AString &s = CpuName; |
552 | 604 | ||
@@ -600,21 +652,32 @@ void CCpuName::Fill() | |||
600 | Revision += GetAnsiString(name); | 652 | Revision += GetAnsiString(name); |
601 | } | 653 | } |
602 | } | 654 | } |
655 | #ifdef _WIN32 | ||
656 | key.GetValue_UInt32_IfOk(TEXT("~MHz"), MHz); | ||
657 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
658 | /* | ||
659 | mapping arm64 registers to Windows registry: | ||
660 | CP 4000: MIDR_EL1 | ||
661 | CP 4020: ID_AA64PFR0_EL1 | ||
662 | CP 4021: ID_AA64PFR1_EL1 | ||
663 | CP 4028: ID_AA64DFR0_EL1 | ||
664 | CP 4029: ID_AA64DFR1_EL1 | ||
665 | CP 402C: ID_AA64AFR0_EL1 | ||
666 | CP 402D: ID_AA64AFR1_EL1 | ||
667 | CP 4030: ID_AA64ISAR0_EL1 | ||
668 | CP 4031: ID_AA64ISAR1_EL1 | ||
669 | CP 4038: ID_AA64MMFR0_EL1 | ||
670 | CP 4039: ID_AA64MMFR1_EL1 | ||
671 | CP 403A: ID_AA64MMFR2_EL1 | ||
672 | */ | ||
673 | if (key.GetValue_UInt64_IfOk(TEXT("CP 4030"), Arm64_ISAR0_EL1) == ERROR_SUCCESS) | ||
674 | Arm64_ISAR0_EL1_Defined = true; | ||
675 | #endif | ||
676 | #endif | ||
603 | LONG res[2]; | 677 | LONG res[2]; |
604 | CByteBuffer bufs[2]; | 678 | CByteBuffer bufs[2]; |
605 | { | 679 | res[0] = key.QueryValue_Binary(TEXT("Previous Update Revision"), bufs[0]); |
606 | for (unsigned i = 0; i < 2; i++) | 680 | res[1] = key.QueryValue_Binary(TEXT("Update Revision"), bufs[1]); |
607 | { | ||
608 | UInt32 size = 0; | ||
609 | res[i] = key.QueryValue(i == 0 ? | ||
610 | TEXT("Previous Update Revision") : | ||
611 | TEXT("Update Revision"), | ||
612 | bufs[i], size); | ||
613 | if (res[i] == ERROR_SUCCESS) | ||
614 | if (size != bufs[i].Size()) | ||
615 | res[i] = ERROR_SUCCESS + 1; | ||
616 | } | ||
617 | } | ||
618 | if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) | 681 | if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) |
619 | { | 682 | { |
620 | for (unsigned i = 0; i < 2; i++) | 683 | for (unsigned i = 0; i < 2; i++) |
@@ -747,9 +810,18 @@ void AddCpuFeatures(AString &s) | |||
747 | unsigned long h = MY_getauxval(AT_HWCAP); | 810 | unsigned long h = MY_getauxval(AT_HWCAP); |
748 | PrintHex(s, h); | 811 | PrintHex(s, h); |
749 | #ifdef MY_CPU_ARM64 | 812 | #ifdef MY_CPU_ARM64 |
813 | #ifndef HWCAP_SHA3 | ||
814 | #define HWCAP_SHA3 (1 << 17) | ||
815 | #endif | ||
816 | #ifndef HWCAP_SHA512 | ||
817 | #define HWCAP_SHA512 (1 << 21) | ||
818 | // #pragma message("=== HWCAP_SHA512 define === ") | ||
819 | #endif | ||
750 | if (h & HWCAP_CRC32) s += ":CRC32"; | 820 | if (h & HWCAP_CRC32) s += ":CRC32"; |
751 | if (h & HWCAP_SHA1) s += ":SHA1"; | 821 | if (h & HWCAP_SHA1) s += ":SHA1"; |
752 | if (h & HWCAP_SHA2) s += ":SHA2"; | 822 | if (h & HWCAP_SHA2) s += ":SHA2"; |
823 | if (h & HWCAP_SHA3) s += ":SHA3"; | ||
824 | if (h & HWCAP_SHA512) s += ":SHA512"; | ||
753 | if (h & HWCAP_AES) s += ":AES"; | 825 | if (h & HWCAP_AES) s += ":AES"; |
754 | if (h & HWCAP_ASIMD) s += ":ASIMD"; | 826 | if (h & HWCAP_ASIMD) s += ":ASIMD"; |
755 | #elif defined(MY_CPU_ARM) | 827 | #elif defined(MY_CPU_ARM) |
@@ -908,13 +980,18 @@ void GetSystemInfoText(AString &sRes) | |||
908 | } | 980 | } |
909 | } | 981 | } |
910 | { | 982 | { |
911 | AString s; | 983 | AString s, registers; |
912 | GetCpuName_MultiLine(s); | 984 | GetCpuName_MultiLine(s, registers); |
913 | if (!s.IsEmpty()) | 985 | if (!s.IsEmpty()) |
914 | { | 986 | { |
915 | sRes += s; | 987 | sRes += s; |
916 | sRes.Add_LF(); | 988 | sRes.Add_LF(); |
917 | } | 989 | } |
990 | if (!registers.IsEmpty()) | ||
991 | { | ||
992 | sRes += registers; | ||
993 | sRes.Add_LF(); | ||
994 | } | ||
918 | } | 995 | } |
919 | /* | 996 | /* |
920 | #ifdef MY_CPU_X86_OR_AMD64 | 997 | #ifdef MY_CPU_X86_OR_AMD64 |
@@ -932,8 +1009,8 @@ void GetSystemInfoText(AString &sRes) | |||
932 | } | 1009 | } |
933 | 1010 | ||
934 | 1011 | ||
935 | void GetCpuName_MultiLine(AString &s); | 1012 | void GetCpuName_MultiLine(AString &s, AString ®isters); |
936 | void GetCpuName_MultiLine(AString &s) | 1013 | void GetCpuName_MultiLine(AString &s, AString ®isters) |
937 | { | 1014 | { |
938 | CCpuName cpuName; | 1015 | CCpuName cpuName; |
939 | cpuName.Fill(); | 1016 | cpuName.Fill(); |
@@ -945,6 +1022,10 @@ void GetCpuName_MultiLine(AString &s) | |||
945 | s.Add_LF(); | 1022 | s.Add_LF(); |
946 | s += s2; | 1023 | s += s2; |
947 | } | 1024 | } |
1025 | registers.Empty(); | ||
1026 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
1027 | cpuName.Get_Registers(registers); | ||
1028 | #endif | ||
948 | } | 1029 | } |
949 | 1030 | ||
950 | 1031 | ||
diff --git a/CPP/Windows/SystemInfo.h b/CPP/Windows/SystemInfo.h index c2e2e3b..4601685 100644 --- a/CPP/Windows/SystemInfo.h +++ b/CPP/Windows/SystemInfo.h | |||
@@ -6,7 +6,7 @@ | |||
6 | #include "../Common/MyString.h" | 6 | #include "../Common/MyString.h" |
7 | 7 | ||
8 | 8 | ||
9 | void GetCpuName_MultiLine(AString &s); | 9 | void GetCpuName_MultiLine(AString &s, AString ®isters); |
10 | 10 | ||
11 | void GetOsInfoText(AString &sRes); | 11 | void GetOsInfoText(AString &sRes); |
12 | void GetSystemInfoText(AString &s); | 12 | void GetSystemInfoText(AString &s); |
diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h index d72f64c..75c1616 100644 --- a/CPP/Windows/Thread.h +++ b/CPP/Windows/Thread.h | |||
@@ -26,8 +26,10 @@ public: | |||
26 | { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); } | 26 | { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); } |
27 | WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet) | 27 | WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet) |
28 | { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); } | 28 | { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); } |
29 | 29 | ||
30 | #ifdef _WIN32 | 30 | #ifdef _WIN32 |
31 | WRes Create_With_Group(THREAD_FUNC_TYPE startAddress, LPVOID param, unsigned group, CAffinityMask affinity = 0) | ||
32 | { return Thread_Create_With_Group(&thread, startAddress, param, group, affinity); } | ||
31 | operator HANDLE() { return thread; } | 33 | operator HANDLE() { return thread; } |
32 | void Attach(HANDLE handle) { thread = handle; } | 34 | void Attach(HANDLE handle) { thread = handle; } |
33 | HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } | 35 | HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } |
@@ -36,7 +38,7 @@ public: | |||
36 | bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } | 38 | bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } |
37 | int GetPriority() { return ::GetThreadPriority(thread); } | 39 | int GetPriority() { return ::GetThreadPriority(thread); } |
38 | bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } | 40 | bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } |
39 | #endif | 41 | #endif |
40 | }; | 42 | }; |
41 | 43 | ||
42 | } | 44 | } |
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index bbd79ba..4e3bc59 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp | |||
@@ -258,8 +258,9 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, | |||
258 | FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0, | 258 | FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0, |
259 | Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, | 259 | Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, |
260 | Cygwin 2.9, mingw, MSVC 14, Android 9.0. | 260 | Cygwin 2.9, mingw, MSVC 14, Android 9.0. |
261 | Android NDK defines TIME_UTC but doesn't have the timespec_get(). | ||
261 | */ | 262 | */ |
262 | #if defined(TIME_UTC) | 263 | #if defined(TIME_UTC) && !defined(__ANDROID__) |
263 | #define ZIP7_USE_timespec_get | 264 | #define ZIP7_USE_timespec_get |
264 | // #pragma message("ZIP7_USE_timespec_get") | 265 | // #pragma message("ZIP7_USE_timespec_get") |
265 | #elif defined(CLOCK_REALTIME) | 266 | #elif defined(CLOCK_REALTIME) |
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index f41b393..703e22e 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs | |||
@@ -1,7 +1,7 @@ | |||
1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
2 | 2 | ||
3 | <?define VerMajor = "24" ?> | 3 | <?define VerMajor = "25" ?> |
4 | <?define VerMinor = "08" ?> | 4 | <?define VerMinor = "01" ?> |
5 | <?define VerBuild = "00" ?> | 5 | <?define VerBuild = "00" ?> |
6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> | 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> |
7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> | 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> |
diff --git a/DOC/License.txt b/DOC/License.txt index 8917dfc..bbb56a3 100644 --- a/DOC/License.txt +++ b/DOC/License.txt | |||
@@ -3,7 +3,7 @@ | |||
3 | License for use and distribution | 3 | License for use and distribution |
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
5 | 5 | ||
6 | 7-Zip Copyright (C) 1999-2024 Igor Pavlov. | 6 | 7-Zip Copyright (C) 1999-2025 Igor Pavlov. |
7 | 7 | ||
8 | The licenses for files are: | 8 | The licenses for files are: |
9 | 9 | ||
@@ -58,7 +58,7 @@ BSD 3-clause License in 7-Zip code | |||
58 | 58 | ||
59 | Copyright (c) 2015-2016, Apple Inc. All rights reserved. | 59 | Copyright (c) 2015-2016, Apple Inc. All rights reserved. |
60 | Copyright (c) Facebook, Inc. All rights reserved. | 60 | Copyright (c) Facebook, Inc. All rights reserved. |
61 | Copyright (c) 2023-2024 Igor Pavlov. | 61 | Copyright (c) 2023-2025 Igor Pavlov. |
62 | 62 | ||
63 | Text of the "BSD 3-clause License" | 63 | Text of the "BSD 3-clause License" |
64 | ---------------------------------- | 64 | ---------------------------------- |
@@ -102,7 +102,7 @@ BSD 2-clause License in 7-Zip code | |||
102 | XXH64 code in 7-Zip was derived from the original XXH64 code developed by Yann Collet. | 102 | XXH64 code in 7-Zip was derived from the original XXH64 code developed by Yann Collet. |
103 | 103 | ||
104 | Copyright (c) 2012-2021 Yann Collet. | 104 | Copyright (c) 2012-2021 Yann Collet. |
105 | Copyright (c) 2023-2024 Igor Pavlov. | 105 | Copyright (c) 2023-2025 Igor Pavlov. |
106 | 106 | ||
107 | Text of the "BSD 2-clause License" | 107 | Text of the "BSD 2-clause License" |
108 | ---------------------------------- | 108 | ---------------------------------- |
diff --git a/DOC/readme.txt b/DOC/readme.txt index 6d04c5a..cc89a39 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt | |||
@@ -1,9 +1,9 @@ | |||
1 | 7-Zip 24.07 Sources | 1 | 7-Zip 25.01 Sources |
2 | ------------------- | 2 | ------------------- |
3 | 3 | ||
4 | 7-Zip is a file archiver for Windows. | 4 | 7-Zip is a file archiver for Windows. |
5 | 5 | ||
6 | 7-Zip Copyright (C) 1999-2024 Igor Pavlov. | 6 | 7-Zip Copyright (C) 1999-2025 Igor Pavlov. |
7 | 7 | ||
8 | 8 | ||
9 | License Info | 9 | License Info |
@@ -73,8 +73,8 @@ All final 7-Zip binaries are compiled via makefiles, that provide best | |||
73 | optimization options. | 73 | optimization options. |
74 | 74 | ||
75 | 75 | ||
76 | How to compile with makefile | 76 | How to compile with makefile in Windows |
77 | ---------------------------- | 77 | --------------------------------------- |
78 | 78 | ||
79 | Some macronames can be defined for compiling with makefile: | 79 | Some macronames can be defined for compiling with makefile: |
80 | 80 | ||
@@ -88,6 +88,23 @@ MY_DYNAMIC_LINK | |||
88 | for dynamic linking to the run-time library (msvcrt.dll). | 88 | for dynamic linking to the run-time library (msvcrt.dll). |
89 | The default makefile option is static linking to the run-time library. | 89 | The default makefile option is static linking to the run-time library. |
90 | 90 | ||
91 | To compile all 7-Zip files for x64 with Visual Studio 2022, | ||
92 | use the following command sequence: | ||
93 | |||
94 | cd SRC\CPP\7zip | ||
95 | %comspec% /k "C:\Program Files\VS2022\VC\Auxiliary\Build\vcvars64.bat" | ||
96 | nmake | ||
97 | |||
98 | You can use another "vcvars*.bat" files from "VS2022\VC\Auxiliary\Build" directory | ||
99 | to compile for other platforms: | ||
100 | vcvars64.bat | ||
101 | vcvarsamd64_arm64.bat | ||
102 | vcvarsamd64_x86.bat | ||
103 | |||
104 | Also you can compile single binary from directory with related project. | ||
105 | For example, to compile 7za.exe, use the following command sequence: | ||
106 | cd SRC\CPP\7zip\Bundles\Alone\ | ||
107 | nmake | ||
91 | 108 | ||
92 | 109 | ||
93 | Compiling 7-Zip for Unix/Linux | 110 | Compiling 7-Zip for Unix/Linux |
@@ -100,12 +117,14 @@ So if you compile the version with Assembeler code, you will get faster 7-Zip bi | |||
100 | 7-Zip's assembler code uses the following syntax for different platforms: | 117 | 7-Zip's assembler code uses the following syntax for different platforms: |
101 | 118 | ||
102 | 1) x86 and x86-64 (AMD64): MASM syntax. | 119 | 1) x86 and x86-64 (AMD64): MASM syntax. |
103 | There are 2 programs that supports MASM syntax in Linux. | 120 | Now there are 3 programs that supports MASM syntax in Linux. |
104 | ' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some | 121 | ' 'Asmc Macro Assembler, JWasm, and UASM. Note that JWasm now doesn't support some |
105 | cpu instructions used in 7-Zip. | 122 | cpu instructions used in 7-Zip. |
106 | So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version | 123 | So you must install Asmc Macro Assembler in Linux or UASM, if you want to compile |
107 | of 7-Zip x86 and x86-64: | 124 | fastest version of 7-Zip x86 and x86-64: |
108 | https://github.com/nidud/asmc | 125 | https://github.com/nidud/asmc |
126 | https://github.com/Terraspace/UASM | ||
127 | |||
109 | 128 | ||
110 | 2) arm64: GNU assembler for ARM64 with preprocessor. | 129 | 2) arm64: GNU assembler for ARM64 with preprocessor. |
111 | That systax is supported by GCC and CLANG for ARM64. | 130 | That systax is supported by GCC and CLANG for ARM64. |
@@ -155,6 +174,13 @@ USE_JWASM=1 | |||
155 | Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c | 174 | Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c |
156 | will be used instead of assembler code from AesOpt.asm. | 175 | will be used instead of assembler code from AesOpt.asm. |
157 | 176 | ||
177 | If you want to use UASM for x86-64 compiling, you can change 7zip_gcc.mak, | ||
178 | or send IS_X64=1 USE_ASM=1 MY_ASM="$UASM" to make command calling: | ||
179 | UASM="$PWD/GccUnixR/uasm" | ||
180 | cd "7zip-src/CPP/7zip/Bundles/Alone2" | ||
181 | make -f makefile.gcc -j IS_X64=1 USE_ASM=1 MY_ASM="$UASM" | ||
182 | |||
183 | |||
158 | DISABLE_RAR=1 | 184 | DISABLE_RAR=1 |
159 | removes whole RAR related code from compilation. | 185 | removes whole RAR related code from compilation. |
160 | 186 | ||
diff --git a/DOC/src-history.txt b/DOC/src-history.txt index 1653c07..48c9647 100644 --- a/DOC/src-history.txt +++ b/DOC/src-history.txt | |||
@@ -1,6 +1,51 @@ | |||
1 | HISTORY of the 7-Zip source code | 1 | HISTORY of the 7-Zip source code |
2 | -------------------------------- | 2 | -------------------------------- |
3 | 3 | ||
4 | 25.01 2025-08-03 | ||
5 | ------------------------- | ||
6 | - The code for handling symbolic links has been changed | ||
7 | to provide greater security when extracting files from archives. | ||
8 | Command line switch -snld20 can be used to bypass default security | ||
9 | checks when creating symbolic links. | ||
10 | |||
11 | |||
12 | 25.00 2025-07-05 | ||
13 | ------------------------- | ||
14 | - 7-Zip for Windows can now use more than 64 CPU threads for compression | ||
15 | to zip/7z/xz archives and for the 7-Zip benchmark. | ||
16 | If there are more than one processor group in Windows (on systems with more than | ||
17 | 64 cpu threads), 7-Zip distributes running CPU threads across different processor groups. | ||
18 | - bzip2 compression speed was increased by 15-40%. | ||
19 | - deflate (zip/gz) compression speed was increased by 1-3%. | ||
20 | - improved support for zip, cpio and fat archives. | ||
21 | - fixed some bugs and vulnerabilities. | ||
22 | - the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives. | ||
23 | - the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives. | ||
24 | |||
25 | |||
26 | 24.09 2024-11-29 | ||
27 | ------------------------- | ||
28 | - The default dictionary size values for LZMA/LZMA2 compression methods were increased: | ||
29 | dictionary size compression level | ||
30 | v24.08 v24.09 v24.09 | ||
31 | 32-bit 64-bit | ||
32 | 8 MB 16 MB 16 MB -mx4 | ||
33 | 16 MB 32 MB 32 MB -mx5 : Normal | ||
34 | 32 MB 64 MB 64 MB -mx6 | ||
35 | 32 MB 64 MB 128 MB -mx7 : Maximum | ||
36 | 64 MB 64 MB 256 MB -mx8 | ||
37 | 64 MB 64 MB 256 MB -mx9 : Ultra | ||
38 | The default dictionary size values for 32-bit versions of LZMA/LZMA2 don't exceed 64 MB. | ||
39 | - 7-Zip now can calculate the following hash checksums: SHA-512, SHA-384, SHA3-256 and MD5. | ||
40 | - APM and HFS support was improved. | ||
41 | - If an archive update operation uses a temporary archive folder and | ||
42 | the archive is moved to the destination folder, 7-Zip shows the progress of moving | ||
43 | the archive file, as this operation can take a long time if the archive is large. | ||
44 | - The bug was fixed: 7-Zip File Manager didn't propagate Zone.Identifier stream | ||
45 | for extacted files from nested archives (if there is open archive inside another open archive). | ||
46 | - Some bugs were fixed. | ||
47 | |||
48 | |||
4 | 24.08 2024-08-11 | 49 | 24.08 2024-08-11 |
5 | ------------------------- | 50 | ------------------------- |
6 | - The bug in 7-Zip 24.00-24.07 was fixed: | 51 | - The bug in 7-Zip 24.00-24.07 was fixed: |