📄 fastcopy.cpp
字号:
int len = lstrlenV(path = pathArray[kind].Path(idx)), targ = FILE_EXP; if (lGetCharV(path, len -1) == '\\') { lSetCharV(path, len -1, 0); targ = DIR_EXP; } if (!regExp[kind][targ].RegisterWildCard(path, RegExp::CASE_INSENSE)) return ConfirmErr("Bad or Too long windcard string", path, FALSE), FALSE; } } if (path) isFilter = TRUE; if ((info.flags & LISTING_ONLY) == 0 && (info.mode != DELETE_MODE || (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA))) && (info.bufSize > MAX_BUF || info.bufSize < MIN_BUF * 2)) return ConfirmErr("Too large or small Main Buffer.", NULL, FALSE), FALSE; if ((info.flags & (DIR_REPARSE|FILE_REPARSE)) && (info.mode == MOVE_MODE || info.mode == DELETE_MODE)) { return ConfirmErr("Illega Flags (junction/symlink)", NULL, FALSE), FALSE; } // command if (info.mode == DELETE_MODE) { srcArray = *_srcArray; if (InitDeletePath(0) == FALSE) return FALSE; } else { srcArray = *_srcArray; dstArray = *_dstArray; if (InitDstPath() == FALSE) return FALSE; if (InitSrcPath(0) == FALSE) return FALSE; } _info->isRenameMode = isRename; return !isAbort;}BOOL FastCopy::TakeExclusivePriv(void){ return ::WaitForSingleObject(hRunMutex, 0) == WAIT_OBJECT_0 ? TRUE : FALSE;}BOOL FastCopy::Start(void){ u_int id; int allocSize = (info.flags & LISTING_ONLY) ? MAX_LIST_BUF : info.bufSize+PAGE_SIZE; memset(&total, 0, sizeof(total)); if (info.flags & PRE_SEARCH) total.isPreSearch = TRUE; isAbort = FALSE; writeReq = NULL; isSuspend = FALSE; dstAsyncRequest = DSTREQ_NONE; nextFileID = 1; errFileID = 0; openFiles = NULL; cv.Initialize(2); // using condition valiable by 2 threads readReqList.Init(); writeReqList.Init(); errBuf.AllocBuf(MIN_ERR_BUF, MAX_ERR_BUF); if (info.flags & LISTING_ONLY) listBuf.AllocBuf(MIN_PUTLIST_BUF, MAX_PUTLIST_BUF); if (info.mode == DELETE_MODE) { if ((info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA)) && (info.flags & LISTING_ONLY) == 0) { if (mainBuf.AllocBuf(allocSize) == FALSE) { ConfirmErr("Can't alloc memory(delBuf)", NULL, FALSE); goto ERR; } SetupRandomDataBuf(); } startTick = ::GetTickCount(); if (!(hReadThread = (HANDLE)_beginthreadex(0, 0, FastCopy::DeleteThread, this, 0, &id))) goto ERR; return TRUE; } openFiles = new FileStat *[info.maxOpenFiles + MAX_ALTSTREAM]; /* for Alternate Stream */ openFilesCnt = 0; // src/dst dir-entry/attr 梡僶僢僼傽妋曐 fileStatBuf.AllocBuf(MIN_ATTR_BUF, info.maxAttrSize); dirStatBuf.AllocBuf(MIN_ATTR_BUF, info.maxDirSize); dstStatBuf.AllocBuf(MIN_ATTR_BUF, info.maxAttrSize); dstStatIdxBuf.AllocBuf(MIN_ATTRIDX_BUF, MAX_ATTRIDX_BUF(info.maxAttrSize)); if (info.flags & SKIP_EMPTYDIR) mkdirQueueBuf.AllocBuf(MIN_MKDIRQUEUE_BUF, MAX_MKDIRQUEUE_BUF); dstDirExtBuf.AllocBuf(MIN_DSTDIREXT_BUF, MAX_DSTDIREXT_BUF); // 儊僀儞儕儞僌僶僢僼傽妋曐 if (mainBuf.AllocBuf(allocSize) == FALSE && (info.flags & LISTING_ONLY) == 0) { ConfirmErr("Can't alloc memory(mainBuf)", NULL, FALSE); goto ERR; } // 儕儞僌僶僢僼傽梡僆僼僙僢僩弶婜壔 usedOffset = freeOffset = mainBuf.Buf(); if (IS_WINNT_V && info.isPhysLock) { ::SetProcessWorkingSetSize(::GetCurrentProcess(), mainBuf.Size() + APP_MEMSIZE, mainBuf.Size() + APP_MEMSIZE); mainBuf.LockBuf(); fileStatBuf.LockBuf(); dirStatBuf.LockBuf(); dstStatBuf.LockBuf(); dstStatIdxBuf.LockBuf(); } startTick = ::GetTickCount(); if (!(hReadThread = (HANDLE)_beginthreadex(0, 0, FastCopy::ReadThread, this, 0, &id)) || !(hWriteThread = (HANDLE)_beginthreadex(0, 0, FastCopy::WriteThread, this, 0, &id))) goto ERR; return TRUE;ERR: End(); return FALSE;}/*========================================================================= 娭 悢 丗 ReadThread 奣 梫 丗 Read 張棟 愢 柧 丗 拲 堄 丗 =========================================================================*/unsigned WINAPI FastCopy::ReadThread(void *fastCopyObj){ return ((FastCopy *)fastCopyObj)->ReadThreadCore();}BOOL FastCopy::ReadThreadCore(void){ BOOL isSameDrvOld; int done_cnt = 0; if (info.flags & PRE_SEARCH) PreSearch(); for (int i=0; i < srcArray.Num(); i++) { if (InitSrcPath(i)) { if (done_cnt >= 1 && isSameDrvOld != isSameDrv) ChangeToWriteMode(); ReadProc(srcBaseLen, info.overWrite == BY_ALWAYS ? FALSE : TRUE); isSameDrvOld = isSameDrv; done_cnt++; } if (isAbort) break; } SendRequest(REQ_EOF); ChangeToWriteMode(); return TRUE;}BOOL FastCopy::PreSearch(void){ BOOL is_delete = info.mode == DELETE_MODE; BOOL (FastCopy::*InitPath)(int) = is_delete ? &FastCopy::InitDeletePath : &FastCopy::InitSrcPath; void *&path = is_delete ? dst : src; int &prefix_len = is_delete ? dstPrefixLen : srcPrefixLen; int &base_len = is_delete ? dstBaseLen : srcBaseLen; BOOL ret = TRUE; for (int i=0; i < srcArray.Num(); i++) { if ((this->*InitPath)(i)) { if (!PreSearchProc(path, prefix_len, base_len)) ret = FALSE; } if (isAbort) break; } total.isPreSearch = FALSE; startTick = ::GetTickCount(); return ret && !isAbort;}BOOL FastCopy::FilterCheck(const void *path, const void *fname, DWORD attr){ int targ = IsDir(attr) ? DIR_EXP : FILE_EXP; if (regExp[EXC_EXP][targ].IsMatch(fname)) return FALSE; if (!regExp[INC_EXP][targ].IsRegistered()) return TRUE; if (regExp[INC_EXP][targ].IsMatch(fname)) return TRUE; return FALSE;}BOOL FastCopy::PreSearchProc(void *path, int prefix_len, int dir_len){ HANDLE hDir; BOOL ret = TRUE; WIN32_FIND_DATAW fdat; if (waitTick) Wait(1); if ((hDir = FindFirstFileV(path, &fdat)) == INVALID_HANDLE_VALUE) { return ConfirmErr("FindFirstFile(pre)", MakeAddr(path, prefix_len)), FALSE; } do { if (IsParentOrSelfDirs(fdat.cFileName)) continue; // src 僨傿儗僋僩儕帺懱偵懳偟偰偼丄僼傿儖僞懳徾偵偟側偄 if (isFilter && (dir_len != srcBaseLen || isMetaSrc) && !FilterCheck(path, fdat.cFileName, fdat.dwFileAttributes)) continue; if (IsDir(fdat.dwFileAttributes)) { total.preDirs++; if (!IsReparse(fdat.dwFileAttributes) || (info.flags & DIR_REPARSE)) { int len = sprintfV(MakeAddr(path, dir_len), FMT_CAT_ASTER_V, fdat.cFileName) -1; ret = PreSearchProc(path, prefix_len, dir_len + len); } } else { total.preFiles++; total.preTrans += (((_int64)fdat.nFileSizeHigh << 32) + fdat.nFileSizeLow); } } while (!isAbort && FindNextFileV(hDir, &fdat)); if (!isAbort && ret && ::GetLastError() != ERROR_NO_MORE_FILES) { ret = FALSE; ConfirmErr("FindNextFile(pre)", MakeAddr(path, prefix_len)); } ::FindClose(hDir); return ret && !isAbort;}BOOL FastCopy::PutList(void *path, DWORD opt){ BOOL add_backslash = GetChar(path, 0) == '\\' && GetChar(path, 1) != '\\'; ::EnterCriticalSection(&listCs); if (listBuf.RemainSize() >= MAX_PATHLEN_V || listBuf.Grow(MIN_PUTLIST_BUF)) { int len = sprintfV(listBuf.Buf() + listBuf.UsedSize(), listBuf.UsedSize() ? FMT_LIST2_V : FMT_LIST1_V, (opt & PL_DELETE) ? '-' : '+', add_backslash ? BACK_SLASH_V : EMPTY_STR_V, path, (opt & PL_DIRECTORY) ? L"\\" : (opt & PL_COMPARE) ? L" !!" : L""); listBuf.AddUsedSize(len * CHAR_LEN_V); } ::LeaveCriticalSection(&listCs); return TRUE;}BOOL FastCopy::MakeDigest(void *path, VBuf *vbuf, TDigest *digest, BYTE *val){ DWORD mode = GENERIC_READ; DWORD flg = ((info.flags & USE_OSCACHE_READ) ? 0 : FILE_FLAG_NO_BUFFERING) | FILE_FLAG_SEQUENTIAL_SCAN; if (enableAcl || enableStream) { mode |= READ_CONTROL; flg |= FILE_FLAG_BACKUP_SEMANTICS; } HANDLE hFile = CreateFileV(path, mode, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, flg, 0); BOOL ret = FALSE; memset(val, 0, SHA1_SIZE); digest->Reset(); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if (vbuf->MaxSize() >= maxTransSize || vbuf->AllocBuf(maxTransSize, maxTransSize)) { BY_HANDLE_FILE_INFORMATION bhi; if (::GetFileInformationByHandle(hFile, &bhi)) { _int64 remain_size = ((_int64)bhi.nFileSizeHigh << 32) + bhi.nFileSizeLow; while (remain_size > 0 && !isAbort) { DWORD trans_size = 0; if (::ReadFile(hFile, vbuf->Buf(), maxTransSize, &trans_size, NULL) && trans_size > 0) { digest->Update(vbuf->Buf(), trans_size); remain_size -= trans_size; } else { break; } } if (remain_size == 0) { ret = digest->GetVal(val); } } } ::CloseHandle(hFile); return ret;}BOOL FastCopy::IsSameContents(){ if (!isSameDrv) { DstRequest(DSTREQ_DIGEST); } BOOL src_ret = MakeDigest(src, &srcDigestBuf, &srcDigest, srcDigestVal); BOOL dst_ret = isSameDrv ? MakeDigest(confirmDst, &dstDigestBuf, &dstDigest, dstDigestVal) : WaitDstRequest(); return src_ret && dst_ret && memcmp(srcDigestVal, dstDigestVal, SHA1_SIZE) == 0 ? TRUE : FALSE;}BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir){ BOOL ret = TRUE; FileStat *srcStat, *statEnd; FileStat *dstStat = NULL; int new_dir_len, curDirStatSize; int confirm_len = dir_len + (dstBaseLen - srcBaseLen); BOOL is_rename_local = isRename; BOOL confirm_dir_local = confirm_dir || is_rename_local; isRename = FALSE; // top level 偺傒岠壥傪弌偡 if (waitTick) Wait(1); // 僇儗儞僩偺僒僀僘傪曐懚 curDirStatSize = dirStatBuf.UsedSize(); if (confirm_dir_local && !isSameDrv) DstRequest(DSTREQ_READSTAT); // 僨傿儗僋僩儕僄儞僩儕傪愭偵偡傋偰撉傒庢傞 ret = ReadDirEntry(dir_len, confirm_dir_local); if (confirm_dir_local && (isSameDrv ? ReadDstStat() : WaitDstRequest()) == FALSE || isAbort || !ret) return FALSE; // 僼傽僀儖傪愭偵張棟 statEnd = (FileStat *)(fileStatBuf.Buf() + fileStatBuf.UsedSize()); for (srcStat = (FileStat *)fileStatBuf.Buf(); srcStat < statEnd; srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size)) { if (confirm_dir_local) dstStat = hash.Search(srcStat->upperName, srcStat->hashVal); if (dstStat) { if (is_rename_local) { SetRenameCount(srcStat); } else { dstStat->isExists = TRUE; if (!IsOverWriteFile(srcStat, dstStat) && (IsReparse(srcStat->dwFileAttributes) == IsReparse(dstStat->dwFileAttributes) || (info.flags & FILE_REPARSE))) { if ((info.flags & LISTING_ONLY) && (info.flags & VERIFY_FILE)) { strcpyV(MakeAddr(confirmDst, confirm_len), srcStat->cFileName); strcpyV(MakeAddr(src, dir_len), srcStat->cFileName); if (!IsSameContents() && !isAbort) { PutList(MakeAddr(src, srcPrefixLen), PL_COMPARE|PL_NORMAL); } } total.skipFiles++; total.skipTrans += dstStat->FileSize(); continue; } } } total.readFiles++; if (OpenFileProc(srcStat, dir_len) == FALSE || srcFsType == FSTYPE_NETWORK || waitTick && openFilesCnt >= 10 || openFilesCnt >= info.maxOpenFiles) { ReadMultiFilesProc(dir_len); CloseMultiFilesProc(); } if (isAbort) goto END; } ReadMultiFilesProc(dir_len); CloseMultiFilesProc(); if (isAbort) goto END; statEnd = (FileStat *)(dirStatBuf.Buf() + dirStatBuf.UsedSize()); // 僨傿儗僋僩儕偺懚嵼妋擣 if (confirm_dir_local) { for (srcStat = (FileStat *)(dirStatBuf.Buf() + curDirStatSize); srcStat < statEnd; srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size)) { if ((dstStat = hash.Search(srcStat->upperName, srcStat->hashVal)) != NULL) { if (is_rename_local) SetRenameCount(srcStat); else srcStat->isExists = dstStat->isExists = TRUE; } else srcStat->isExists = FALSE; } } // SYNC儌乕僪偺応崌丄僐僺乕尦偵柍偄僼傽僀儖傪嶍彍 if (confirm_dir_local && info.mode == SYNCCP_MODE) { int max = dstStatIdxBuf.UsedSize() / sizeof(FileStat *); for (int i=0; i < max; i++) { if ((dstStat = ((FileStat **)dstStatIdxBuf.Buf())[i])->isExists) continue; if (isFilter && !FilterCheck(confirmDst, dstStat->cFileName, dstStat->dwFileAttributes)) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -