📄 fastcopy.cpp
字号:
{ int new_dir_len = dir_len + sprintfV(MakeAddr(path, dir_len), FMT_CAT_ASTER_V, fname) -1; BOOL ret; int cur_skips = total.filterSkips; if (info.mode == DELETE_MODE && (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA))) { memcpy(MakeAddr(confirmDst, dir_len), MakeAddr(path, dir_len), (new_dir_len - dir_len + 2) * CHAR_LEN_V); } if (!IsReparse(stat->dwFileAttributes)) { if ((ret = DeleteProc(path, new_dir_len)), isAbort) return ret; } if (isFilter && (cur_skips != total.filterSkips || regExp[INC_EXP][FILE_EXP].IsRegistered())) return ret; SetChar(path, new_dir_len - 1, 0); if (info.flags & LISTING_ONLY) { PutList(MakeAddr(path, dstPrefixLen), PL_DIRECTORY|PL_DELETE); } else { if (!IsReparse(stat->dwFileAttributes)) SetFileAttributesV(path, stat->dwFileAttributes & ~FILE_ATTRIBUTE_READONLY); if (info.mode == DELETE_MODE && (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA))) { if (RenameRandomFname(dst, confirmDst, dir_len, new_dir_len-dir_len-1)) { path = confirmDst; } } if ((ret = RemoveDirectoryV(path)) == FALSE) { total.errDirs++; return ConfirmErr("RemoveDirectory", MakeAddr(path, dstPrefixLen)), FALSE; } } total.deleteDirs++; return ret;}BOOL FastCopy::DeleteFileProc(void *path, int dir_len, void *fname, FileStat *stat){ int len = sprintfV(MakeAddr(path, dir_len), FMT_STR_V, fname); if (info.flags & LISTING_ONLY) { PutList(MakeAddr(path, dstPrefixLen), PL_DELETE); } else { if (stat->dwFileAttributes & FILE_ATTRIBUTE_READONLY) SetFileAttributesV(path, FILE_ATTRIBUTE_NORMAL); if (info.mode == DELETE_MODE && (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA)) && !IsReparse(stat->dwFileAttributes)) { if (RenameRandomFname(dst, confirmDst, dir_len, len)) { path = confirmDst; } if (stat->FileSize()) { if (WriteRandomData(path, stat, TRUE) == FALSE) { total.errFiles++; return ConfirmErr("OverWrite", MakeAddr(path, dstPrefixLen)), FALSE; } total.writeFiles++; } } if (DeleteFileV(path) == FALSE) { total.errFiles++; return ConfirmErr("DeleteFile", MakeAddr(path, dstPrefixLen)), FALSE; } } total.deleteFiles++; total.deleteTrans += stat->FileSize(); return TRUE;}/*========================================================================= 奣 梫 丗 忋彂偒嶍彍梡儖乕僠儞=========================================================================*/void FastCopy::SetupRandomDataBuf(void){ RandomDataBuf *data = (RandomDataBuf *)mainBuf.Buf(); data->is_nsa = (info.flags & OVERWRITE_DELETE_NSA) ? TRUE : FALSE; data->base_size = max(PAGE_SIZE, dstSectorSize); data->buf_size = mainBuf.Size() - data->base_size; data->buf[0] = mainBuf.Buf() + data->base_size; if (data->is_nsa) { data->buf_size /= 3; data->buf_size = (data->buf_size / data->base_size) * data->base_size; data->buf_size = min(info.maxTransSize, data->buf_size); data->buf[1] = data->buf[0] + data->buf_size; data->buf[2] = data->buf[1] + data->buf_size; if (info.flags & OVERWRITE_PARANOIA) { TGenRandom(data->buf[0], data->buf_size); // CryptAPI偺rand偼抶偄... TGenRandom(data->buf[1], data->buf_size); } else { for (int i=0, max=data->buf_size / sizeof(int) * 2; i < max; i++) { *((int *)data->buf[0] + i) = rand(); } } memset(data->buf[2], 0, data->buf_size); } else { data->buf_size = min(info.maxTransSize, data->buf_size); if (info.flags & OVERWRITE_PARANOIA) { TGenRandom(data->buf[0], data->buf_size); // CryptAPI偺rand偼抶偄... } else { for (int i=0, max=data->buf_size / sizeof(int); i < max; i++) { *((int *)data->buf[0] + i) = rand(); } } }}void FastCopy::GenRandomName(void *path, int fname_len, int ext_len){ static char *char_dict = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for (int i=0; i < fname_len; i++) { SetChar(path, i, char_dict[(rand() >> 4) % 62]); } if (ext_len) { SetChar(path, fname_len - ext_len, '.'); } SetChar(path, fname_len, 0);}BOOL FastCopy::RenameRandomFname(void *org_path, void *rename_path, int dir_len, int fname_len){ void *fname = MakeAddr(org_path, dir_len); void *rename_fname = MakeAddr(rename_path, dir_len); void *dot = strrchrV(fname, '.'); int ext_len = dot ? fname_len - DiffLen(dot, fname) : 0; for (int i=fname_len; i <= MAX_FNAME_LEN; i++) { for (int j=0; j < 128; j++) { GenRandomName(rename_fname, i, ext_len); if (MoveFileV(org_path, rename_path)) { return TRUE; } else if (::GetLastError() != ERROR_ALREADY_EXISTS) { return FALSE; } } } return FALSE;}BOOL FastCopy::WriteRandomData(void *path, FileStat *stat, BOOL skip_hardlink){ BOOL isNonBuf = dstFsType != FSTYPE_NETWORK && (stat->FileSize() >= max(nbMinSize, PAGE_SIZE) || (stat->FileSize() % dstSectorSize) == 0) && (info.flags & USE_OSCACHE_WRITE) == 0 ? TRUE : FALSE; DWORD flg = (isNonBuf ? FILE_FLAG_NO_BUFFERING : 0) | FILE_FLAG_SEQUENTIAL_SCAN; DWORD trans_size; HANDLE hFile = CreateFileV(path, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, flg, 0); BOOL ret = TRUE; if (hFile == INVALID_HANDLE_VALUE) { return ConfirmErr("Write by Random Data(open)", MakeAddr(path, dstPrefixLen)), FALSE; } BY_HANDLE_FILE_INFORMATION bhi; if (!skip_hardlink || !::GetFileInformationByHandle(hFile, &bhi) || bhi.nNumberOfLinks <= 1) { RandomDataBuf *data = (RandomDataBuf *)mainBuf.Buf(); _int64 file_size = isNonBuf ? ALIGN_SIZE(stat->FileSize(), dstSectorSize) : stat->FileSize(); for (int i=0, end=data->is_nsa ? 3 : 1; i < end && ret; i++) { ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN); for (_int64 remain_size=file_size; remain_size > 0; remain_size -= trans_size) { if (!(ret = ::WriteFile(hFile, data->buf[i], (DWORD)(remain_size > data->buf_size ? data->buf_size : remain_size), &trans_size, NULL))) { break; } total.writeTrans += trans_size; } total.writeTrans -= file_size - stat->FileSize(); ::FlushFileBuffers(hFile); } ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN); ::SetEndOfFile(hFile); } ::CloseHandle(hFile); return ret;}/*========================================================================= 娭 悢 丗 WriteThread 奣 梫 丗 Write 張棟 愢 柧 丗 拲 堄 丗 =========================================================================*/unsigned WINAPI FastCopy::WriteThread(void *fastCopyObj){ return ((FastCopy *)fastCopyObj)->WriteThreadCore();}BOOL FastCopy::WriteThreadCore(void){ BOOL ret = WriteProc(dstBaseLen); if (info.mode == MOVE_MODE && !isAbort && errBuf.UsedSize() == 0 && total.errFiles == 0 && total.errDirs == 0) DeleteThreadCore(); // 僄儔乕偑側偄側傜丄僜乕僗偺嶍彍 else FinishNotify(); return ret;}BOOL FastCopy::FinishNotify(void){ endTick = ::GetTickCount(); return ::PostMessage(info.hNotifyWnd, info.uNotifyMsg, END_NOTIFY, 0);}BOOL FastCopy::WriteProc(int dir_len){ BOOL ret = TRUE; int new_dir_len; FileStat sv_stat; while (!isAbort) { if ((ret = RecvRequest()) == FALSE || writeReq->command == REQ_EOF) { break; } if (writeReq->command == WRITE_FILE || writeReq->command == WRITE_BACKUP_FILE) { if (writeReq->stat.renameCount == 0) new_dir_len = dir_len + sprintfV(MakeAddr(dst, dir_len), FMT_STR_V, writeReq->stat.cFileName); else new_dir_len = dir_len + MakeRenameName(MakeAddr(dst, dir_len), writeReq->stat.renameCount, writeReq->stat.cFileName); if (mkdirQueueBuf.UsedSize()) ExecDirQueue(); if (info.flags & LISTING_ONLY) { PutList(MakeAddr(dst, dstPrefixLen), PL_NORMAL); total.writeFiles++; total.writeTrans += writeReq->stat.FileSize(); } else if ((ret = WriteFileProc(new_dir_len)), isAbort) break; } else if (writeReq->command == MKDIR || writeReq->command == INTODIR) { BOOL is_mkdir = writeReq->command == MKDIR; BOOL is_reparse = IsReparse(writeReq->stat.dwFileAttributes) && (info.flags & DIR_REPARSE) == 0; int buf_size = writeReq->bufSize; memcpy(&sv_stat, &writeReq->stat, offsetof(FileStat, cFileName)); if (writeReq->stat.renameCount == 0) new_dir_len = dir_len + sprintfV(MakeAddr(dst, dir_len), FMT_STR_V, writeReq->stat.cFileName); else new_dir_len = dir_len + MakeRenameName(MakeAddr(dst, dir_len), writeReq->stat.renameCount, writeReq->stat.cFileName); if (buf_size) { dstDirExtBuf.AddUsedSize(buf_size); if (dstDirExtBuf.RemainSize() < MIN_DSTDIREXT_BUF && !dstDirExtBuf.Grow(MIN_DSTDIREXT_BUF)) { ConfirmErr("Can't alloc memory(dstDirExtBuf)", NULL, FALSE); break; } memcpy(dstDirExtBuf.Buf() + dstDirExtBuf.UsedSize(), writeReq->buf, buf_size); sv_stat.acl = dstDirExtBuf.Buf() + dstDirExtBuf.UsedSize(); sv_stat.ead = sv_stat.acl + sv_stat.aclSize; sv_stat.rep = sv_stat.ead + sv_stat.eadSize; } if (is_mkdir) { if (is_reparse || (info.flags & SKIP_EMPTYDIR) == 0) { if (info.flags & LISTING_ONLY) { PutList(MakeAddr(dst, dstPrefixLen), PL_DIRECTORY); } else { if (mkdirQueueBuf.UsedSize()) { ExecDirQueue(); } CreateDirectoryV(dst, NULL); } total.writeDirs++; } else { if (mkdirQueueBuf.RemainSize() < sizeof(int) && mkdirQueueBuf.Grow(MIN_MKDIRQUEUE_BUF) == FALSE) { ConfirmErr("Can't alloc memory(mkdirQueueBuf)", NULL, FALSE); break; } *(int *)(mkdirQueueBuf.Buf() + mkdirQueueBuf.UsedSize()) = new_dir_len; mkdirQueueBuf.AddUsedSize(sizeof(int)); } } strcpyV(MakeAddr(dst, new_dir_len), BACK_SLASH_V); if (!is_reparse) { if ((ret = WriteProc(new_dir_len + 1)), isAbort) // 嵞婣 break; } SetChar(dst, new_dir_len, 0); // 枛旜偺 '\\' 傪庢傞 if ((info.flags & LISTING_ONLY) == 0) { if (!is_mkdir || (info.flags & SKIP_EMPTYDIR) == 0 || mkdirQueueBuf.UsedSize() == 0 || is_reparse) { // 僞僀儉僗僞儞僾/ACL/懏惈/儕僷乕僗億僀儞僩偺僙僢僩 if ((ret = SetDirExtData(&sv_stat)) == FALSE && is_reparse && is_mkdir) { RemoveDirectoryV(dst); // 怴婯嶌惉僼僅儖僟偺儕僷乕僗億僀儞僩壔偵幐攕偟偨応崌偼丄僼僅儖僟嶍彍 } } } if (buf_size) { dstDirExtBuf.AddUsedSize(-buf_size); } if (mkdirQueueBuf.UsedSize()) { mkdirQueueBuf.AddUsedSize(-(int)sizeof(int)); } } else if (writeReq->command == DELETE_FILES) { if (IsDir(writeReq->stat.dwFileAttributes)) ret = DeleteDirProc(dst, dir_len, writeReq->stat.cFileName, &writeReq->stat); else ret = DeleteFileProc(dst, dir_len, writeReq->stat.cFileName, &writeReq->stat); } else if (writeReq->command == RETURN_PARENT) { break; } else { switch (writeReq->command) { case WRITE_ABORT: case WRITE_FILE_CONT: case WRITE_BACKUP_ACL: case WRITE_BACKUP_EADATA: case WRITE_BACKUP_ALTSTREAM: case WRITE_BACKUP_END: break; default: ret = FALSE; WCHAR cmd[2] = { writeReq->command + '0', 0 }; ConfirmErr("Illegal Request (internal error)", cmd, FALSE); break; } } } return ret && !isAbort;}BOOL FastCopy::ExecDirQueue(void){ for (int offset=0; offset < mkdirQueueBuf.UsedSize(); offset += sizeof(int)) { int dir_len = *(int *)(mkdirQueueBuf.Buf() + offset); SetChar(dst, dir_len, 0); if (info.flags & LISTING_ONLY) PutList(MakeAddr(dst, dstPrefixLen), PL_DIRECTORY); else CreateDirectoryV(dst, NULL); SetChar(dst, dir_len, '\\'); total.writeDirs++; } mkdirQueueBuf.SetUsedSize(0); return TRUE;}BOOL FastCopy::SetDirExtData(FileStat *stat){ if (stat->dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM)) SetFileAttributesV(dst, stat->dwFileAttributes); HANDLE fh; DWORD mode = GENERIC_WRITE | (stat->acl && enableAcl ? (WRITE_OWNER|WRITE_DAC) : 0); BOOL is_reparse = IsReparse(stat->dwFileAttributes) && (info.flags & DIR_REPARSE) == 0; BOOL ret = TRUE; if (!IS_WINNT_V || (fh = CreateFileV(dst, mode, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|(is_reparse ? FILE_FLAG_OPEN_REPARSE_POINT : 0), 0)) == INVALID_HANDLE_VALUE) { if (is_reparse) { total.errDirs++; } return FALSE; } if (is_reparse) { char rp[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; BOOL is_set = TRUE; if (ReadReparsePoint(fh, rp, sizeof(rp)) > 0) { if (IsReparseDataSame(rp, stat->rep)) { is_set = FALSE; } else { DeleteReparsePoint(fh, rp); } } if (is_set) { if (WriteReparsePoint(fh, stat->rep, stat->repSize) <= 0) { ret = FALSE; total.errDirs++; ConfirmErr("WriteReparsePoint(dir)", MakeAddr(dst, dstPrefixLen)); } } } if (stat->acl) { void *backupContent = NULL; DWORD size; if (!::BackupWrite(fh, stat->acl, stat->aclSize, &size, FALSE, TRUE, &backupContent)) { if (info.flags & REPORT_ACL_ERROR) ConfirmErr("BackupWrite(DIRACL)", MakeAddr(dst, dstPrefixLen)); } ::BackupWrite(fh, NULL, NULL, NULL, TRUE, TRUE, &backupContent); } ::SetFileTime(fh, &stat->ftCreationTime, &stat->ftLastAccessTime, &stat->ftLastWriteTime); SYSTEMTIME st; FileTimeToSystemTime(&stat->ftLastWrit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -