📄 fastcopy.cpp
字号:
if (isSameDrv) { if (IsDir(dstStat->dwFileAttributes)) ret = DeleteDirProc(confirmDst, confirm_len, dstStat->cFileName, dstStat); else ret = DeleteFileProc(confirmDst, confirm_len, dstStat->cFileName, dstStat); } else { SendRequest(DELETE_FILES, 0, dstStat); } if (isAbort) goto END; } } // 僨傿儗僋僩儕張棟 for (srcStat = (FileStat *)(dirStatBuf.Buf() + curDirStatSize); srcStat < statEnd; srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size)) { BOOL is_reparse = IsReparse(srcStat->dwFileAttributes) && (info.flags & DIR_REPARSE) == 0; total.readDirs++; ReqBuf req_buf = {0}; new_dir_len = dir_len + sprintfV(MakeAddr(src, dir_len), FMT_STR_V, srcStat->cFileName); if (confirm_dir && srcStat->isExists) sprintfV(MakeAddr(confirmDst, confirm_len), FMT_CAT_ASTER_V, srcStat->cFileName); if ((info.flags & LISTING_ONLY) == 0) { if (enableAcl || is_reparse) { GetDirExtData(&req_buf, srcStat); } }// ReadFile 偱懳張// if (!is_reparse && IsReparse(srcStat->dwFileAttributes)) {// srcSectorSize = max(srcSectorSize, OPT_SECTOR_SIZE);// sectorSize = max(srcSectorSize, dstSectorSize);// } new_dir_len += sprintfV(MakeAddr(src, new_dir_len), FMT_CAT_ASTER_V, L"") - 1; if (SendRequest(confirm_dir && srcStat->isExists ? INTODIR : MKDIR, req_buf.buf ? &req_buf : 0, srcStat), isAbort) goto END; if (!is_reparse) { if (ReadProc(new_dir_len, confirm_dir && srcStat->isExists), isAbort) goto END; if (SendRequest(RETURN_PARENT), isAbort) goto END; } }END: // 僇儗儞僩偺 dir梡Buf 僒僀僘傪暅尦 dirStatBuf.SetUsedSize(curDirStatSize); return ret && !isAbort;}BOOL FastCopy::GetDirExtData(ReqBuf *req_buf, FileStat *stat){ HANDLE fh; WIN32_STREAM_ID sid; DWORD size, lowSeek, highSeek; void *context = NULL; int altdata_cnt = 0; BYTE streamName[MAX_PATH * sizeof(WCHAR)]; BOOL ret = TRUE; BOOL is_reparse = IsReparse(stat->dwFileAttributes) && (info.flags & DIR_REPARSE) == 0; int used_size_save = dirStatBuf.UsedSize(); if ((fh = CreateFileV(src, GENERIC_READ|READ_CONTROL, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | (is_reparse ? FILE_FLAG_OPEN_REPARSE_POINT : 0), 0)) == INVALID_HANDLE_VALUE) return FALSE; if (is_reparse) { size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; if (dirStatBuf.RemainSize() <= (int)size + maxStatSize && dirStatBuf.Grow(ALIGN_SIZE(size + maxStatSize, MIN_ATTR_BUF)) == FALSE) { ret = FALSE; ConfirmErr("Can't alloc memory(dirStatBuf)", NULL, FALSE); } else if ((size = ReadReparsePoint(fh, dirStatBuf.Buf() + dirStatBuf.UsedSize(), size)) <= 0) { ret = FALSE; total.errDirs++; ConfirmErr("ReadReparsePoint(Dir)", MakeAddr(src, srcPrefixLen)); } else { stat->rep = dirStatBuf.Buf() + dirStatBuf.UsedSize(); stat->repSize = size; dirStatBuf.AddUsedSize(size); } } while (ret) { size = 0; ::SetLastError(0); if (!::BackupRead(fh, (LPBYTE)&sid, STRMID_OFFSET, &size, FALSE, TRUE, &context) || size != STRMID_OFFSET) { DWORD errCode = ::GetLastError(); if (errCode != 0 && errCode != ERROR_INVALID_HANDLE && (info.flags & REPORT_ACL_ERROR)) ConfirmErr("BackupRead(DIR)", MakeAddr(src, srcPrefixLen)); break; } if (sid.dwStreamNameSize && !::BackupRead(fh, streamName, sid.dwStreamNameSize, &size, FALSE, TRUE, &context)) { break; } if (sid.dwStreamId == BACKUP_SECURITY_DATA || sid.dwStreamId == BACKUP_EA_DATA) { BYTE *&data = sid.dwStreamId == BACKUP_SECURITY_DATA ? stat->acl : stat->ead; int &data_size = sid.dwStreamId == BACKUP_SECURITY_DATA ? stat->aclSize : stat->eadSize; if (data || sid.Size.HighPart) { // 偡偱偵奿擺嵪傒 if (info.flags & REPORT_ACL_ERROR) ConfirmErr("Duplicate or Too big ACL/EADATA(dir)", MakeAddr(src, srcPrefixLen)); break; } data = dirStatBuf.Buf() + dirStatBuf.UsedSize(); data_size = sid.Size.LowPart + STRMID_OFFSET; dirStatBuf.AddUsedSize(data_size); if (dirStatBuf.RemainSize() <= maxStatSize && !dirStatBuf.Grow(ALIGN_SIZE(maxStatSize + data_size, MIN_ATTR_BUF))) { if (info.flags & REPORT_ACL_ERROR) ConfirmErr("Can't alloc memory(dirStat(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(DirACL/EADATA)", MakeAddr(src, srcPrefixLen)); break; } sid.Size.LowPart = 0; } if ((sid.Size.LowPart || sid.Size.HighPart) && !::BackupSeek(fh, sid.Size.LowPart, sid.Size.HighPart, &lowSeek, &highSeek, &context)) { if (info.flags & REPORT_ACL_ERROR) ConfirmErr("BackupSeek(DIR)", MakeAddr(src, srcPrefixLen)); break; } } ::BackupRead(fh, NULL, NULL, NULL, TRUE, TRUE, &context); ::CloseHandle(fh); if (ret && (size = stat->aclSize + stat->eadSize + stat->repSize) > 0) { if ((ret = PrepareReqBuf(offsetof(ReqHeader, stat) + stat->minSize, size, stat->fileID, req_buf))) { BYTE *data = req_buf->buf; if (stat->acl) { memcpy(data, stat->acl, stat->aclSize); stat->acl = data; data += stat->aclSize; } if (stat->ead) { memcpy(data, stat->ead, stat->eadSize); stat->ead = data; data += stat->eadSize; } if (stat->rep) { memcpy(data, stat->rep, stat->repSize); stat->rep = data; data += stat->repSize; } } } dirStatBuf.SetUsedSize(used_size_save); return ret && !isAbort;}int FastCopy::MakeRenameName(void *buf, int count, void *fname){ void *ext = strrchrV(fname, '.'); int body_limit = ext ? DiffLen(ext, fname) : MAX_PATH; return sprintfV(buf, FMT_RENAME_V, body_limit, fname, count, ext ? ext : EMPTY_STR_V);}BOOL FastCopy::SetRenameCount(FileStat *stat){ while (1) { WCHAR new_name[MAX_PATH]; int len = MakeRenameName(new_name, ++stat->renameCount, stat->upperName) + 1; DWORD hash_val = hashVal.MakeHash(new_name, len * CHAR_LEN_V); if (hash.Search(new_name, hash_val) == NULL) break; } return TRUE;}/* 忋彂偒敾掕*/BOOL FastCopy::IsOverWriteFile(FileStat *srcStat, FileStat *dstStat){ if (info.overWrite == BY_NAME) return FALSE;// time stamp monitor#if 0 _int64 st = *(_int64 *)&srcStat->ftLastWriteTime; _int64 dt = *(_int64 *)&dstStat->ftLastWriteTime; if (st != dt && (info.flags & LISTING_ONLY)) { ::EnterCriticalSection(&listCs); int len = sprintfV(listBuf.Buf() + listBuf.UsedSize(), L" src/dst: %I64d / %I64d", st, dt); listBuf.AddUsedSize(len * CHAR_LEN_V); ::LeaveCriticalSection(&listCs); }#endif if (info.overWrite == BY_ATTR) { // 僒僀僘偑摍偟偔丄偐偮... if (dstStat->FileSize() == srcStat->FileSize()) { if (*(_int64 *)&dstStat->ftLastWriteTime == *(_int64 *)&srcStat->ftLastWriteTime) { // 峏怴擔晅偑姰慡偵摍偟偄 return FALSE; } if (srcFsType != FSTYPE_NTFS || dstFsType != FSTYPE_NTFS) { // 偳偪傜偐偑 NTFS 偱側偄応崌乮僱僢僩儚乕僋僪儔僀僽傪娷傓乯 // 曅曽偑 NTFS 偱側偄応崌丄1msec 枹枮偺岆嵎偼嫋梕偟偨忋偱丄斾妑乮UDF 懳嶔乯 if (*(_int64 *)&dstStat->ftLastWriteTime + 10000 >= *(_int64 *)&srcStat->ftLastWriteTime && *(_int64 *)&dstStat->ftLastWriteTime - 10000 <= *(_int64 *)&srcStat->ftLastWriteTime) { return FALSE; } // src 偐 dst 偺僞僀儉僗僞儞僾偺嵟彫扨埵偑 1 昩埲忋乮FAT or SAMBA 摍偺壜擻惈乯偱偐偮... if ((*(_int64 *)&srcStat->ftLastWriteTime % 10000000) == 0 || (*(_int64 *)&dstStat->ftLastWriteTime % 10000000) == 0) { // 僞僀儉僗僞儞僾偺嵎偑 2 昩埲撪側傜丄摨堦僞僀儉僗僞儞僾偲傒側偟偰丄忋彂偒偟側偄 if (*(_int64 *)&dstStat->ftLastWriteTime + 20000000 >= *(_int64 *)&srcStat->ftLastWriteTime && *(_int64 *)&dstStat->ftLastWriteTime - 20000000 <= *(_int64 *)&srcStat->ftLastWriteTime) return FALSE; } } } return TRUE; } if (info.overWrite == BY_LASTEST) { // 峏怴擔晅偑 dst 偲摨偠偐屆偄応崌偼峏怴偟側偄 if (*(_int64 *)&dstStat->ftLastWriteTime >= *(_int64 *)&srcStat->ftLastWriteTime) { return FALSE; } if (srcFsType != FSTYPE_NTFS || dstFsType != FSTYPE_NTFS) { // 偳偪傜偐偑 NTFS 偱側偄応崌乮僱僢僩儚乕僋僪儔僀僽傪娷傓乯 // 曅曽偑 NTFS 偱側偄応崌丄1msec 枹枮偺岆嵎偼嫋梕偟偨忋偱丄斾妑乮UDF 懳嶔乯 if (*(_int64 *)&dstStat->ftLastWriteTime + 10000 >= *(_int64 *)&srcStat->ftLastWriteTime) { return FALSE; } // src 偐 dst 偺僞僀儉僗僞儞僾偺嵟彫扨埵偑 1 昩埲忋乮FAT or SAMBA 摍偺壜擻惈乯偱偐偮... if ((*(_int64 *)&srcStat->ftLastWriteTime % 10000000) == 0 || (*(_int64 *)&dstStat->ftLastWriteTime % 10000000) == 0) { // 僞僀儉僗僞儞僾偺嵎偵 2 昩偺儅乕僕儞傪晅偗偨忋偱丄 峏怴擔晅偑 dst 偲摨偠偐屆偄応崌偼丄忋彂偒偟側偄 if (*(_int64 *)&dstStat->ftLastWriteTime + 20000000 >= *(_int64 *)&srcStat->ftLastWriteTime) return FALSE; } } return TRUE; } if (info.overWrite == BY_ALWAYS) return TRUE; return ConfirmErr("Illegal overwrite mode", 0, FALSE), FALSE;}BOOL FastCopy::ReadDirEntry(int dir_len, BOOL confirm_dir){ HANDLE fh; BOOL ret = TRUE; int len; WIN32_FIND_DATAW fdat; fileStatBuf.SetUsedSize(0); if ((fh = FindFirstFileV(src, &fdat)) == INVALID_HANDLE_VALUE) { total.errDirs++; return ConfirmErr("FindFirstFile", MakeAddr(src, srcPrefixLen)), FALSE; } do { if (IsParentOrSelfDirs(fdat.cFileName)) continue; // src 僨傿儗僋僩儕帺懱偵懳偟偰偼丄僼傿儖僞懳徾偵偟側偄 if (isFilter && (dir_len != srcBaseLen || isMetaSrc) && !FilterCheck(src, fdat.cFileName, fdat.dwFileAttributes)) continue; // 僨傿儗僋僩儕仌僼傽僀儖忣曬偺拁愊 if (IsDir(fdat.dwFileAttributes)) { len = FdatToFileStat(&fdat, (FileStat *)(dirStatBuf.Buf() + dirStatBuf.UsedSize()), confirm_dir); dirStatBuf.AddUsedSize(len); if (dirStatBuf.RemainSize() <= maxStatSize && dirStatBuf.Grow(MIN_ATTR_BUF) == FALSE) { ConfirmErr("Can't alloc memory(dirStatBuf)", NULL, FALSE); break; } } else { len = FdatToFileStat(&fdat, (FileStat *)(fileStatBuf.Buf() + fileStatBuf.UsedSize()), confirm_dir); fileStatBuf.AddUsedSize(len); if (fileStatBuf.RemainSize() <= maxStatSize && fileStatBuf.Grow(MIN_ATTR_BUF) == FALSE) { ConfirmErr("Can't alloc memory(fileStatBuf)", NULL, FALSE); break; } } } while (!isAbort && FindNextFileV(fh, &fdat)); if (!isAbort && ::GetLastError() != ERROR_NO_MORE_FILES) { total.errFiles++; ret = FALSE; ConfirmErr("FindNextFile", MakeAddr(src, srcPrefixLen)); } ::FindClose(fh); return ret && !isAbort;}BOOL FastCopy::OpenFileProc(FileStat *stat, int dir_len){ DWORD name_len = strlenV(stat->cFileName); memcpy(MakeAddr(src, dir_len), stat->cFileName, ((name_len + 1) * CHAR_LEN_V)); stat->fileID = nextFileID++; openFiles[openFilesCnt++] = stat; if (waitTick) Wait((waitTick + 9) / 10); BOOL is_backup = enableAcl || enableStream; BOOL is_reparse = IsReparse(stat->dwFileAttributes) && (info.flags & FILE_REPARSE) == 0; if (!is_backup && !is_reparse && stat->FileSize() == 0 || (info.flags & LISTING_ONLY)) return TRUE; DWORD mode = GENERIC_READ; DWORD flg = ((info.flags & USE_OSCACHE_READ) ? 0 : FILE_FLAG_SEQUENTIAL_SCAN) | FILE_FLAG_NO_BUFFERING; if (is_backup) { mode |= READ_CONTROL; flg |= FILE_FLAG_BACKUP_SEMANTICS; } if (is_reparse) { flg |= FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT; } if ((stat->hFile = CreateFileV(src, mode, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, flg, 0)) == INVALID_HANDLE_VALUE) { stat->lastError = ::GetLastError(); return FALSE; } return is_backup ? OpenFileBackupProc(stat, dir_len + name_len) : TRUE;}BOOL FastCopy::OpenFileBackupProc(FileStat *stat, int src_len){ WIN32_STREAM_ID sid; BOOL ret = FALSE; DWORD size = 0; DWORD lowSeek, highSeek; void *context = NULL; int altdata_cnt = 0; BYTE streamName[MAX_PATH * sizeof(WCHAR)]; DWORD flg = ((info.flags & USE_OSCACHE_READ) ? 0 : FILE_FLAG_NO_BUFFERING) | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_BACKUP_SEMANTICS; while (1) { ::SetLastError(0); if (!::BackupRead(stat->hFile, (LPBYTE)&sid, STRMID_OFFSET, &size, FALSE, TRUE, &context) || size != STRMID_OFFSET) { DWORD errCode = ::GetLastError(); if (errCode == 0 || errCode == ERROR_INVALID_HANDLE) ret = TRUE; else if (info.flags & (REPORT_ACL_ERROR|REPORT_STREAM_ERROR)) ConfirmErr("BackupRead(head)", MakeAddr(src, srcPrefixLen)); break; } if (sid.dwStreamNameSize) { if (!::BackupRead(stat->hFile, streamName, sid.dwStreamNameSize, &size, FALSE, TRUE, &context)) { if (info.flags & REPORT_STREAM_ERROR) ConfirmErr("BackupRead(name)", MakeAddr(src, srcPrefixLen)); break; } lSetCharV((LPBYTE)streamName + sid.dwStreamNameSize, 0, 0); // terminate 偝傟側偄偨傔乮dwStreamNameSize 偼僶僀僩悢乯 } if (sid.dwStreamId == BACKUP_ALTERNATE_DATA && enableStream) { FileStat *subStat = (FileStat *)(fileStatBuf.Buf() + fileStatBuf.UsedSize()); if (++altdata_cnt >= MAX_ALTSTREAM) { if (info.flags & REPORT_STREAM_ERROR) ConfirmErr("Too Many AltStream", MakeAddr(src, srcPrefixLen)); break; } openFiles[openFilesCnt++] = subStat; subStat->fileID = nextFileID++; subStat->hFile = INVALID_HANDLE_VALUE; subStat->nFileSizeLow = sid.Size.LowPart; subStat->nFileSizeHigh = sid.Size.HighPart; subStat->dwFileAttributes = 0; // ALTSTREAM subStat->renameCount = 0; subStat->lastError = 0; subStat->size = sid.dwStreamNameSize + offsetof(FileStat, cFileName); subStat->minSize = ALIGN_SIZE(subStat->size, 8); fileStatBuf.AddUsedSize(subStat->minSize); if (fileStatBuf.RemainSize() <= maxStatSize && fileStatBuf.Grow(MIN_ATTR_BUF) == FALSE) { ConfirmErr("Can't alloc memory(fileStatBuf2)", NULL, FALSE); break; } memcpy(subStat->cFileName, streamName, size + CHAR_LEN_V); memcpy(MakeAddr(src, src_len), subStat->cFileName, size + CHAR_LEN_V); if ((subStat->hFile = CreateFileV(src, GENERIC_READ|READ_CONTROL, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, flg, 0)) == INVALID_HANDLE_VALUE) { if (info.flags & REPORT_STREAM_ERROR) ConfirmErr("OpenFile(Stream)", MakeAddr(src, srcPrefixLen)); subStat->lastError = ::GetLastError(); break; } } else if ((sid.dwStreamId == BACKUP_SECURITY_DATA || sid.dwStreamId == BACKUP_EA_DATA) && enableAcl) { BYTE *&data = sid.dwStreamId == BACKUP_SECURITY_DATA ? stat->acl : stat->ead; int &data_size = sid.dwStreamId == BACKUP_SECURITY_DATA ? stat->aclSize : stat->eadSize; if (data || sid.Size.HighPart) { // 偡偱偵奿擺嵪傒 if (info.flags & REPORT_ACL_ERROR) ConfirmErr("Duplicate or Too big ACL/EADATA", MakeAddr(src, srcPrefixLen)); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -