⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastcopy.cpp

📁 fastcopy是一个非常快速的数据拷贝软件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			}			data = fileStatBuf.Buf() + fileStatBuf.UsedSize();			data_size = sid.Size.LowPart + STRMID_OFFSET;			fileStatBuf.AddUsedSize(data_size);			if (fileStatBuf.RemainSize() <= maxStatSize && !fileStatBuf.Grow(ALIGN_SIZE(maxStatSize + data_size, MIN_ATTR_BUF))) {				if (info.flags & REPORT_ACL_ERROR)					ConfirmErr("Can't alloc memory(fileStat(ACL/EADATA))", MakeAddr(src, srcPrefixLen), FALSE);				break;			}			memcpy(data, &sid, STRMID_OFFSET);			if (!::BackupRead(stat->hFile, data + STRMID_OFFSET, sid.Size.LowPart, &size, FALSE, TRUE, &context) || size <= 0) {				if (info.flags & REPORT_ACL_ERROR)					ConfirmErr("BackupRead(ACL/EADATA)", MakeAddr(src, srcPrefixLen));				break;			}			sid.Size.LowPart = 0;		}		if ((sid.Size.LowPart || sid.Size.HighPart) && !::BackupSeek(stat->hFile, sid.Size.LowPart, sid.Size.HighPart, &lowSeek, &highSeek, &context)) {			if (info.flags & (REPORT_ACL_ERROR|REPORT_STREAM_ERROR))				ConfirmErr("BackupSeek", MakeAddr(src, srcPrefixLen));			break;		}	}	::BackupRead(stat->hFile, 0, 0, 0, TRUE, FALSE, &context);	if (ret)		total.readAclStream++;	else		total.errAclStream++;	return	ret;}BOOL FastCopy::ReadMultiFilesProc(int dir_len){	for (int i=0; !isAbort && i < openFilesCnt; ) {		ReadFileProc(i, &i, dir_len);	}	return	!isAbort;}BOOL FastCopy::CloseMultiFilesProc(void){	if ((info.flags & LISTING_ONLY) == 0) {		for (int i=0; i < openFilesCnt; i++) {			if (openFiles[i]->hFile != INVALID_HANDLE_VALUE)				::CloseHandle(openFiles[i]->hFile);		}	}	openFilesCnt = 0;	return	!isAbort;}void *FastCopy::RestoreOpenFilePath(void *path, int idx, int dir_len){	FileStat	*stat = openFiles[idx];	BOOL		isStream = stat->dwFileAttributes ? FALSE : TRUE;	if (isStream) {		int	i;		for (i=idx-1; i >= 0; i--) {			if (openFiles[i]->dwFileAttributes) {				dir_len += sprintfV(MakeAddr(path, dir_len), FMT_STR_V, openFiles[i]->cFileName);				break;			}		}		if (i < 0)			ConfirmErr("RestoreOpenFilePath", MakeAddr(path, srcPrefixLen), FALSE);	}	sprintfV(MakeAddr(path, dir_len), FMT_STR_V, stat->cFileName);	return	path;}BOOL FastCopy::ReadFileProc(int start_idx, int *end_idx, int dir_len){	BOOL		ret = TRUE;	FileStat	*stat = openFiles[start_idx];	_int64		file_size = stat->FileSize();	DWORD		trans_size;	ReqBuf		req_buf;	Command		command = enableAcl || enableStream ? stat->dwFileAttributes ? WRITE_BACKUP_FILE : WRITE_BACKUP_ALTSTREAM : WRITE_FILE;	BOOL		isStream = command == WRITE_BACKUP_ALTSTREAM;	BOOL		is_reparse = IsReparse(stat->dwFileAttributes) && (info.flags & FILE_REPARSE) == 0;	BOOL		is_send_request = FALSE;	int			&totalFiles = isStream ? total.readAclStream : total.readFiles;	int			&totalErrFiles = isStream ? total.errAclStream  : total.errFiles;	*end_idx = start_idx + 1;//	ReadFile 偱懳張//	if (!is_reparse && IsReparse(stat->dwFileAttributes)) {		// reparse愭傪僐僺乕//		srcSectorSize = max(srcSectorSize, OPT_SECTOR_SIZE);//		sectorSize = max(srcSectorSize, dstSectorSize);//	}	if ((file_size == 0 && !is_reparse) || (info.flags & LISTING_ONLY)) {		ret = SendRequest(command, 0, stat);		is_send_request = TRUE;		if (command != WRITE_BACKUP_FILE || (info.flags & LISTING_ONLY))			return	ret;	}	if (stat->hFile == INVALID_HANDLE_VALUE) {		if (command != WRITE_BACKUP_ALTSTREAM && file_size > 0) {			::SetLastError(stat->lastError);			totalErrFiles++;		}		stat->SetFileSize(0);		if (isStream && !(info.flags & REPORT_STREAM_ERROR) || ConfirmErr(isStream ? "OpenFile(Stream)" : "OpenFile", MakeAddr(RestoreOpenFilePath(src, start_idx, dir_len), srcPrefixLen)) == Confirm::CONTINUE_RESULT) {			if ((info.flags & CREATE_OPENERR_FILE) && !is_send_request) {				SendRequest(command, 0, stat);				is_send_request = TRUE;			}		}		if (is_send_request && command == WRITE_BACKUP_FILE) {			SendRequest(WRITE_BACKUP_END, 0, 0);		}		return	FALSE;	}	if (is_reparse) {		BYTE	rd[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];		if ((stat->repSize = ReadReparsePoint(stat->hFile, rd, sizeof(rd))) <= 0 || PrepareReqBuf(offsetof(ReqHeader, stat) + stat->minSize, stat->repSize, stat->fileID, &req_buf) == FALSE) {			ConfirmErr("ReadReparsePoint(File)", MakeAddr(RestoreOpenFilePath(src, start_idx, dir_len), srcPrefixLen));			totalErrFiles++;			return	FALSE;		}		memcpy(req_buf.buf, rd, stat->repSize);		SendRequest(command, &req_buf, stat);		is_send_request = TRUE;	}	else {		::SetFilePointer(stat->hFile, 0, NULL, FILE_BEGIN);		for (_int64 remain_size=file_size; remain_size > 0; remain_size -= trans_size) {			trans_size = 0;			while (1) {				if ((ret = PrepareReqBuf(offsetof(ReqHeader, stat) + (is_send_request ? 0 : stat->minSize), remain_size, stat->fileID, &req_buf)) == FALSE)					break;				if ((ret = ::ReadFile(stat->hFile, req_buf.buf, req_buf.bufSize, &trans_size, NULL)))					break;				if (::GetLastError() == ERROR_INVALID_PARAMETER || sectorSize < OPT_SECTOR_SIZE) {	// reparse point 偱暿 volume 偵堏摦偟偨応崌梡					srcSectorSize = max(srcSectorSize, OPT_SECTOR_SIZE);					sectorSize = max(srcSectorSize, dstSectorSize);				}//	僄儔乕専弌傑偱偵帪娫偑偐偐傞偨傔丄堦扷丄儁儞僨傿儞僌//				else if (::GetLastError() == ERROR_NO_SYSTEM_RESOURCES && maxTransSize > MIN_BUF) {//					maxTransSize = maxTransSize / 2;//					maxTransSize = ALIGN_SIZE(maxTransSize, MIN_BUF);//					ConfirmErr("limit changed");//				}				else break;			}			if (!ret || trans_size != (DWORD)req_buf.bufSize && trans_size < remain_size) {				ret = FALSE;				totalErrFiles++;				if (isStream && !(info.flags & REPORT_STREAM_ERROR) || ConfirmErr(isStream ? "ReadFile(stream)" : ret && !trans_size ? "ReadFile(truncate)" : "ReadFile", MakeAddr(RestoreOpenFilePath(src, start_idx, dir_len), srcPrefixLen)) == Confirm::CONTINUE_RESULT) {					stat->SetFileSize(0);					req_buf.bufSize = 0;					if ((info.flags & CREATE_OPENERR_FILE) || is_send_request) {						SendRequest(is_send_request ? WRITE_ABORT : command, &req_buf, is_send_request ? 0 : stat);						is_send_request = TRUE;					}				}				break;			}			total.readTrans += trans_size;			SendRequest(is_send_request ? WRITE_FILE_CONT : command, &req_buf, is_send_request ? 0 : stat);			is_send_request = TRUE;			if (waitTick && remain_size > trans_size) Wait();		}	}	if (command == WRITE_BACKUP_FILE) {		while (ret && !isAbort && (*end_idx) < openFilesCnt && openFiles[(*end_idx)]->dwFileAttributes == 0) {			ret = ReadFileProc(*end_idx, end_idx, dir_len);		}		if (ret && stat->acl) {			if ((ret = PrepareReqBuf(offsetof(ReqHeader, stat) + stat->minSize, stat->aclSize, stat->fileID, &req_buf))) {				memcpy(req_buf.buf, stat->acl, stat->aclSize);				ret = SendRequest(WRITE_BACKUP_ACL, &req_buf, stat);			}		}		if (ret && stat->ead) {			if ((ret = PrepareReqBuf(offsetof(ReqHeader, stat) + stat->minSize, stat->eadSize, stat->fileID, &req_buf))) {				memcpy(req_buf.buf, stat->ead, stat->eadSize);				ret = SendRequest(WRITE_BACKUP_EADATA, &req_buf, stat);			}		}		if (!isAbort && is_send_request) {			SendRequest(WRITE_BACKUP_END, 0, 0);		}	}	return	ret && !isAbort;}void FastCopy::DstRequest(DstReqKind kind){	cv.Lock();	dstAsyncRequest = kind;	cv.Notify();	cv.UnLock();}BOOL FastCopy::WaitDstRequest(void){	cv.Lock();	while (dstAsyncRequest != DSTREQ_NONE && !isAbort)		cv.Wait(5000);	cv.UnLock();	return	dstRequestResult;}BOOL FastCopy::CheckDstRequest(void){	if (isAbort || dstAsyncRequest == DSTREQ_NONE)	return FALSE;	if (!isSameDrv)		cv.UnLock();	switch (dstAsyncRequest) {	case DSTREQ_READSTAT: dstRequestResult = ReadDstStat(); break;	case DSTREQ_DIGEST: dstRequestResult = MakeDigest(confirmDst, &dstDigestBuf, &dstDigest, dstDigestVal); break;	}	if (!isSameDrv) {		cv.Lock();		cv.Notify();	}	dstAsyncRequest = DSTREQ_NONE;	return	dstRequestResult;}BOOL FastCopy::ReadDstStat(void){	HANDLE		fh;	int			num = 0, len;	FileStat	*dstStat, **dstStatIdx;	WIN32_FIND_DATAW	fdat;	BOOL		ret = TRUE;	dstStat = (FileStat *)dstStatBuf.Buf();	dstStatIdx = (FileStat **)dstStatIdxBuf.Buf();	dstStatBuf.SetUsedSize(0);	dstStatIdxBuf.SetUsedSize(0);	if ((fh = FindFirstFileV(confirmDst, &fdat)) == INVALID_HANDLE_VALUE) {		if (::GetLastError() != ERROR_FILE_NOT_FOUND && strcmpV(MakeAddr(confirmDst, dstBaseLen), ASTERISK_V) == 0) {			ret = FALSE;			total.errDirs++;			ConfirmErr("FindFirstFile(stat)", MakeAddr(confirmDst, dstPrefixLen));		}	// 僼傽僀儖柤傪巜掕偟偰偺僐僺乕偱丄僐僺乕愭偑尒偮偐傜側偄応崌偼丄			// 僄儞僩儕側偟偱偺惉岟偲傒側偡		goto END;	}	do {		if (IsParentOrSelfDirs(fdat.cFileName))			continue;		dstStatIdx[num++] = dstStat;		len = FdatToFileStat(&fdat, dstStat, TRUE);		dstStatBuf.AddUsedSize(len);		// 師偺 stat 梡 buffer 偺僙僢僩		dstStat = (FileStat *)(dstStatBuf.Buf() + dstStatBuf.UsedSize());		dstStatIdxBuf.AddUsedSize(sizeof(FileStat *));		if (dstStatBuf.RemainSize() <= maxStatSize && dstStatBuf.Grow(MIN_ATTR_BUF) == FALSE) {			ConfirmErr("Can't alloc memory(dstStatBuf)", NULL, FALSE);			break;		}		if (dstStatIdxBuf.RemainSize() <= sizeof(FileStat *) && dstStatIdxBuf.Grow(MIN_ATTRIDX_BUF) == FALSE) {			ConfirmErr("Can't alloc memory(dstStatIdxBuf)", NULL, FALSE);			break;		}	}	while (!isAbort && FindNextFileV(fh, &fdat));	if (!isAbort && ::GetLastError() != ERROR_NO_MORE_FILES) {		total.errFiles++;		ret = FALSE;		ConfirmErr("FindNextFile(stat)", MakeAddr(confirmDst, dstPrefixLen));	}	::FindClose(fh);END:	if (ret)		ret = MakeHashTable();	return	ret;}BOOL FastCopy::MakeHashTable(void){	int		num = dstStatIdxBuf.UsedSize() / sizeof(FileStat *);	int		require_size = hash.RequireSize(num), grow_size;	if ((grow_size = require_size - dstStatIdxBuf.RemainSize()) > 0 && dstStatIdxBuf.Grow(ALIGN_SIZE(grow_size, MIN_ATTRIDX_BUF)) == FALSE) {		ConfirmErr("Can't alloc memory(dstStatIdxBuf2)", NULL, FALSE);		return	FALSE;	}	return	hash.Init((FileStat **)dstStatIdxBuf.Buf(), num, dstStatIdxBuf.Buf() + dstStatIdxBuf.UsedSize());}int StatHash::HashNum(int data_num){	return	data_num | 1;}BOOL StatHash::Init(FileStat **data, int data_num, void *tbl_buf){	hashNum = HashNum(data_num);	hashTbl = (FileStat **)tbl_buf;	memset(hashTbl, 0, hashNum * sizeof(FileStat *));	for (int i=0; i < data_num; i++) {		FileStat **stat = hashTbl+(data[i]->hashVal % hashNum);		while (*stat) {			stat = &(*stat)->next;		}		*stat = data[i];	}	return	TRUE;}FileStat *StatHash::Search(void *upperName, DWORD hash_val){	for (FileStat *target = hashTbl[hash_val % hashNum]; target; target = target->next) {		if (target->hashVal == hash_val && strcmpV(target->upperName, upperName) == 0)			return	target;	}	return	NULL;}/*=========================================================================  娭  悢 丗 DeleteThread  奣  梫 丗 DELETE_MODE 張棟  愢  柧 丗   拲  堄 丗 =========================================================================*/unsigned WINAPI FastCopy::DeleteThread(void *fastCopyObj){	return	((FastCopy *)fastCopyObj)->DeleteThreadCore();}BOOL FastCopy::DeleteThreadCore(void){	if ((info.flags & PRE_SEARCH) && info.mode == DELETE_MODE)		PreSearch();	for (int i=0; i < srcArray.Num() && !isAbort; i++) {		if (InitDeletePath(i))			DeleteProc(dst, dstBaseLen);	}	FinishNotify();	return	TRUE;}/*	嶍彍張棟*/BOOL FastCopy::DeleteProc(void *path, int dir_len){	HANDLE		hDir;	BOOL		ret = TRUE;	FileStat	stat;	WIN32_FIND_DATAW fdat;	if ((hDir = FindFirstFileV(path, &fdat)) == INVALID_HANDLE_VALUE) {		total.errDirs++;		return	ConfirmErr("FindFirstFile(del)", MakeAddr(path, dstPrefixLen)), FALSE;	}	do {		if (IsParentOrSelfDirs(fdat.cFileName))			continue;		if (waitTick) Wait((waitTick + 9) / 10);		// 嶍彍巜掕偟偨僨傿儗僋僩儕帺懱乮儖乕僩乯偱側偔偐偮丄僼傿儖僞乕彍奜懳徾		if (isFilter && (dstBaseLen != dir_len || isMetaSrc) && !FilterCheck(path, fdat.cFileName, fdat.dwFileAttributes)) {			total.filterSkips++;			continue;		}		stat.nFileSizeLow		= fdat.nFileSizeLow;		stat.nFileSizeHigh		= fdat.nFileSizeHigh;		stat.dwFileAttributes	= fdat.dwFileAttributes;		if (IsDir(stat.dwFileAttributes))			ret = DeleteDirProc(path, dir_len, fdat.cFileName, &stat);		else			ret = DeleteFileProc(path, dir_len, fdat.cFileName, &stat);	}	while (!isAbort && FindNextFileV(hDir, &fdat));	if (!isAbort && ret && ::GetLastError() != ERROR_NO_MORE_FILES) {		ret = FALSE;		ConfirmErr("FindNextFile(del)", MakeAddr(path, dstPrefixLen));	}	::FindClose(hDir);	return	ret && !isAbort;}BOOL FastCopy::DeleteDirProc(void *path, int dir_len, void *fname, FileStat *stat)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -