Improve detection of the last slice
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// verify.c
|
// verify.c
|
||||||
// Copyright : 2022-10-14 Yutaka Sawada
|
// Copyright : 2024-06-09 Yutaka Sawada
|
||||||
// License : GPL
|
// License : GPL
|
||||||
|
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
@@ -1253,21 +1253,22 @@ static int search_block_slide(
|
|||||||
slice_ctx *sc)
|
slice_ctx *sc)
|
||||||
{
|
{
|
||||||
unsigned char *buf, hash[16], hash2[16], err_mag, *short_use;
|
unsigned char *buf, hash[16], hash2[16], err_mag, *short_use;
|
||||||
int i, j, find_num, find_flag, find_next, find_last, short_next;
|
int i, j, find_num, find_flag, find_next, find_last, short_next, short2_next, tmp_next;
|
||||||
int block_count, short_count, tiny_count, tiny_skip, num, i1, i2, i3, i4;
|
int block_count, short_count, tiny_count, tiny_skip, num, i1, i2, i3, i4;
|
||||||
int *order, *index, index_shift;
|
int *order, *index, index_shift;
|
||||||
unsigned int len, off, end_off, err_off;
|
unsigned int len, off, end_off, err_off;
|
||||||
unsigned int prev_crc, fail_count, rear_off, overlap_count;
|
unsigned int prev_crc, fail_count, rear_off, overlap_count;
|
||||||
unsigned int crc, *crcs, *short_crcs;
|
unsigned int crc, *crcs, *short_crcs;
|
||||||
unsigned int time_last, time_slide;
|
unsigned int time_last, time_slide;
|
||||||
__int64 file_off, file_next, short_off, fail_off;
|
__int64 file_off, file_next, short_off, short2_off, tmp_off, fail_off;
|
||||||
|
|
||||||
if (file_size + 1 < last_off + (__int64)(sc->min_size))
|
if (file_size + 1 < last_off + (__int64)(sc->min_size))
|
||||||
return 0; // 小さすぎるファイルは調べない
|
return 0; // 小さすぎるファイルは調べない
|
||||||
find_num = 0; // このファイル内で何ブロック見つけたか
|
find_num = 0; // このファイル内で何ブロック見つけたか
|
||||||
find_next = -1; // 次に見つかると予想したブロックの番号
|
find_next = -1; // 次に見つかると予想したブロックの番号
|
||||||
find_last = -1; // 最後に見つけたブロックの番号 (-1=不明)
|
find_last = -1; // 最後に見つけたブロックの番号 (-1=不明)
|
||||||
short_next = -1;
|
short_next = -1; // 予想される末尾ブロックの番号
|
||||||
|
short2_next = -1;
|
||||||
fail_count = 0; // CRC は一致したけど MD5 が違った回数
|
fail_count = 0; // CRC は一致したけど MD5 が違った回数
|
||||||
fail_off = 0;
|
fail_off = 0;
|
||||||
rear_off = 0;
|
rear_off = 0;
|
||||||
@@ -1278,24 +1279,32 @@ static int search_block_slide(
|
|||||||
find_last = find_next - 1; // 最後に見つけたブロックの番号
|
find_last = find_next - 1; // 最後に見つけたブロックの番号
|
||||||
if ((last_off >= files[num1].size) || (last_off + block_size > file_size + 1))
|
if ((last_off >= files[num1].size) || (last_off + block_size > file_size + 1))
|
||||||
find_next = -1; // 予想位置がファイル・サイズを超えると駄目
|
find_next = -1; // 予想位置がファイル・サイズを超えると駄目
|
||||||
if ((last_size < block_size) && (files[num1].b_num >= 2) && // 末尾の半端なブロックの番号と想定位置
|
if ((last_size < block_size) && (last_off < files[num1].size)){ // 末尾の半端なブロックの番号と想定位置
|
||||||
(last_off < files[num1].size) && (files[num1].size <= file_size + 1)){
|
tmp_next = files[num1].b_off + files[num1].b_num - 1; // 末尾ブロックの番号
|
||||||
short_next = files[num1].b_off + files[num1].b_num - 1; // 末尾ブロックの番号
|
if (find_next == tmp_next)
|
||||||
if (find_next == short_next)
|
|
||||||
find_next = -1; // 予想が重複したら末尾ブロックとして探す
|
find_next = -1; // 予想が重複したら末尾ブロックとして探す
|
||||||
short_off = files[num1].size - last_size;
|
if ((files[num1].b_num >= 2) && (files[num1].size <= file_size + 1)){ // 本来の位置を調べる
|
||||||
// ファイルサイズが1ブロック未満でも、同じサイズならエラー訂正を試みる
|
short_next = tmp_next;
|
||||||
} else if ((last_off == 0) && (file_size == files[num1].size) && (file_size < (__int64)block_size)){
|
short_off = files[num1].size - last_size;
|
||||||
short_off = 0;
|
} else if ((last_off == 0) && (file_size == last_size)){ // ファイルが1ブロック未満でも、同じサイズならエラー訂正を試みる
|
||||||
short_next = files[num1].b_off;
|
short_next = tmp_next;
|
||||||
|
short_off = 0;
|
||||||
|
}
|
||||||
|
if (last_size < file_size){ // 末尾を調べる
|
||||||
|
short2_next = tmp_next;
|
||||||
|
short2_off = file_size - last_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (file_size > files[num1].size){
|
if (file_size > files[num1].size){
|
||||||
rear_off = (unsigned int)((file_size - files[num1].size) % (__int64)block_size);
|
rear_off = (unsigned int)((file_size - files[num1].size) % (__int64)block_size);
|
||||||
} else if (file_size < files[num1].size){
|
} else if (file_size < files[num1].size){
|
||||||
rear_off = block_size - (unsigned int)((files[num1].size - file_size) % (__int64)block_size);
|
rear_off = block_size - (unsigned int)((files[num1].size - file_size) % (__int64)block_size);
|
||||||
}
|
}
|
||||||
//printf("file = %d, find_next = %d, find_last = %d\n", num1, find_next, find_last);
|
/* printf("file = %d, find_next = %d, find_last = %d, rear_off = %d\n", num1, find_next, find_last, rear_off);
|
||||||
//printf("short_off = %I64d, short_next = %d, rear_off = %d\n", short_off, short_next, rear_off);
|
if (short_next >= 0)
|
||||||
|
printf("short_off = %I64d, short_next = %d\n", short_off, short_next);
|
||||||
|
if (short2_next >= 0)
|
||||||
|
printf("short2_off = %I64d, short2_next = %d\n", short2_off, short2_next);*/
|
||||||
}
|
}
|
||||||
file_off = last_off; // 検査開始位置から調べる
|
file_off = last_off; // 検査開始位置から調べる
|
||||||
buf = sc->buf;
|
buf = sc->buf;
|
||||||
@@ -1374,8 +1383,11 @@ static int search_block_slide(
|
|||||||
if (last_off < file_off + last_size)
|
if (last_off < file_off + last_size)
|
||||||
last_off = file_off + last_size; // 一番大きな半端なブロックの終端
|
last_off = file_off + last_size; // 一番大きな半端なブロックの終端
|
||||||
find_next = -2; // 小さなファイルが見つかった = ブロック検出の予想が外れた
|
find_next = -2; // 小さなファイルが見つかった = ブロック検出の予想が外れた
|
||||||
if (i == short_next)
|
if (i == short_next){ // この末尾ブロックは検出済み
|
||||||
short_next = -1; // 末尾ブロックは検出済み
|
short_next = -1;
|
||||||
|
} else if (i == short2_next){
|
||||||
|
short2_next = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// 経過表示
|
// 経過表示
|
||||||
if (GetTickCount() - time_last >= UPDATE_TIME){
|
if (GetTickCount() - time_last >= UPDATE_TIME){
|
||||||
@@ -1416,7 +1428,7 @@ static int search_block_slide(
|
|||||||
|
|
||||||
// ブロック・サイズごとに探す
|
// ブロック・サイズごとに探す
|
||||||
if (((block_count > 0) && ((file_off + (__int64)block_size <= file_size)
|
if (((block_count > 0) && ((file_off + (__int64)block_size <= file_size)
|
||||||
|| (find_next >= 0))) || (short_next >= 0)){ // ブロックの位置を予想して探す
|
|| (find_next >= 0))) || (short_next >= 0) || (short2_next >= 0)){ // ブロックの位置を予想して探す
|
||||||
// 前からスライドさせながらチェックサムを比較する
|
// 前からスライドさせながらチェックサムを比較する
|
||||||
//printf("slide search from %I64d, file %d, next = %d\n", file_off, num1, find_next);
|
//printf("slide search from %I64d, file %d, next = %d\n", file_off, num1, find_next);
|
||||||
off = 0; // buf 内でのオフセット
|
off = 0; // buf 内でのオフセット
|
||||||
@@ -1445,8 +1457,13 @@ static int search_block_slide(
|
|||||||
while (off < end_off){
|
while (off < end_off){
|
||||||
find_flag = -2;
|
find_flag = -2;
|
||||||
// 次の番号のブロックがその位置にあるかを先に調べる (発見済みでも)
|
// 次の番号のブロックがその位置にあるかを先に調べる (発見済みでも)
|
||||||
if ((short_next >= 0) && (file_off + off == short_off)){ // 半端なブロックなら
|
if (((short_next >= 0) && (file_off + off == short_off)) ||
|
||||||
i = short_next;
|
((short2_next >= 0) && (file_off + off == short2_off))){ // 半端なブロックなら
|
||||||
|
if ((short_next >= 0) && (file_off + off == short_off)){
|
||||||
|
i = short_next;
|
||||||
|
} else {
|
||||||
|
i = short2_next;
|
||||||
|
}
|
||||||
num = s_blk[i].file;
|
num = s_blk[i].file;
|
||||||
if ((short_use[num] & 4) == 0){ // パディング部分を取り除いた CRC-32 を逆算する
|
if ((short_use[num] & 4) == 0){ // パディング部分を取り除いた CRC-32 を逆算する
|
||||||
short_crcs[num] = crc_reverse_zero(s_blk[i].crc, block_size - s_blk[i].size);
|
short_crcs[num] = crc_reverse_zero(s_blk[i].crc, block_size - s_blk[i].size);
|
||||||
@@ -1456,7 +1473,8 @@ static int search_block_slide(
|
|||||||
find_flag = correct_error(buf + off, s_blk[i].size, s_blk[i].hash, short_crcs[num], &err_off, &err_mag);
|
find_flag = correct_error(buf + off, s_blk[i].size, s_blk[i].hash, short_crcs[num], &err_off, &err_mag);
|
||||||
if (find_flag == 0)
|
if (find_flag == 0)
|
||||||
find_flag = 2;
|
find_flag = 2;
|
||||||
} else if ((find_next >= 0) && (file_off + off == last_off)){ // フルサイズのブロックなら
|
}
|
||||||
|
if ((find_flag < 0) && (find_next >= 0) && (file_off + off == last_off)){ // フルサイズのブロックなら
|
||||||
i = find_next;
|
i = find_next;
|
||||||
if (crc == s_blk[i].crc){
|
if (crc == s_blk[i].crc){
|
||||||
data_md5(buf + off, block_size, hash);
|
data_md5(buf + off, block_size, hash);
|
||||||
@@ -1661,20 +1679,81 @@ static int search_block_slide(
|
|||||||
find_next = i + 1;
|
find_next = i + 1;
|
||||||
if ((find_next >= source_num) || (s_blk[find_next].file != num)){
|
if ((find_next >= source_num) || (s_blk[find_next].file != num)){
|
||||||
// 最後までいった、またはファイルが異なる
|
// 最後までいった、またはファイルが異なる
|
||||||
short_next = -1;
|
|
||||||
find_next = -1;
|
find_next = -1;
|
||||||
|
if ((short_next >= 0) && ((s_blk[short_next].exist & 0x1000) != 0))
|
||||||
|
short_next = -1;
|
||||||
|
if ((short2_next >= 0) && ((s_blk[short2_next].exist & 0x1000) != 0))
|
||||||
|
short2_next = -1;
|
||||||
} else if (s_blk[find_next].size < block_size){ // 半端なブロックは別に調べる
|
} else if (s_blk[find_next].size < block_size){ // 半端なブロックは別に調べる
|
||||||
short_next = find_next;
|
if (file_off + off + block_size + s_blk[find_next].size <= file_size){ // ファイル内に収まってる時だけ
|
||||||
short_off = file_off + off + block_size;
|
tmp_next = find_next;
|
||||||
//printf("short_off = %I64d, short_next = %d, file = %d\n", short_off, short_next, num);
|
tmp_off = file_off + off + block_size;
|
||||||
|
if (find_flag <= 3){ // 順当な位置で見つけた場合
|
||||||
|
if ((tmp_next == short_next) && (tmp_off == short_off)){
|
||||||
|
// 予測済みのと一致するなら何もしない
|
||||||
|
} else if ((short_next >= 0) && (short2_next < 0)){ // 予測と異なるけど、別のが空いてるなら、そっちに記録する
|
||||||
|
//printf("short2_off = %I64d, short2_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short2_next = tmp_next;
|
||||||
|
short2_off = tmp_off;
|
||||||
|
} else {
|
||||||
|
if ((short_next >= 0) && (tmp_next == short2_next) && (tmp_off == short2_off)){ // 既に予測済みのと一致するなら入れ替える
|
||||||
|
short2_next = short_next;
|
||||||
|
short2_off = short_off;
|
||||||
|
//printf("exchange short2_off = %I64d, short2_next = %d\n", short2_off, short2_next);
|
||||||
|
}
|
||||||
|
//printf("short_off = %I64d, short_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short_next = tmp_next;
|
||||||
|
short_off = tmp_off;
|
||||||
|
}
|
||||||
|
} else if ((short_next < 0) &&
|
||||||
|
(((__int64)block_size * (__int64)(tmp_next - files[num].b_off) == tmp_off) ||
|
||||||
|
(tmp_off + s_blk[tmp_next].size == file_size))){
|
||||||
|
// 検出ブロックが順当でなくても、末尾ブロックの開始位置や末端がファイル・サイズに一致すれば
|
||||||
|
//printf("short_off = %I64d, short_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short_next = tmp_next;
|
||||||
|
short_off = tmp_off;
|
||||||
|
} else {
|
||||||
|
//printf("short2_off = %I64d, short2_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short2_next = tmp_next;
|
||||||
|
short2_off = tmp_off;
|
||||||
|
}
|
||||||
|
}
|
||||||
find_next = -1;
|
find_next = -1;
|
||||||
} else {
|
} else {
|
||||||
short_next = files[num].b_off + files[num].b_num - 1; // 末尾ブロックの番号
|
tmp_next = files[num].b_off + files[num].b_num - 1; // 末尾ブロックの番号
|
||||||
if (s_blk[short_next].size < block_size){ // 半端なブロックは別に調べる
|
if (s_blk[tmp_next].size < block_size){ // 半端なブロックは別に調べる
|
||||||
short_off = file_off + off + (__int64)(short_next - i) * (__int64)block_size;
|
tmp_off = file_off + off + (__int64)(tmp_next - i) * (__int64)block_size;
|
||||||
//printf("short_off = %I64d, short_next = %d, file = %d\n", short_off, short_next, num);
|
if (tmp_off + s_blk[tmp_next].size <= file_size){ // ファイル内に収まってる時だけ
|
||||||
} else {
|
if (find_flag <= 3){ // 順当な位置で見つけた場合
|
||||||
short_next = -1;
|
if ((tmp_next == short_next) && (tmp_off == short_off)){
|
||||||
|
// 予測済みのと一致するなら何もしない
|
||||||
|
} else if ((short_next >= 0) && (short2_next < 0)){ // 予測と異なるけど、別のが空いてるなら、そっちに記録する
|
||||||
|
//printf("far short2_off = %I64d, short2_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short2_next = tmp_next;
|
||||||
|
short2_off = tmp_off;
|
||||||
|
} else {
|
||||||
|
if ((short_next >= 0) && (tmp_next == short2_next) && (tmp_off == short2_off)){ // 既に予測済みのと一致するなら入れ替える
|
||||||
|
short2_next = short_next;
|
||||||
|
short2_off = short_off;
|
||||||
|
//printf("exchange short2_off = %I64d, short2_next = %d\n", short2_off, short2_next);
|
||||||
|
}
|
||||||
|
//printf("far short_off = %I64d, short_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short_next = tmp_next;
|
||||||
|
short_off = tmp_off;
|
||||||
|
}
|
||||||
|
} else if ((short_next < 0) &&
|
||||||
|
(((__int64)block_size * (__int64)(tmp_next - files[num].b_off) == tmp_off) ||
|
||||||
|
(tmp_off + s_blk[tmp_next].size == file_size))){
|
||||||
|
// 検出ブロックが順当でなくても、末尾ブロックの開始位置や末端がファイル・サイズに一致すれば
|
||||||
|
//printf("far short_off = %I64d, short_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short_next = tmp_next;
|
||||||
|
short_off = tmp_off;
|
||||||
|
} else if ((short2_next != tmp_next) || (short2_off != tmp_off)){
|
||||||
|
//printf("far short2_off = %I64d, short2_next = %d, file = %d\n", tmp_off, tmp_next, num);
|
||||||
|
short2_next = tmp_next;
|
||||||
|
short2_off = tmp_off;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tiny_skip = 0; // 小さなファイルをブロック直後に一回だけ探す
|
tiny_skip = 0; // 小さなファイルをブロック直後に一回だけ探す
|
||||||
|
|||||||
Reference in New Issue
Block a user