📄 fastcopy.h
字号:
/* static char *fastcopy_id =
"@(#)Copyright (C) H.Shirouzu 2004-2007 fastcopy.h Ver1.52"; */
/* ========================================================================
Project Name : Fast Copy file and directory
Create : 2004-09-15(Wed)
Update : 2007-02-06(Tue)
Copyright : H.Shirouzu
Reference :
======================================================================== */
#include "tlib.h"
#include "resource.h"
#include "utility.h"
#include "regexp.h"
#define ALIGN_SIZE(all_size, block_size) (((all_size) + (block_size) -1) / (block_size) * (block_size))
#define MIN_SECTOR_SIZE (512)
#define OPT_SECTOR_SIZE (2048)
#define MAX_BUF (1024 * 1024 * 1024)
#define MIN_BUF (1024 * 1024)
#define BIGTRANS_ALIGN (32 * 1024)
#define APP_MEMSIZE (6 * 1024 * 1024)
#define PATH_LOCAL_PREFIX L"\\\\?\\"
#define PATH_UNC_PREFIX L"\\\\?\\UNC"
#define PATH_LOCAL_PREFIX_LEN 4
#define PATH_UNC_PREFIX_LEN 7
#define MIN_ATTR_BUF (256 * 1024)
//#define MAX_ATTR_BUF (128 * 1024 * 1024)
#define MIN_ATTRIDX_BUF ALIGN_SIZE((MIN_ATTR_BUF / 4), PAGE_SIZE)
#define MAX_ATTRIDX_BUF(x) ALIGN_SIZE(((x) / 4), PAGE_SIZE)
#define MIN_MKDIRQUEUE_BUF (8 * 1024)
#define MAX_MKDIRQUEUE_BUF (64 * 1024)
#define MIN_ERR_BUF (32 * 1024)
#define MAX_ERR_BUF (64 * 1024)
#define MAX_LIST_BUF (128 * 1024)
#define MAX_PUTLIST_BUF (128 * 1024 * 1024)
#define MIN_PUTLIST_BUF (1024 * 1024)
#define FASTCOPY_MUTEX "FastCopyMutex"
#define FASTCOPY_EVENT "FastCopyEvent"
struct TotalTrans {
BOOL isPreSearch;
int preDirs;
int preFiles;
_int64 preTrans;
int readDirs;
int readFiles;
_int64 readTrans;
int writeDirs;
int writeFiles;
_int64 writeTrans;
int deleteDirs;
int deleteFiles;
_int64 deleteTrans;
int skipDirs;
int skipFiles;
_int64 skipTrans;
int filterSkips;
int errFiles;
int errDirs;
_int64 errTrans;
int openRetry;
};
struct TransInfo {
TotalTrans total;
DWORD tickCount;
BOOL isSameDrv;
BOOL ignoreErr;
DWORD autoSlow;
VBuf *errBuf;
CRITICAL_SECTION *errCs;
VBuf *listBuf;
CRITICAL_SECTION *listCs;
WCHAR curPath[MAX_PATH_EX];
};
struct FileStat {
_int64 fileID;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeLow; // WIN32_FIND_DATA 偺 nFileSizeLow/High
DWORD nFileSizeHigh; // 偲偼媡弴乮_int64 梡乯
DWORD dwFileAttributes;
HANDLE hFile;
DWORD lastError;
int renameCount;
BOOL isExists;
int size;
int minSize; // upperName 暘傪娷傔側偄
BYTE *upperName; // cFileName 廔抂+1傪巜偡
DWORD hashVal; // upperName 偺 hash抣
FileStat *next; // for hashTable
BYTE cFileName[4]; // 4 == dummy
_int64 FileSize() { return *(_int64 *)&nFileSizeLow; }
void SetFileSize(_int64 file_size) { *(_int64 *)&nFileSizeLow = file_size; }
};
class StatHash {
FileStat **hashTbl;
int hashNum;
int HashNum(int data_num);
public:
StatHash() {}
int RequireSize(int data_num) { return sizeof(FileStat *) * HashNum(data_num); }
BOOL Init(FileStat **data, int _data_num, void *tbl_buf);
FileStat *Search(void *upperName, DWORD hash_val);
};
struct DirStatTag {
int statNum;
int oldStatSize;
FileStat *statBuf;
FileStat **statIndex;
};
class FastCopy {
public:
enum Mode { DIFFCP_MODE, SYNCCP_MODE, MOVE_MODE, DELETE_MODE };
enum OverWrite { BY_NAME, BY_ATTR, BY_LASTEST, BY_CONTENTS, BY_ALWAYS };
enum FsType { FSTYPE_NONE, FSTYPE_NTFS, FSTYPE_FAT, FSTYPE_NETWORK };
enum Flags { CREATE_OPENERR_FILE=1, USE_OSCACHE_READ=2, USE_OSCACHE_WRITE=4, PRE_SEARCH=8, SAMEDIR_RENAME=0x10, SKIP_EMPTYDIR=0x20, FIX_SAMEDISK=0x40, FIX_DIFFDISK=0x80, AUTOSLOW_IOLIMIT=0x100, LISTING_ONLY=0x10000000 };
struct Info {
BOOL ignoreErr; // (I/ )
Mode mode; // (I/ )
OverWrite overWrite; // (I/ )
BOOL isPhysLock; // (I/ )
int flags; // (I/ )
int bufSize; // (I/ )
int maxOpenFiles; // (I/ )
int maxTransSize; // (I/ )
int maxAttrSize; // (I/ )
int maxDirSize; // (I/ )
int nbMinSizeNtfs; // (I/ ) FILE_FLAG_NO_BUFFERING 偱僆乕僾儞偡傞嵟彫僼傽僀儖僒僀僘
int nbMinSizeFat; // (I/ ) FILE_FLAG_NO_BUFFERING 偱僆乕僾儞偡傞嵟彫僼傽僀儖僒僀僘 (FAT梡)
TWin *notifyWnd; // (I/ )
UINT uNotifyMsg; // (I/ )
int lcid; // (I/ )
BOOL isRenameMode; // ( /O) ...乽暋惢偟傑偡乿僟僀傾儘僌僞僀僩儖梡忣曬乮巄掕乯
}; // 彨棃揑偵丄忣曬偑憹偊傟偽丄儊儞僶偐傜愗傝棧偟
enum Notify { END_NOTIFY, CONFIRM_NOTIFY, RENAME_NOTIFY };
struct Confirm {
enum Result { CANCEL_RESULT, IGNORE_RESULT, CONTINUE_RESULT };
const char *message; // (I/ )
BOOL allow_continue; // (I/ )
const void *path; // (I/ )
Result result; // ( /O)
};
// struct Rename {
// enum Result { CANCEL_RENAME, AUTO_RENAME, AUTOALL_RENAME, MANUAL_RENAME };
// char *message; // (I/ )
// void *path; // (I/ )
// void *rename; // (I/O)
// Result result; // ( /O)
// };
int maxStatSize; // max size of FileStat
int nbMinSize; // struct Info 嶲徠
protected:
enum Command { WRITE_FILE, WRITE_FILE_CONT, WRITE_ABORT, REMOVE_FILES, MKDIR, INTODIR, DELETE_FILES, RETURN_PARENT, REQ_EOF /*, READDIR*/ };
enum PutListOpt { PL_NORMAL, PL_DIRECTORY, PL_DELETE };
struct ReqHeader : public TListObj { // request header
Command command;
BYTE *buf;
int bufSize;
int reqSize;
FileStat stat; // 壜曄挿
};
struct ReqBuf {
BYTE *buf;
int bufSize;
ReqHeader *req;
int reqSize;
};
// 婎杮忣曬
DriveMng driveMng; // Drive 忣曬
Info info; // 僆僾僔儑儞巜掕摍
StatHash hash;
HashVal hashVal;
PathArray srcArray;
PathArray dstArray;
void *src; // src 僷僗奿擺梡
void *dst; // dst 僷僗奿擺梡
void *confirmDst; // 忋彂偒妋擣挷嵏梡
int srcBaseLen; // src 僷僗偺屌掕晹暘偺挿偝
int dstBaseLen; // dst 僷僗偺屌掕晹暘偺挿偝
int srcPrefixLen; // \\?\ or \\?\UNC\ 偺挿偝
int dstPrefixLen;
BOOL isExtendDir;
BOOL isMetaSrc;
// filter
BOOL isFilter;
enum { FILE_EXP, DIR_EXP, MAX_FTYPE_EXP };
enum { INC_EXP, EXC_EXP, MAX_KIND_EXP };
RegExp regExp[MAX_FTYPE_EXP][MAX_KIND_EXP];
// 僶僢僼傽
VBuf mainBuf; // Read/Write 梡 buffer
VBuf fileStatBuf; // src file stat 梡 buffer
VBuf dirStatBuf; // src dir stat 梡 buffer
VBuf dstStatBuf; // dst dir/file stat 梡 buffer
VBuf dstStatIdxBuf; // dstStatBuf 撪 entry 偺 index sort 梡
VBuf mkdirQueueBuf;
VBuf errBuf;
VBuf listBuf;
// 僙僋僞忣曬側偳
int srcSectorSize;
int dstSectorSize;
int sectorSize;
int maxTransSize;
FsType srcFsType;
FsType dstFsType;
BYTE src_root[MAX_PATH];
TotalTrans total; // 僼傽僀儖僐僺乕摑寁忣曬
DWORD startTick;
DWORD suspendTick;
DWORD autoSlow;
BOOL isAbort;
BOOL isSuspend;
BOOL isSameDrv;
BOOL isSameVol;
BOOL isRename;
BOOL readDestStatQueue;
BOOL readDestStatResult;
HANDLE hReadThread;
HANDLE hWriteThread;
class TReqList : public TList {
public:
TReqList(void) {}
ReqHeader *TopObj(void) { return (ReqHeader *)TList::TopObj(); }
ReqHeader *NextObj(ReqHeader *obj) { return (ReqHeader *)TList::NextObj(obj); }
};
HANDLE hRunMutex;
Condition cv;
CRITICAL_SECTION errCs;
CRITICAL_SECTION listCs;
TReqList readReqList;
TReqList writeReqList;
BYTE *usedOffset;
BYTE *freeOffset;
ReqHeader *writeReq;
_int64 nextFileID;
_int64 errFileID;
FileStat **openFiles;
int openFilesCnt;
static unsigned WINAPI ReadThread(void *fastCopyObj);
static unsigned WINAPI WriteThread(void *fastCopyObj);
static unsigned WINAPI DeleteThread(void *fastCopyObj);
BOOL ReadThreadCore(void);
BOOL DeleteThreadCore(void);
BOOL WriteThreadCore(void);
BOOL PreSearch(void);
BOOL PreSearchProc(void *path, int prefix_len, int dir_len);
BOOL ReadProc(int dir_len, BOOL confirm_dir=TRUE);
BOOL IsOverWriteFile(FileStat *srcStat, FileStat *dstStat);
int MakeRenameName(void *new_fname, int count, void *org_fname);
BOOL SetRenameCount(FileStat *stat);
BOOL FilterCheck(const void *path, const void *fname, DWORD attr);
BOOL ReadDirEntry(int dir_len, BOOL confirm_dir);
BOOL OpenFileProc(FileStat *stat, int dir_len);
BOOL ReadMultiFilesProc(void);
BOOL CloseMultiFilesProc(void);
BOOL ReadFileProc(FileStat *stat);
BOOL DeleteProc(void *path, int dir_len);
BOOL DeleteDirProc(void *path, int dir_len, void *fname, FileStat *stat);
BOOL DeleteFileProc(void *path, int dir_len, void *fname, FileStat *stat);
void ReadDestStatRequest(void);
BOOL WaitReadDestStat(void);
BOOL ReadDestStat(void);
BOOL MakeHashTable(void);
void FreeDestStat(void);
static int SortStatFunc(const void *stat1, const void *stat2);
BOOL ExecDirQueue(void);
BOOL WriteProc(int dir_len);
BOOL WriteFileProc(void);
BOOL ChangeToWriteModeCore(void);
BOOL ChangeToWriteMode(void);
BOOL AllocReqBuf(int req_size, _int64 _data_size, ReqBuf *buf);
BOOL PrepareReqBuf(int req_size, _int64 data_size, _int64 file_id, ReqBuf *buf);
BOOL SendRequest(Command command, ReqBuf *buf=NULL, FileStat *stat=NULL);
BOOL RecvRequest(void);
void WriteReqDone(void);
void SetErrFileID(_int64 file_id);
BOOL InitSrcPath(int idx);
BOOL InitDeletePath(int idx);
BOOL InitDstPath(void);
BOOL GetRootDir(const void *path, void *root_dir);
FsType GetFsType(const void *root_dir);
int GetSectorSize(const void *root_dir);
BOOL IsSameDrive(const void *root1, const void *root2);
int MakeUnlimitedPath(WCHAR *buf);
BOOL PutList(void *path, DWORD opt);
inline BOOL IsParentOrSelfDirs(void *name) { return *(BYTE *)name == '.' && (!strcmpV(name, DOT_V) || !strcmpV(name, DOTDOT_V)); }
int FdatToFileStat(WIN32_FIND_DATAW *fdat, FileStat *stat, BOOL is_usehash);
Confirm::Result ConfirmErr(const char *message, const void *path=NULL, BOOL allow_continue=TRUE);
BOOL ConvertExternalPath(const void *path, void *buf, int buf_len, BOOL to_ansi=FALSE);
public:
FastCopy(void);
virtual ~FastCopy();
BOOL RegisterInfo(const PathArray *_srcArray, const PathArray *_dstArray, Info *_info, const PathArray *_includeArray=NULL, const PathArray *_excludeArray=NULL);
BOOL TakeExclusivePriv(void);
BOOL Start(void);
BOOL End(void);
BOOL IsStarting(void) { return hReadThread || hWriteThread; }
BOOL Suspend(void);
BOOL Resume(void);
void Aborting(void) { isAbort = TRUE; WriteErrLog(" Aborted by User"); }
BOOL FastCopy::WriteErrLog(char *message, int len=-1);
BOOL IsAborting(void) { return isAbort; }
void SetAutoSlow(DWORD wait) { autoSlow = wait; }
DWORD GetAutoSlow() { return autoSlow; }
BOOL GetTransInfo(TransInfo *ti, BOOL fullInfo=TRUE);
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -