Skip to content

Commit 0663b62

Browse files
authored
Merge pull request #4 from KengoSawa2/1.2.7
1.2.7
2 parents 6208d92 + 363a88f commit 0663b62

File tree

6 files changed

+214
-41
lines changed

6 files changed

+214
-41
lines changed

fastcopy.cpp

+174-10
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ FastCopy::FastCopy()
123123
mainThread_pt = QThread::currentThreadId();
124124
//実行フェーズを「実行前」に変更
125125
phase = NORUNNING;
126+
127+
ltfs_prohibitlist << LTFS_PROHIBIT_SLASH;
128+
ltfs_prohibitlist << LTFS_PROHIBIT_COLON;
126129
}
127130

128131
FastCopy::~FastCopy()
@@ -1665,6 +1668,9 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
16651668
BOOL confirm_dir_local = confirm_dir || is_rename_local;
16661669

16671670
isRename = FALSE; // top level のみ効果を出す
1671+
//v125 LTFS,ODAの禁則文字置き換えワーク
1672+
char wk_filename[MAX_PATH];
1673+
unsigned long wk_hashVal;
16681674

16691675
if(waitTick) Wait(1);
16701676

@@ -1688,7 +1694,24 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
16881694
for(srcStat = (FileStat *)fileStatBuf.Buf(); srcStat < statEnd;
16891695
srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size)) {
16901696
if(confirm_dir_local){
1691-
dstStat = hash.Search(srcStat->upperName, srcStat->hashVal);
1697+
if(srcStat->isArchived){
1698+
strncpy(wk_filename,(char*)srcStat->upperName,strlen((char*)srcStat->upperName) + 1);
1699+
Convert_Prohibitchar_Archive(wk_filename,true);
1700+
//srcStatのhashVal再計算いるのう。。
1701+
wk_hashVal = MakeHash(wk_filename,strlen((char*)srcStat->upperName) + 1);
1702+
dstStat = hash.Search(wk_filename,wk_hashVal);
1703+
//かぶるファイル名がいるので強引に書き換える
1704+
if(dstStat){
1705+
//upperNameじゃダメだからcFileNameでやり直し
1706+
strncpy(wk_filename,(char*)srcStat->cFileName,strlen((char*)srcStat->cFileName) + 1);
1707+
Convert_Prohibitchar_Archive(wk_filename,true);
1708+
strncpy((char*)dstStat->cFileName,wk_filename,strlen(wk_filename) + 1);
1709+
dstStat->hashVal = wk_hashVal;
1710+
}
1711+
}
1712+
else{
1713+
dstStat = hash.Search(srcStat->upperName, srcStat->hashVal);
1714+
}
16921715
}
16931716
int path_len = 0;
16941717
srcStat->fileID = nextFileID++;
@@ -1711,7 +1734,12 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
17111734
|| (info.flags & FILE_REPARSE))) {
17121735
/* 比較モード */
17131736
if (isListingOnly && (info.flags & VERIFY_FILE)) {
1714-
strcpyV(MakeAddr(confirmDst, confirm_len), srcStat->cFileName);
1737+
if(srcStat->isArchived){
1738+
strcpyV(MakeAddr(confirmDst, confirm_len), dstStat->cFileName);
1739+
}
1740+
else{
1741+
strcpyV(MakeAddr(confirmDst, confirm_len), srcStat->cFileName);
1742+
}
17151743
strcpyV(MakeAddr(src, dir_len), srcStat->cFileName);
17161744
CheckSuspend();
17171745
if (!IsSameContents(srcStat, dstStat) && !isAbort) {
@@ -1762,6 +1790,25 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
17621790
for(srcStat = (FileStat *)(dirStatBuf.Buf() + curDirStatSize); srcStat < statEnd;
17631791
srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size)){
17641792

1793+
if(srcStat->isArchived){
1794+
strncpy(wk_filename,(char*)srcStat->upperName,strlen((char*)srcStat->upperName) + 1);
1795+
Convert_Prohibitchar_Archive(wk_filename,true);
1796+
//srcStatのhashVal再計算いるのう。。
1797+
wk_hashVal = MakeHash(wk_filename,strlen((char*)srcStat->upperName) + 1);
1798+
//qDebug() << "ReadProc(dir):" << wk_filename << "hashval=" << wk_hashVal;
1799+
dstStat = hash.Search(wk_filename,wk_hashVal);
1800+
1801+
//かぶるファイル名がいるので強引に書き換える
1802+
if(dstStat){
1803+
//upperNameじゃダメだからcFileNameでやり直し
1804+
strncpy(wk_filename,(char*)srcStat->cFileName,strlen((char*)srcStat->cFileName) + 1);
1805+
Convert_Prohibitchar_Archive(wk_filename,true);
1806+
strncpy((char*)dstStat->cFileName,wk_filename,strlen(wk_filename) + 1);
1807+
dstStat->hashVal = wk_hashVal;
1808+
}
1809+
}
1810+
//LTFSじゃない場合ね
1811+
17651812
if((dstStat = hash.Search(srcStat->upperName, srcStat->hashVal)) != NULL){
17661813
//srcStat->isCaseChanged = strcmpV(srcStat->cFileName, dstStat->cFileName);
17671814
if(is_rename_local){
@@ -1841,8 +1888,17 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
18411888
new_dir_len = dir_len + sprintfV(MakeAddr(src, dir_len), FMT_STR_V, srcStat->cFileName);
18421889
srcStat->fileID = nextFileID++;
18431890

1844-
if (confirm_dir && srcStat->isExists)
1845-
sprintfV(MakeAddr(confirmDst, confirm_len), FMT_CAT_ASTER_V, srcStat->cFileName);
1891+
if (confirm_dir && srcStat->isExists){
1892+
1893+
if(srcStat->isArchived){
1894+
strncpy(wk_filename,(char*)srcStat->cFileName,strlen((char*)srcStat->cFileName) + 1);
1895+
Convert_Prohibitchar_Archive(wk_filename,true);
1896+
sprintfV(MakeAddr(confirmDst, confirm_len), FMT_CAT_ASTER_V, wk_filename);
1897+
}
1898+
else{
1899+
sprintfV(MakeAddr(confirmDst, confirm_len), FMT_CAT_ASTER_V, srcStat->cFileName);
1900+
}
1901+
}
18461902

18471903
if (!isListingOnly) {
18481904
//ディレクトリへのシンボリックリンクskip確定してないか最初にチェック
@@ -2490,6 +2546,11 @@ BOOL FastCopy::ReadDirEntry(int dir_len, BOOL confirm_dir)
24902546
caseHash.clear();
24912547
}
24922548

2549+
if(info.flags_second & LTFS_MODE){
2550+
//禁則文字自動置換後のファイル名/フォルダ名格納ハッシュ
2551+
archiveHash.clear();
2552+
}
2553+
24932554
//リンクは実体としてコピー?
24942555
if(info.flags & DIR_REPARSE || info.flags & FILE_REPARSE){
24952556
wk_rtn = stat((const char*)src,&fdat);
@@ -2688,6 +2749,18 @@ BOOL FastCopy::ReadDirEntry(int dir_len, BOOL confirm_dir)
26882749
continue;
26892750
}
26902751
// ディレクトリ&ファイル情報の蓄積
2752+
if(info.flags_second & LTFS_MODE){
2753+
//エラー処理は中にお任せ
2754+
if(!Check_Prohibitchar_Archive(namelist[i]->d_name,wk_fullpath)){
2755+
if(IsDir(fdat.st_mode)){
2756+
total.errDirs++;
2757+
}
2758+
else{
2759+
total.errFiles++;
2760+
}
2761+
break;
2762+
}
2763+
}
26912764
if (IsDir(fdat.st_mode)) {
26922765
//ディレクトリやな
26932766
len = FdatToFileStat(&fdat, (FileStat *)(dirStatBuf.Buf() + dirStatBuf.UsedSize()),
@@ -3622,7 +3695,7 @@ BOOL FastCopy::ReadDstStat(void)
36223695
goto END;
36233696
}
36243697
dstStatIdx[num++] = dstStat;
3625-
len = FdatToFileStat(&fdat, (FileStat *)dstStat,TRUE,wk_filename);
3698+
len = FdatToFileStat(&fdat, (FileStat *)dstStat,TRUE,wk_filename,false);
36263699
dstStatBuf.AddUsedSize(len);
36273700
dstStatIdxBuf.AddUsedSize(sizeof(FileStat *));
36283701
if (dstStatBuf.RemainSize() <= maxStatSize && !dstStatBuf.Grow(MIN_ATTR_BUF)) {
@@ -3641,7 +3714,7 @@ BOOL FastCopy::ReadDstStat(void)
36413714
/* FindFirstFileはdir単体を指定すると中のファイルエントリを調査せずにdirエントリだけ返す謎仕様 */
36423715
/* FindFirstFileの挙動エミュレートのために、dir情報だけ登録してリターンしちゃうぞ */
36433716
dstStatIdx[num++] = dstStat;
3644-
len = FdatToFileStat(&fdat, (FileStat *)dstStat,TRUE,wk_filename);
3717+
len = FdatToFileStat(&fdat, (FileStat *)dstStat,TRUE,wk_filename,false);
36453718
dstStatBuf.AddUsedSize(len);
36463719
dstStatIdxBuf.AddUsedSize(sizeof(FileStat *));
36473720

@@ -3717,7 +3790,7 @@ BOOL FastCopy::ReadDstStat(void)
37173790
//事前調査対象として適切なファイルかどうか判定。
37183791
if(IsFile(fdat.st_mode) || IsDir(fdat.st_mode) || IsSlnk(fdat.st_mode)){
37193792
dstStatIdx[num++] = dstStat;
3720-
len = FdatToFileStat(&fdat, dstStat, TRUE,&namelist[i]->d_name[0]);
3793+
len = FdatToFileStat(&fdat, dstStat, TRUE,&namelist[i]->d_name[0],false);
37213794
dstStatBuf.AddUsedSize(len);
37223795

37233796
// 次の stat 用 buffer のセット
@@ -4396,6 +4469,13 @@ BOOL FastCopy::WriteProc(int dir_len)
43964469
total.linkFiles++;
43974470
}
43984471
else {
4472+
//v145 archive属性の場合はdstを自動置換
4473+
if(writeReq->stat.isArchived){
4474+
Convert_Prohibitchar_Archive((char*)dst,true);
4475+
if(info.flags_second & LTFS_MODE){
4476+
ConfirmErr((char*)GetLoadStrV(IDS_LTFS_REPLACE_WARN),(char*)dst,CEF_NOAPI);
4477+
}
4478+
}
43994479
//verifyモード時は、dstに存在しないファイルがあったらエラーとする
44004480
if(info.mode == VERIFY_MODE){
44014481
//エラー要因を確認
@@ -4563,6 +4643,13 @@ BOOL FastCopy::WriteDirProc(int dir_len)
45634643
if(mkdirQueueBuf.UsedSize()){
45644644
ExecDirQueue();
45654645
}
4646+
if(sv_stat.isArchived){
4647+
//dst中の禁則フォルダ名書き換える
4648+
Convert_Prohibitchar_Archive((char*)dst,true);
4649+
if(info.flags_second & LTFS_MODE){
4650+
ConfirmErr((char*)GetLoadStrV(IDS_LTFS_REPLACE_WARN),(char*)dst,CEF_NOAPI);
4651+
}
4652+
}
45664653
if(isListingOnly || !mkdir((const char*)dst, 0777)){
45674654
if(isListing && !is_reparse){
45684655
if(info.mode == VERIFY_MODE){
@@ -5431,6 +5518,14 @@ BOOL FastCopy::WriteFileProc(int dst_len,int parent_fh)
54315518
else {
54325519
//xattr延長の再帰でWriteFileProcが呼ばれてない?(最初のファイル実体writeか?)
54335520
if(fh == SYSCALL_ERR){
5521+
if(stat->isArchived){
5522+
if(Convert_Prohibitchar_Archive((char*)dst,true)){
5523+
//禁則文字列変換あった?
5524+
if(info.flags_second & LTFS_MODE){
5525+
ConfirmErr((char*)GetLoadStrV(IDS_LTFS_REPLACE_WARN),(char*)dst,CEF_NOAPI);
5526+
}
5527+
}
5528+
}
54345529
//書き込み対象のファイルハンドルをopen
54355530

54365531
//LTFSへの書き込みで禁則文字の":"や"/"を発見した場合は
@@ -5607,10 +5702,12 @@ BOOL FastCopy::WriteFileProc(int dst_len,int parent_fh)
56075702
memcpy(obj->path, dst, path_size);
56085703

56095704
BOOL is_empty_buf = digestList.RemainSize() <= digestList.MinMargin();
5610-
if (is_empty_buf || (info.flags & SERIAL_VERIFY_MOVE))
5705+
//v127
5706+
if (is_empty_buf || (info.flags & SERIAL_VERIFY_MOVE)){
56115707
phase = VERIFYING;
56125708
CheckDigests(is_empty_buf ? CD_WAIT : CD_NOWAIT); // empty なら wait
56135709
phase = COPYING;
5710+
}
56145711
}
56155712

56165713
if (command == WRITE_BACKUP_FILE) {
@@ -5826,6 +5923,65 @@ BOOL FastCopy::WriteFileBackupAclLocal(int fh,ReqHeader *writereq)
58265923
return(ret);
58275924
}
58285925

5926+
bool FastCopy::Convert_Prohibitchar_Archive(char *orgdst,bool req_replace){
5927+
5928+
QString dst_wk(orgdst);
5929+
bool isexists = false;
5930+
5931+
if(info.flags_second & LTFS_MODE){
5932+
for(int i=0; i < ltfs_prohibitlist.length();i++){
5933+
if(dst_wk.contains(ltfs_prohibitlist[i])){
5934+
isexists = true;
5935+
if(req_replace){
5936+
dst_wk.replace(ltfs_prohibitlist[i],LTFS_CONVERTED_AFTER);
5937+
}
5938+
}
5939+
}
5940+
}
5941+
if(req_replace && isexists){
5942+
//Warning出力
5943+
//ConfirmErr((char*)GetLoadStrV(IDS_LTFS_REPLACE_WARN),dst_wk.toLocal8Bit().data(),CEF_NOAPI);
5944+
strcpy(orgdst,dst_wk.toLocal8Bit().data());
5945+
}
5946+
return isexists;
5947+
}
5948+
5949+
bool FastCopy::Check_Prohibitchar_Archive(char* name,char* fullpath){
5950+
5951+
QString namewk(name);
5952+
bool ret = true; //true = 変換結果に問題なしorそも変換してない
5953+
//false = 変換結果がかぶるよ
5954+
5955+
if(info.flags_second & LTFS_MODE){
5956+
for(int i=0; i < ltfs_prohibitlist.length();i++){
5957+
if(namewk.contains(ltfs_prohibitlist[i])){
5958+
namewk.replace(ltfs_prohibitlist[i],LTFS_CONVERTED_AFTER);
5959+
}
5960+
}
5961+
}
5962+
//当該フォルダ内で変換結果後の名前または元々の_つきの名前が重複する?
5963+
if(archiveHash.value(namewk) == true){
5964+
5965+
//重複する場合は強制停止とする。理由は以下。
5966+
//scandir()ソートした結果で先にハッシュに入った方がコピー対象に送られると、
5967+
//dstの中身は"どっち"と比較されるのが正しかったのかは判断できない。
5968+
//安全のためにリネームを促して強制停止。
5969+
if(info.flags_second & LTFS_MODE){
5970+
ConfirmErr((char*)GetLoadStrV(IDS_LTFS_REPLACE_CHECK_ERR),
5971+
fullpath,CEF_NOAPI|CEF_STOP);
5972+
}
5973+
ret = false;
5974+
}
5975+
else{
5976+
//まだ誰もいないのでキーとして入れておこっと
5977+
archiveHash[namewk] = true;
5978+
ret = true;
5979+
}
5980+
//qDebug() << archiveHash;
5981+
// else 内部矛盾
5982+
return(ret);
5983+
}
5984+
58295985
BOOL FastCopy::ChangeToWriteModeCore(BOOL is_finish)
58305986
{
58315987
BOOL isResetRunMode = runMode == RUN_DIGESTREQ;
@@ -6301,7 +6457,7 @@ void FastCopy::signal_handler(int signum){
63016457
abort();
63026458
}
63036459

6304-
int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,char* f_name)
6460+
int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,char* f_name,bool isSrcstat)
63056461
{
63066462

63076463
stat->fileID = 0;
@@ -6335,7 +6491,7 @@ int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,
63356491
stat->hFile = SYSCALL_ERR; //file descripter
63366492
stat->lastError = 0;
63376493
stat->isExists = FALSE;
6338-
stat->isCaseChanged = FALSE;
6494+
stat->isArchived = FALSE;
63396495
stat->renameCount = 0;
63406496
stat->acl = NULL;
63416497
stat->aclSize = 0;
@@ -6367,6 +6523,14 @@ int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,
63676523
//4バイトを超えてぶっこんだ分も込みでサイズ長を設定
63686524
//FilestatのcFileNameまでのサイズ + CFileNameから始まる、ぶっこんだ分のサイズ
63696525
//が入ってるよ。ちなみにLL含むサイズなので、頭からLL分足せばnextレコードになるよ。
6526+
6527+
if(isSrcstat && (info.flags_second & LTFS_MODE)){
6528+
if(Convert_Prohibitchar_Archive((char*)stat->cFileName,false)){
6529+
//書き込み時には変換後名称
6530+
stat->isArchived = true;
6531+
}
6532+
}
6533+
63706534
stat->size = len + offsetof(FileStat, cFileName);
63716535
stat->minSize = ALIGN_SIZE(stat->size, 8);
63726536

fastcopy.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ struct FileStat {
192192
DWORD lastError; //最後に発生したerrno
193193
int renameCount;
194194
BOOL isExists;
195-
BOOL isCaseChanged;
195+
BOOL isArchived; // LTFS,ODAなどのアーカイブで禁則文字変換有無
196196
int size;
197197
int minSize; // upperName 分を含めない
198198
DWORD hashVal; // upperName の hash値
@@ -545,7 +545,8 @@ class FastCopy: public QObject{
545545
// バッファ
546546
VBuf mainBuf; // Read/Write 用 buffer
547547
VBuf fileStatBuf; // src file stat 用 buffer
548-
QHash<unsigned long,bool> caseHash; //case-sensitive->no case-sensitiveコピー判定用ハッシュ
548+
QHash <unsigned long,bool> caseHash; //case-sensitive->no case-sensitiveコピー判定用ハッシュ
549+
QHash <QString,bool> archiveHash;//LTFS,ODAモード自動置換後の重複チェック用ハッシュ
549550
VBuf dirStatBuf; // src dir stat 用 buffer
550551
VBuf dstStatBuf; // dst dir/file stat 用 buffer
551552
VBuf dstStatIdxBuf; // dstStatBuf 内 entry の index sort 用
@@ -632,6 +633,8 @@ class FastCopy: public QObject{
632633
DataList::Head *moveFinPtr; // 書き込み終了ID位置
633634
TLinkHashTbl hardLinkList; // ハードリンク用リスト
634635

636+
QStringList ltfs_prohibitlist;
637+
635638
BOOL ReadThreadCore(void);
636639
BOOL DeleteThreadCore(void);
637640
BOOL WriteThreadCore(void);
@@ -738,12 +741,14 @@ class FastCopy: public QObject{
738741
return *(char *)name == '.' && (*(char *)name)+1 != '\0';
739742
}
740743

741-
int FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,char *f_name);
744+
int FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,char *f_name,bool isSrcstat=true);
742745
Confirm::Result ConfirmErr(const char *message, const void *path=NULL, DWORD flags=0,const char *count_message=NULL,char *count_message2=NULL);
743746
BOOL ConvertExternalPath(const void *path, void *buf, int buf_len);
744747
void apath_to_path_file_a(char *path,char *dir,char *file);
745748
BOOL Wait(DWORD tick=0);
746749
BOOL WriteFileBackupAclLocal(int fh,ReqHeader *writereq);
750+
bool Convert_Prohibitchar_Archive(char *orgdst,BOOL req_replace);
751+
bool Check_Prohibitchar_Archive(char *name,char *fullpath);
747752
};
748753

749754
//RapidCopyで実行される各種スレッドクラス

0 commit comments

Comments
 (0)